aboutsummaryrefslogtreecommitdiff
path: root/doc/chapters/exploringrequests.inc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/chapters/exploringrequests.inc')
-rw-r--r--doc/chapters/exploringrequests.inc103
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 @@
1This chapter will deal with the information which the client sends to the
2server at every request. We are going to examine the most useful fields of such an request
3and print them out in a readable manner. This could be useful for logging facilities.
4
5The starting point is the @emph{hellobrowser} program with the former response removed.
6
7This time, we just want to collect information in the callback function, thus we will
8just return MHD_NO after we have probed the request. This way, the connection is closed
9without much ado by the server.
10
11@verbatim
12int 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
21The ellipsis marks the position where the following instructions shall be inserted.
22
23
24We begin with the most obvious information available to the server, the request line. You should
25already have noted that a request consists of a command (or "method") and a URI (e.g. a filename).
26It also contains a string for the version of the protocol which can be found in @code{version}.
27To call it a "new request" is justified because we return only @code{MHD_NO}, thus ensuring the
28function will not be called again for this connection.
29@verbatim
30printf ("New request %s for %s using version %s\n", method, url, version);
31@end verbatim
32@noindent
33
34The rest of the information is a bit more hidden. Nevertheless, there is lot of it sent from common
35Internet browsers. It is stored in "key-name" pairs and we want to list what we find in the header.
36As there is no mandatory set of keys a client has to send, each key--name pair is printed out one by
37one until there are no more left. We do this by writing a separate function which will be called for
38each pair just like the above function is called for each HTTP request.
39It can then print out the content of this pair.
40@verbatim
41int 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
49To start the iteration process that calls our new function for every key, the line
50@verbatim
51MHD_get_connection_values (connection, MHD_HEADER_KIND, print_out_key, NULL);
52@end verbatim
53@noindent
54needs to be inserted in the connection callback function too. The second parameter tells the function
55that we are only interested in keys from the general HTTP header of the request. Our iterating
56function @code{PrintOutKey} does not rely on any additional information to fulfill its duties
57so the last parameter can be NULL.
58
59All in all, this constitutes the complete @code{logger.c} program for this chapter which can be
60found in the @code{examples} section.
61
62Connecting with any modern Internet browser should yield a handful of keys. You should try to
63interpret them with the aid of @emph{RFC 2616}.
64Especially worth mentioning is the host key which is often used to serve several different websites
65hosted under one single IP address but reachable by different domain names.
66
67@heading Conclusion
68The introduced capabilities to itemize the content of a simple GET request---especially the
69URI---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
71recommended as the GET method (including its header data) is by convention considered a "SAFE"
72operation, which should not change the server's state in a significant way, but temporally actions
73like searching for a passed string is fine.
74
75Of course, no transmission can occur while the return value is still set to @code{MHD_NO} in the
76callback function.
77
78@heading Exercises
79@itemize @bullet
80@item
81By 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
83containing a link to @code{/another.html} page which is also to be created "on the fly" in case of
84being requested. If neither of these two pages are requested, @code{MHD_HTTP_NOT_FOUND} shall be
85returned accompanied by an informative message.
86
87@item
88A very interesting information has still been ignored by our logger---the client's IP address.
89Implement a callback function
90@verbatim
91int on_client_connect (void *cls,
92 const struct sockaddr *addr,socklen_t addrlen)
93@end verbatim
94@noindent
95that 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
97substructures and is @emph{not} the variable this function expects.
98Make 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
100to 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