diff options
Diffstat (limited to 'doc/chapters/exploringrequests.inc')
-rw-r--r-- | doc/chapters/exploringrequests.inc | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/doc/chapters/exploringrequests.inc b/doc/chapters/exploringrequests.inc new file mode 100644 index 00000000..11a169dd --- /dev/null +++ b/doc/chapters/exploringrequests.inc | |||
@@ -0,0 +1,103 @@ | |||
1 | This chapter will deal with the information which the client sends to the | ||
2 | server at every request. We are going to examine the most useful fields of such an request | ||
3 | and print them out in a readable manner. This could be useful for logging facilities. | ||
4 | |||
5 | The starting point is the @emph{hellobrowser} program with the former response removed. | ||
6 | |||
7 | This time, we just want to collect information in the callback function, thus we will | ||
8 | just return MHD_NO after we have probed the request. This way, the connection is closed | ||
9 | without much ado by the server. | ||
10 | |||
11 | @verbatim | ||
12 | int answer_to_connection (void *cls, struct MHD_Connection *connection, const char *url, | ||
13 | const char *method, const char *version, const char *upload_data, | ||
14 | unsigned int *upload_data_size, void **con_cls) | ||
15 | { | ||
16 | ... | ||
17 | return MHD_NO; | ||
18 | } | ||
19 | @end verbatim | ||
20 | @noindent | ||
21 | The ellipsis marks the position where the following instructions shall be inserted. | ||
22 | |||
23 | |||
24 | We begin with the most obvious information available to the server, the request line. You should | ||
25 | already have noted that a request consists of a command (or "method") and a URI (e.g. a filename). | ||
26 | It also contains a string for the version of the protocol which can be found in @code{version}. | ||
27 | To call it a "new request" is justified because we return only @code{MHD_NO}, thus ensuring the | ||
28 | function will not be called again for this connection. | ||
29 | @verbatim | ||
30 | printf ("New request %s for %s using version %s\n", method, url, version); | ||
31 | @end verbatim | ||
32 | @noindent | ||
33 | |||
34 | The rest of the information is a bit more hidden. Nevertheless, there is lot of it sent from common | ||
35 | Internet browsers. It is stored in "key-name" pairs and we want to list what we find in the header. | ||
36 | As there is no mandatory set of keys a client has to send, each key--name pair is printed out one by | ||
37 | one until there are no more left. We do this by writing a separate function which will be called for | ||
38 | each pair just like the above function is called for each HTTP request. | ||
39 | It can then print out the content of this pair. | ||
40 | @verbatim | ||
41 | int print_out_key (void *cls, enum MHD_ValueKind kind, const char *key, const char *value) | ||
42 | { | ||
43 | printf ("%s = %s\n", key, value); | ||
44 | return MHD_YES; | ||
45 | } | ||
46 | @end verbatim | ||
47 | @noindent | ||
48 | |||
49 | To start the iteration process that calls our new function for every key, the line | ||
50 | @verbatim | ||
51 | MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key, NULL); | ||
52 | @end verbatim | ||
53 | @noindent | ||
54 | needs to be inserted in the connection callback function too. The second parameter tells the function | ||
55 | that we are only interested in keys from the general HTTP header of the request. Our iterating | ||
56 | function @code{PrintOutKey} does not rely on any additional information to fulfill its duties | ||
57 | so the last parameter can be NULL. | ||
58 | |||
59 | All in all, this constitutes the complete @code{logger.c} program for this chapter which can be | ||
60 | found in the @code{examples} section. | ||
61 | |||
62 | Connecting with any modern Internet browser should yield a handful of keys. You should try to | ||
63 | interpret them with the aid of @emph{RFC 2616}. | ||
64 | Especially worth mentioning is the host key which is often used to serve several different websites | ||
65 | hosted under one single IP address but reachable by different domain names. | ||
66 | |||
67 | @heading Conclusion | ||
68 | The introduced capabilities to itemize the content of a simple GET request---especially the | ||
69 | URI---should already allow the server to satisfy clients' requests for small specific resources | ||
70 | (e.g. files) or even induce alteration of how the server operates. However, the latter is not | ||
71 | recommended as the GET method (including its header data) is by convention considered a "SAFE" | ||
72 | operation, which should not change the server's state in a significant way, but temporally actions | ||
73 | like searching for a passed string is fine. | ||
74 | |||
75 | Of course, no transmission can occur while the return value is still set to @code{MHD_NO} in the | ||
76 | callback function. | ||
77 | |||
78 | @heading Exercises | ||
79 | @itemize @bullet | ||
80 | @item | ||
81 | By parsing the @code{url} string and delivering responses accordingly, implement a small server for | ||
82 | "virtual" files. When asked for @code{/index.htm@{l@}}, let the response consist of a HTML page | ||
83 | containing a link to @code{/another.html} page which is also to be created "on the fly" in case of | ||
84 | being requested. If neither of these two pages are requested, @code{MHD_HTTP_NOT_FOUND} shall be | ||
85 | returned accompanied by an informative message. | ||
86 | |||
87 | @item | ||
88 | A very interesting information has still been ignored by our logger---the client's IP address. | ||
89 | Implement a callback function | ||
90 | @verbatim | ||
91 | int on_client_connect (void *cls, | ||
92 | const struct sockaddr *addr,socklen_t addrlen) | ||
93 | @end verbatim | ||
94 | @noindent | ||
95 | that prints out the IP address in an appropriate format. You might want to use the posix function | ||
96 | @code{inet_ntoa} but bear in mind that @code{addr} is actually just a structure containing other | ||
97 | substructures and is @emph{not} the variable this function expects. | ||
98 | Make sure to return @code{MHD_YES} so that the library knows the client is allowed to connect | ||
99 | (and to request). If one wanted to limit access basing on IP addresses, this would be the place | ||
100 | to do it. The address of your function will then be passed as the third parameter of the | ||
101 | @code{MHD_start_daemon} call. | ||
102 | |||
103 | @end itemize | ||