aboutsummaryrefslogtreecommitdiff
path: root/doc/chapters
diff options
context:
space:
mode:
Diffstat (limited to 'doc/chapters')
-rw-r--r--doc/chapters/basicauthentication.inc207
-rw-r--r--doc/chapters/bibliography.inc30
-rw-r--r--doc/chapters/exploringrequests.inc103
-rw-r--r--doc/chapters/hellobrowser.inc203
-rw-r--r--doc/chapters/introduction.inc17
-rw-r--r--doc/chapters/processingpost.inc231
-rw-r--r--doc/chapters/responseheaders.inc177
7 files changed, 968 insertions, 0 deletions
diff --git a/doc/chapters/basicauthentication.inc b/doc/chapters/basicauthentication.inc
new file mode 100644
index 00000000..8e7f4c60
--- /dev/null
+++ b/doc/chapters/basicauthentication.inc
@@ -0,0 +1,207 @@
1With the small exception of IP address based access control,
2requests from all connecting clients where served equally until now.
3This chapter discusses a first method of client's authentication and
4its limits.
5
6A very simple approach feasible with the means already discussed would
7be to expect the password in the @emph{URI} string before granting access to
8the secured areas. The password could be separated from the actual resource identifier
9by a certain character, thus the request line might look like
10@verbatim
11GET /picture.png?mypassword
12@end verbatim
13@noindent
14
15In a situation, where the client is customized enough and the connection occurs
16through secured lines (e.g., a embedded device directly attached to another via wire),
17this can be a reasonable choice.
18
19But when it is assumed that the user connecting does so with an ordinary Internet browser,
20this implementation brings some problems about. For example, the URI including the password
21stays in the address field or at least in the history of the browser for anybody near enough to see.
22It will also be inconvenient to add the password manually to any new URI when the browser does
23not know how to compose this automatically.
24
25At least the convenience issue can be addressed by employing the simplest built-in password
26facilities of HTTP compliant browsers, hence we want to start there. It will however turn out
27to have still severe weaknesses in terms of security which need consideration.
28
29Before we will start implementing @emph{Basic Authentication} as described in @emph{RFC 2617},
30we should finally abandon the bad practice of responding every request the first time our callback
31is called for a given connection. This is becoming more important now because the client and
32the server will have to talk in a more bi-directional way than before to
33
34But how can we tell whether the callback has been called before for the particular connection?
35Initially, the pointer this parameter references is set by @emph{MHD} in the callback. But it will
36also be "remembered" on the next call (for the same connection).
37Thus, we will generate no response until the parameter is non-null---implying the callback was
38called before at least once. We do not need to share information between different calls of the callback,
39so we can set the parameter to any adress that is assured to be not null. The pointer to the
40@code{connection} structure will be pointing to a legal adress, so we take this.
41
42Not even the headers will be looked at on the first iteration.
43
44@verbatim
45int answer_to_connection (void *cls, struct MHD_Connection *connection,
46 const char *url, const char *method, const char *version,
47 const char *upload_data, unsigned int *upload_data_size,
48 void **con_cls)
49{
50 if (0 != strcmp(method, "GET")) return MHD_NO;
51 if (NULL == *con_cls) {*con_cls = connection; return MHD_YES;}
52
53 ...
54 /* else respond accordingly */
55 ...
56}
57@end verbatim
58@noindent
59
60Note how we lop off the connection on the first condition, but return asking for more on
61the other one with @code{MHD_YES}.
62With the framework improved, we can proceed to implement the actual authentication process.
63
64@heading Request for authentication
65
66Let us assume we had only files not intended to be handed out without the correct username/password,
67so every "GET" request will be challenged.
68@emph{RFC 2617} describes how the server shall ask for authentication by adding a
69@emph{WWW-Authenticate} response header with the name of the @emph{realm} protected.
70
71We let an extra function function do this.
72@verbatim
73int ask_for_authentication (struct MHD_Connection *connection, const char *realm)
74{
75 int ret;
76 struct MHD_Response *response;
77 char *headervalue;
78 const char *strbase = "Basic realm=";
79
80 response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
81 if (!response) return MHD_NO;
82
83 headervalue = malloc (strlen (strbase) + strlen (realm) + 1);
84 if (!headervalue) return MHD_NO;
85
86 strcpy (headervalue, strbase);
87 strcat (headervalue, realm);
88
89 ret = MHD_add_response_header (response, "WWW-Authenticate", headervalue);
90 free (headervalue);
91 if (!ret) {MHD_destroy_response (response); return MHD_NO;}
92
93 ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
94
95 MHD_destroy_response (response);
96
97 return ret;
98}
99@end verbatim
100@noindent
101
102@code{#define} the realm name according to your own taste, e.g. "Maintenance" or "Area51" but
103it will need to have extra quotes.
104
105But the client may send the authentication right away, so it would be wrong to ask for
106it without checking the request's header--where the authentication is expected to be found.
107
108@heading Authentication in detail
109Checking @emph{RFC 2617} again, we find that the client will pack the username and password, by
110whatever means he might have obtained them, in a line separated by a colon---and then encodes
111them to @emph{Base64}. The actual implementation of this encoding are not within the scope of
112this tutorial although a working function is included in the complete source file of the example.
113
114An unencoded word describing the authentication method (here "Basic") will precede the code
115and the resulting line is the value of a request header of the type "Authorization".
116
117This header line thus is of interest to the function checking a connection for a given username/password:
118@verbatim
119int is_authenticated (struct MHD_Connection *connection,
120 const char *username, const char *password)
121{
122 const char *headervalue;
123 ...
124
125 headervalue = MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
126 "Authorization");
127 if (NULL == headervalue) return 0;
128@end verbatim
129@noindent
130
131where, firstly, the authentication method will be checked.
132@verbatim
133const char *strbase = "Basic ";
134...
135if (0 != strncmp (headervalue, strbase, strlen (strbase))) return 0;
136@end verbatim
137@noindent
138
139Of course, we could decode the passed credentials in the next step and compare them directly to
140the given strings. But as this would involve string parsing, which is more complicated then string
141composing, it is done the other way around---the clear text credentials will be encoded to @emph{Base64}
142and then compared against the headerline. The authentication method string will be left out here as
143it has been checked already at this point.
144@verbatim
145 char *expected_b64, *expected;
146 int authenticated;
147
148 ...
149 strcpy (expected, username);
150 strcat (expected, ":");
151 strcat (expected, password);
152
153 expected_b64 = string_to_base64 (expected);
154 if (NULL == expected_b64) return 0;
155
156 strcpy (expected, strbase);
157 authenticated = (strcmp (headervalue + strlen (strbase), expected_b64) == 0);
158
159 free (expected_b64);
160
161 return authenticated;
162}
163@end verbatim
164@noindent
165
166These two functions---together with a response function in case of positive authentication doing little
167new---allow the rest of the callback function to be rather short.
168@verbatim
169 if (!is_authenticated (connection, USER, PASSWORD))
170 return ask_for_authentication (connection, REALM);
171
172 return secret_page (connection);
173}
174@end verbatim
175@noindent
176
177See the @code{examples} directory for the complete example file.
178
179@heading Remarks
180For a proper server, the conditional statements leading to a return of @code{MHD_NO} should yield a
181response with a more precise status code instead of silently closing the connection. For example,
182failures of memory allocation are best reported as @emph{internal server error} and unexpected
183authentication methods as @emph{400 bad request}.
184
185@heading Exercises
186@itemize @bullet
187@item
188Make the server respond to wrong credentials (but else correct requests) with the recommended
189@emph{401 unauthorized} status code. If the client still does not authenticate correctly within the
190same connection, close it and store the client's IP address for a certain time. (It is OK to check for
191expiration not until the main thread wakes up again on the next connection.) If the client fails
192authenticating three times during this period, add it to another list whose entries the
193@code{AcceptPolicyCallback} function denies connection (temporally).
194
195@item
196With the network utility @emph{netcat} connect and log the response of a "GET" request as you
197did in the exercise of the first example, this time to a file. Now stop the server and let @emph{netcat}
198listen on the same port the server used to listen on and have it fake being the proper server by giving
199the file's content as the response (e.g. @code{cat log | nc -l -p 8888}). Pretending to think your were
200connecting to the actual server, browse to the eavesdropper and give the correct credentials.
201
202Copy and paste the encoded string you see in netcat's output to some of the Base64 decode tools available online
203and see how both the user's name and password could be completely restored.
204
205@end itemize
206
207
diff --git a/doc/chapters/bibliography.inc b/doc/chapters/bibliography.inc
new file mode 100644
index 00000000..547028f5
--- /dev/null
+++ b/doc/chapters/bibliography.inc
@@ -0,0 +1,30 @@
1@itemize @bullet
2@heading API reference
3@item
4The @emph{GNU libmicrohttpd} manual by Christian Grothoff 2008
5@uref{http://gnunet.org/libmicrohttpd/microhttpd.html}
6
7@heading Requests for comments
8All referenced RFCs can be found on the website of @emph{The Internet Engineering Task Force}
9@uref{http://www.ietf.org/}
10
11@item
12@emph{RFC 2616}: Fielding, R., Gettys, J., Mogul, J., Frystyk, H., and T. Berners-Lee,
13"Hypertext Transfer Protocol -- HTTP/1.1", RFC 2016, January 1997.
14
15@item
16@emph{RFC 2617}: Franks, J., Hallam-Baker, P., Hostetler, J., Lawrence, S., Leach, P.,
17Luotonen, A., and L. Stewart, "HTTP Authentication: Basic and Digest Access Authentication", RFC 2617, June 1999.
18
19
20@heading Recommended readings
21@item
22A well--structured @emph{HTML} reference can be found on
23@uref{http://www.echoecho.com/html.htm}
24
25For those readers understanding German or French, there is an excellent document both for learning
26@emph{HTML} and for reference, whose English version unfortunately has been discontinued.
27@uref{http://de.selfhtml.org/} and @uref{http://fr.selfhtml.org/}
28
29
30@end itemize
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
diff --git a/doc/chapters/hellobrowser.inc b/doc/chapters/hellobrowser.inc
new file mode 100644
index 00000000..0513a674
--- /dev/null
+++ b/doc/chapters/hellobrowser.inc
@@ -0,0 +1,203 @@
1The most basic task for a HTTP server is to deliver a static text message to any client connecting to it.
2Given that this is also easy to implement, it is an excellent problem to start with.
3
4For now, the particular filename the client asks for shall have no effect on the message that will
5be returned. In addition, the server shall end the connection after the message has been sent so that
6the client will know there is nothing more to expect.
7
8The C program @code{hellobrowser.c}, which is to be found in the examples section, does just that.
9If you are very eager, you can compile and start it right away but it is advisable to type the
10lines in by yourself as they will be discussed and explained in detail.
11
12After the unexciting includes and the definition of the port which our server should listen on
13@verbatim
14#include <microhttpd.h>
15#include <string.h>
16#include <stdlib.h>
17#include <stdio.h>
18@end verbatim
19@noindent
20the desired behaviour of our server when HTTP request arrive have to be implemented. We already have
21agreed that it should not care about the particular details of the request, such as who is requesting
22what. The server will respond merely with the same small HTML page to every request.
23
24The function we are going to write now will be called by @emph{GNU libmicrohttpd} every time an
25appropriate request comes in. While the name of this callback function is arbitrary, its parameter
26list has to follow a certain layout. So please, ignore the lot of parameters for now, they will be
27explained at the point they are needed. We have to use only one of them,
28@code{struct MHD_Connection *connection}, for the minimalistic functionality we want to archive at the moment.
29
30This parameter is set by the @emph{libmicrohttpd} daemon and holds the necessary information to
31relate the call with a certain connection. Keep in mind that a server might have to satisfy hundreds
32of concurrent connections and we have to make sure that the correct data is sent to the destined
33client. Therefore, this variable is a means to refer to a particular connection if we ask the
34daemon to sent the reply.
35
36Talking about the reply, it is defined as a string right after the function header
37@verbatim
38int answer_to_connection (void *cls, struct MHD_Connection *connection, const char *url,
39 const char *method, const char *version, const char *upload_data,
40 unsigned int *upload_data_size, void **con_cls)
41{
42 const char *page = "<html><body>Hello, browser!</body></html>";
43@end verbatim
44@noindent
45HTTP is a rather strict protocol and the client would certainly consider it "inappropriate" if we
46just sent the answer string "as is". Instead, it has to be wrapped in certain layers, called headers,
47of additional information. Luckily, most of the work in this area is done by the library for us---we
48just have to ask. Our reply string packed in the necessary layers will be called a "response".
49To obtain such a response we hand our data (the reply--string) and its size over to the
50@code{MHD_create_response_from_data} function. The last two parameters basically tell @emph{MHD}
51that we do not want it to dispose the message data for us when it has been sent and there also needs
52no internal copy to be done because the @emph{constant} string won't change anyway.
53
54@verbatim
55 struct MHD_Response *response;
56 int ret;
57
58 response = MHD_create_response_from_data (strlen (page),
59 (void*) page, MHD_NO, MHD_NO);
60@end verbatim
61@noindent
62Now that the the response has been laced up, it is ready for delivery and can be queued for sending.
63This is done by passing it to another @emph{GNU libmicrohttpd} function. As all our work was done in
64the scope of one function, the recipient is without doubt the one associated with the
65local variable @code{connection} and consequently this variable is given to the queue function.
66Every HTTP response is accompanied by a status code, here "OK", so that the client knows
67this response is the intended result of his request and not due to some error or malfunction.
68
69Finally, the packet is destroyed and the return value from the queue returned,
70already being set at this point to either MHD_YES or MHD_NO in case of success or failure.
71
72@verbatim
73 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
74 MHD_destroy_response (response);
75
76 return ret;
77}
78@end verbatim
79@noindent
80With the primary task of our server implemented, we can start the actual server daemon which will listen
81on @code{PORT} for connections. This is done in the main function.
82@verbatim
83int main ()
84{
85 struct MHD_Daemon *daemon;
86
87 daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
88 &answer_to_connection, NULL, MHD_OPTION_END);
89 if (NULL == daemon) return 1;
90@end verbatim
91@noindent
92The first parameter is one of three possible modes of operation. Here we want the daemon to run in
93a separate thread and to manage all incoming connections in the same thread. This means that while
94producing the response for one connection, the other connections will be put on hold. In this
95chapter, where the reply is already known and therefore the request is served quickly, this poses no problem.
96
97We will allow all clients to connect regardless of their name or location, therefore we do not check
98them on connection and set the forth and fifth parameter to NULL.
99
100Parameter six is the address of the function we want to be called whenever a new connection has been
101established. Our @code{AnswerToConnection} knows best what the client wants and needs no additional
102information (which could be passed via the next parameter) so the next parameter is NULL. Likewise,
103we do not need to pass extra options to the daemon so we just write the MHD_OPTION_END as the last parameter.
104
105As the server daemon runs in the background in its own thread, the execution flow in our main
106function will contine right after the call. Because of this, we must delay the execution flow in the
107main thread or else the program will terminate prematurely. We let it pause in a processing-time
108friendly manner by waiting for the enter key to be pressed. In the end, we stop the daemon so it can
109do its cleanup tasks.
110@verbatim
111 getchar ();
112
113 MHD_stop_daemon (daemon);
114 return 0;
115}
116
117@end verbatim
118@noindent
119The first example is now complete.
120
121Compile it with
122@verbatim
123cc hellobrowser.c -o hellobrowser -I$PATH_TO_LIBMHD_INCLUDES
124 -L$PATH_TO_LIBMHD_INCLUDES -static -lmicrohttpd -pthread
125@end verbatim
126with the two paths set accordingly and run it.
127
128Now open your favorite Internet browser and go to the address @code{localhost:8888}, provided that
129is the port you chose. If everything works as expected, the browser will present the message of the
130static HTML page it got from our minimal server.
131
132@heading Remarks
133To keep this first example as small as possible, some drastic shortcuts were taken and are to be
134discussed now.
135
136Firstly, there is no distinction made between the kinds of requests a client could send. We implied
137that the client sends a GET request, that means, that he actually asked for some data. Even when
138it is not intended to accept POST requests, a good server should at least recognize that this
139request does not constitute a legal request and answer with an error code. This can be easily
140implemented by checking if the parameter @code{method} equals the string "GET" and returning a
141@code{MHD_NO} if not so.
142
143Secondly, the above practice of queuing a response upon the first call of the callback function
144brings with it some limitations. This is because the content of the message body will not be
145received if a response is queued in the first iteration. Furthermore, the connection will be closed
146right after the response has been transferred then.
147
148Both of these issues you will find addressed in the official @code{minimal_example.c} residing in
149the @code{src/examples} directory of the @emph{GNU libmicrohttpd} package. The source code of this
150program should look very familiar to you by now and easy to understand.
151
152For our example, the @code{must_copy} and @code{must_free} parameter at the response construction
153function could be set to @code{MHD_NO}. In the usual case, responses cannot be sent immediately
154after being queued. For example, there might be other data on the system that needs to be sent with
155a higher priority. Nevertheless, the queue function will return successfully---raising the problem
156that the data we have pointed to may be invalid by the time it is about being sent. This is not an
157issue here because we can expect the @code{page} string, which is a constant @emph{string literal}
158here, to be static. That means it will be present and unchanged for as long as the program runs.
159For dynamic data, one could choose to either have @emph{MHD} free the memory @code{page} points
160to itself when it is not longer needed or, alternatively, have the library to make and manage
161its own copy of it.
162
163@heading Exercises
164@itemize @bullet
165@item
166While the server is running, use a program like telnet or netcat to connect to it. Try to form a
167valid HTTP1.1 request yourself like
168@verbatim
169GET /dontcare HTTP1.1
170Host: itsme
171<enter>
172@end verbatim
173@noindent
174and see what the server returns to you.
175
176
177@item
178Also, try other requests, like POST, and see how our server does not mind and why.
179How far in malforming a request can you go before the builtin functionality of @emph{MHD} intervenes
180and an altered response is sent? Make sure you read about the status codes in the @emph{RFC}.
181
182
183@item
184Add the option @code{MHD_USE_PEDANTIC_CHECKS} to the start function of the daemon in @code{main}.
185Mind the special format of the parameter list here which is described in the manual. How indulgent
186is the server now to your input?
187
188
189@item
190Let the main function take a string as the first command line argument and pass @code{argv[1]} to
191the @code{MHD_start_daemon} function as the sixth parameter. The address of this string will be
192passed to the callback function via the @code{cls} variable. Decorate the text given at the command
193line when the server is started with proper HTML tags and send it as the response instead of the
194former static string.
195
196
197@item
198@emph{Demanding:} Write a separate function returning a string containing some useful information,
199for example, the time. Pass the function's address as the sixth parameter and evaluate this function
200on every request anew in @code{AnswerToConnection}. Remember to free the memory of the string
201every time after satisfying the request.
202
203@end itemize
diff --git a/doc/chapters/introduction.inc b/doc/chapters/introduction.inc
new file mode 100644
index 00000000..722d0fb7
--- /dev/null
+++ b/doc/chapters/introduction.inc
@@ -0,0 +1,17 @@
1This tutorial is for developers who want to learn how they can add HTTP serving
2capabilities to their applications with the @emph{GNU libmicrohttpd} library,
3abbreviated @emph{MHD}. The reader will learn how to
4implement basic HTTP functions from simple executable
5sample programs that implement various features.
6
7The text is supposed to be a supplement to the API reference manual of
8@emph{GNU libmicrohttpd} and for that reason does not explain many of the parameters.
9Therefore, the reader should always consult the manual to find the exact meaning
10of the functions used in the tutorial. Furthermore, the reader is
11encouraged to study the relevant @emph{RFCs}, which document the HTTP standard.
12
13@emph{GNU libmicrohttpd} is assumed to be already installed. This tutorial
14is written for version @value{VERSION}. At the time being,
15this tutorial has only been tested on @emph{GNU/Linux} machines even though
16efforts were made not to rely on anything that would prevent the samples from being
17built on similar systems.
diff --git a/doc/chapters/processingpost.inc b/doc/chapters/processingpost.inc
new file mode 100644
index 00000000..0677c7e8
--- /dev/null
+++ b/doc/chapters/processingpost.inc
@@ -0,0 +1,231 @@
1The previous chapters already have demonstrated a variety of possibilities to send information
2to the HTTP server, but it is not recommended that the @emph{GET} method is used to alter the way
3the server operates. To induce changes on the server, the @emph{POST} method is preferred over
4and is much more powerful than @emph{GET} and will be introduced in this chapter.
5
6We are going to write an application that asks for the visitor's name and, after the user has posted it,
7composes an individual response text. Even though it was not mandatory to use the @emph{post} method here,
8as there is no permanent change caused by the post, it is an illustrative example on how to share data
9between different functions for the same connection. Furthermore, the reader should be able to extend
10it easily.
11
12@heading GET request
13When the first @emph{GET} request arrives, the server shall respond with a HTML page containing an
14edit field for the name.
15
16@verbatim
17const char* askpage = "<html><body>\
18 What's your name, Sir?<br>\
19 <form action=\"/namepost\" method=\"post\">\
20 <input name=\"name\" type=\"text\"\
21 <input type=\"submit\" value=\" Send \"></form>\
22 </body></html>";
23@end verbatim
24@noindent
25
26The @code{action} entry is the @emph{URI} to be called by the browser when posting, and the
27@code{name} will be used later to be sure it is the editbox's content that has been posted.
28
29We also prepare the answer page, where the name is to be filled in later, and an error page
30as the response for anything but proper @emph{GET} and @emph{POST} requests:
31
32@verbatim
33const char* greatingpage="<html><body><h1>Welcome, %s!</center></h1></body></html>";
34
35const char* errorpage="<html><body>This doesn't seem to be right.</body></html>";
36@end verbatim
37@noindent
38
39Whenever we need to send a page, we use an extra function
40@code{int SendPage(struct MHD_Connection *connection, const char* page)}
41for this, which does not contain anything new and whose implementation is therefore left out here.
42
43
44@heading POST request
45Posted data can be of arbitrary and considerable size; for example, if a user uploads a big
46image to the server. Similar to the case of the header fields, there may also be different streams
47of posted data, such as one containing the text of an editbox and another the state of a button.
48Likewise, we will have to register an iterator function that is going to be called maybe several times
49not only if there are different POSTs but also if one POST has only been received partly yet and
50needs processing before another chunk can be received.
51
52Such an iterator function is called by a @emph{postprocessor}, which must be created upon arriving
53of the post request. We want the iterator function to read the first post data which is tagged
54@code{name} and to create an individual greeting string based on the template and the name.
55But in order to pass this string to other functions and still be able to differentiate different
56connections, we must first define a structure to share the information, holding the most import entries.
57
58@verbatim
59struct connection_info_struct
60{
61 int connectiontype;
62 char *answerstring;
63 struct MHD_PostProcessor *postprocessor;
64};
65@end verbatim
66@noindent
67
68With these information available to the iterator function, it is able to fulfill its task.
69Once it has composed the greeting string, it returns @code{MHD_NO} to inform the post processor
70that it does not need to be called again. Note that this function does not handle processing
71of data for the same @code{key}. If we were to expect that the name will be posted in several
72chunks, we had to expand the namestring dynamically as additional parts of it with the same @code{key}
73came in. But in this example, the name is assumed to fit entirely inside one single packet.
74
75@verbatim
76int iterate_post (void *coninfo_cls, enum MHD_ValueKind kind, const char *key,
77 const char *filename, const char *content_type,
78 const char *transfer_encoding, const char *data, size_t off, size_t size)
79{
80 struct connection_info_struct *con_info = (struct connection_info_struct*) coninfo_cls;
81
82
83 if (0 == strcmp (key, "name"))
84 {
85 if ((size > 0) && (size <= MAXNAMESIZE))
86 {
87 char *answerstring;
88 answerstring = malloc (MAXANSWERSIZE);
89 if (!answerstring) return MHD_NO;
90
91 snprintf (answerstring, MAXANSWERSIZE, greatingpage, data);
92 con_info->answerstring = answerstring;
93 }
94 else con_info->answerstring = NULL;
95
96 return MHD_NO;
97 }
98
99 return MHD_YES;
100}
101@end verbatim
102@noindent
103
104Once a connection has been established, it can be terminated for many reasons. As these
105reasons include unexpected events, we have to register another function that cleans up any resources
106that might have been allocated for that connection by us, namely the post processor and the greetings
107string. This cleanup function must take into account that it will also be called for finished
108requests other than @emph{POST} requests.
109
110@verbatim
111void request_completed (void *cls, struct MHD_Connection *connection, void **con_cls,
112 enum MHD_RequestTerminationCode toe)
113{
114 struct connection_info_struct *con_info = (struct connection_info_struct*) *con_cls;
115
116
117 if (NULL == con_info) return;
118
119 if (con_info->connectiontype == POST)
120 {
121 MHD_destroy_post_processor (con_info->postprocessor);
122 if (con_info->answerstring) free (con_info->answerstring);
123 }
124
125 free (con_info);
126 *con_cls = NULL;
127}
128@end verbatim
129@noindent
130
131@emph{GNU libmicrohttpd} is informed that it shall call the above function when the daemon is started
132in the main function.
133
134@verbatim
135...
136daemon = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL,
137 &answer_to_connection, NULL, MHD_OPTION_NOTIFY_COMPLETED,
138 request_completed, NULL, MHD_OPTION_END);
139...
140@end verbatim
141@noindent
142
143@heading Request handling
144With all other functions prepared, we can now discuss the actual request handling.
145
146On the first iteration for a new request, we start by allocating a new instance of a
147@code{ConnectionInfoStruct} structure, which will store all necessary information for later
148iterations and other functions.
149
150@verbatim
151int answer_to_connection (void *cls, struct MHD_Connection *connection, const char *url,
152 const char *method, const char *version, const char *upload_data,
153 unsigned int *upload_data_size, void **con_cls)
154{
155 if(NULL == *con_cls)
156 {
157 struct connection_info_struct *con_info;
158
159 con_info = malloc (sizeof (struct connection_info_struct));
160 if (NULL == con_info) return MHD_NO;
161 con_info->answerstring = NULL;
162@end verbatim
163@noindent
164
165If the new request is a @emph{POST}, the postprocessor must be created now. In addition, the type
166of the request is stored for convenience.
167@verbatim
168 if (0 == strcmp (method, "POST"))
169 {
170 con_info->postprocessor = MHD_create_post_processor (connection, POSTBUFFERSIZE,
171 iterate_post, (void*) con_info);
172
173 if (NULL == con_info->postprocessor)
174 {
175 free (con_info);
176 return MHD_NO;
177 }
178
179 con_info->connectiontype = POST;
180 }
181 else con_info->connectiontype = GET;
182@end verbatim
183@noindent
184
185The address of our structure will both serve as the indicator for successive iterations and to remember
186the particular details about the connection.
187@verbatim
188 *con_cls = (void*) con_info;
189 return MHD_YES;
190 }
191@end verbatim
192@noindent
193
194The rest of the function will not be executed on the first iteration. A @emph{GET} request is easily
195satisfied by sending the question form.
196@verbatim
197 if (0 == strcmp (method, "GET"))
198 {
199 return send_page (connection, askpage);
200 }
201@end verbatim
202@noindent
203
204In case of @emph{POST}, we invoke the post processor for as long as data keeps incoming, setting
205@code{*upload_data_size} to zero in order to indicate that we have processed---or at least have
206considered---all of it.
207@verbatim
208 if (0 == strcmp (method, "POST"))
209 {
210 struct connection_info_struct *con_info = *con_cls;
211
212 if (*upload_data_size != 0)
213 {
214 MHD_post_process(con_info->postprocessor, upload_data, *upload_data_size);
215 *upload_data_size = 0;
216
217 return MHD_YES;
218 }
219 else if (NULL != con_info->answerstring) return send_page (connection, con_info->answerstring);
220 }
221@end verbatim
222@noindent
223
224If they are neither @emph{GET} nor @emph{POST} requests, the error page is returned finally.
225@verbatim
226 return send_page(connection, errorpage);
227}
228@end verbatim
229@noindent
230
231These were the important parts of the program @code{simplepost.c}.
diff --git a/doc/chapters/responseheaders.inc b/doc/chapters/responseheaders.inc
new file mode 100644
index 00000000..19d10142
--- /dev/null
+++ b/doc/chapters/responseheaders.inc
@@ -0,0 +1,177 @@
1Now that we are able to inspect the incoming request in great detail,
2this chapter discusses the means to enrich the outgoing responses likewise.
3
4As you have learned in the @emph{Hello, Browser} chapter, some obligatory
5header fields are added and set automatically for simple responses by the library
6itself but if more advanced features are desired, additional fields have to be created.
7One of the possible fields is the content type field and an example will be developed around it.
8This will lead to an application capable of correctly serving different types of files.
9
10
11When we responded with HTML page packed in the static string previously, the client had no choice
12but guessing about how to handle the response, because the server hadn't told him.
13What if we had sent a picture or a sound file? Would the message have been understood
14or merely been displayed as an endless stream of random characters in the browser?
15This is what the mime content types are for. The header of the response is extended
16by certain information about how the data is to be interpreted.
17
18To introduce the concept, a picture of the format @emph{PNG} will be sent to the client
19and labeled accordingly with @code{image/png}.
20Once again, we can base the new example on the @code{hellobrowser} program.
21
22@verbatim
23#define FILENAME "picture.png"
24#define MIMETYPE "image/png"
25
26int answer_to_connection (void *cls, struct MHD_Connection *connection, const char *url,
27 const char *method, const char *version, const char *upload_data,
28 unsigned int *upload_data_size, void **con_cls)
29{
30 unsigned char *buffer = NULL;
31 struct MHD_Response *response;
32@end verbatim
33@noindent
34
35We want the program to load the graphics file into memory:
36@verbatim
37 long size;
38 FILE *fp;
39 int ret = 0;
40
41 if (0 != strcmp(method, "GET")) return MHD_NO;
42
43 size = get_file_size (FILENAME);
44 if (size != 0)
45 {
46 fp = fopen (FILENAME, "rb");
47 if (fp)
48 {
49 buffer = malloc (size);
50
51 if (buffer)
52 if (size == fread (buffer, 1, size, fp)) ret = 1;
53
54 fclose(fp);
55 }
56 }
57@end verbatim
58@noindent
59
60The @code{GetFileSize} function, which returns a size of zero if the file could not be opened or
61found, is left out on this page for tidiness.
62
63When dealing with files and allocating memory, there is a lot that could go wrong on the
64server side and if so, the client should be informed with @code{MHD_HTTP_INTERNAL_SERVER_ERROR}.
65
66@verbatim
67 if (!ret)
68 {
69 const char *errorstr = "<html><body>An internal server error has occured!\
70 </body></html>";
71
72 if (buffer) free(buffer);
73
74 response = MHD_create_response_from_data(strlen(errorstr), (void*)errorstr,
75 MHD_NO, MHD_NO);
76
77 if (response)
78 {
79 ret = MHD_queue_response (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, response);
80 MHD_destroy_response (response);
81
82 return MHD_YES;
83 }
84 else return MHD_NO;
85 }
86@end verbatim
87@noindent
88
89Note that we nevertheless have to create a response object even for sending a simple error code.
90Otherwise, the connection would just be closed without comment, leaving the client curious about
91what has happened.
92
93But in the case of success a response will be constructed that contains the buffer filled with the
94file's content.
95
96@verbatim
97response = MHD_create_response_from_data (size, (void*)buffer, MHD_YES, MHD_NO);
98@end verbatim
99@noindent
100
101Contrary to the above case where a static string will be sent, this time we have to
102keep track of the dynamically allocated buffer. As discussed in the @ref{Hello browser example},
103the buffer cannot be safely freed as soon as the function call returns. Instead, we ask the function
104to keep charge of freeing the buffer itself when it is not longer needed. Thus, no further @code{free}
105command is invoked by us.
106
107Up to this point, there was little new. The actual novelty is that we enhance the header with the
108meta data about the content. Aware of the field's name we want to add, it is as easy as that:
109@verbatim
110MHD_add_response_header(response, "Content-Type", MIMETYPE);
111@end verbatim
112@noindent
113We do not have to append a colon expected by the protocol hehind the first
114field---@emph{GNU libhttpdmicro} will take care of this.
115
116The function finishes with the well-known lines
117@verbatim
118 ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
119 MHD_destroy_response (response);
120 return ret;
121}
122@end verbatim
123@noindent
124
125The complete program @code{responseheaders.c} is in the @code{examples} section as usual.
126Find a @emph{PNG} file you like and save it to the directory the example is run from under the name
127@code{picture.png}. You should find the image displayed on your browser if everything worked well.
128
129@heading Remarks
130The include file of the @emph{MHD} library comes with the header types mentioned in @emph{RFC 2616}
131already defined as macros. Thus, we could have written @code{MHD_HTTP_HEADER_CONTENT_TYPE} instead
132of @code{"Content-Type"} as well. However, one is not limited to these standard headers and could
133add custom response headers without violating the protocol. Whether, and how, the client would react
134to these custom header is up to the receiver. Likewise, the client is allowed to send custom request
135headers to the server as well, opening up yet more possibilities how client and server could
136communicate with each other.
137
138The method of creating the response from one big chunk of data is only feasible for smaller files.
139A public file server satisfying many request at the same time would be choking under these high
140demands on memory very soon. Serving responses in smaller parts would be more adequate here and
141will be a topic of a future chapter.
142
143@heading Exercises
144@itemize @bullet
145
146@item
147Remember that the original program was written under a few assumptions---a small, static response
148being one of them. In order to simulate a very large or hard to reach file that cannot be provided
149instantly, postpone the queuing in the callback with the @code{sleep} function for 30 seconds
150@emph{if} the file @code{/big.png} is requested (but deliver the same as above). A request for
151@code{/picture.png} should provide just the same but without any artificial delays.
152
153Now start two instances of your browser (or even use two machines) and see how the second client
154is put on hold while the first waits for his request on the slow file to be fulfilled.
155
156Finally, change the sourcecode to use @code{MHD_USE_THREAD_PER_CONNECTION} when the daemon is
157started and try again.
158
159
160@item
161Did you succeed in implementing the clock exercise yet? This time, let the server save the
162program's start time @code{t} and implement a response simulating a countdown that reaches 0 at
163@code{t+60}. Returning a message saying on which point the countdown is, the response should
164ultimately be to reply "Done" if the program has been running long enough,
165
166A non official, but widely understood, response header line is @code{Refresh: DELAY; url=URL} with
167the uppercase words substituted to tell the client it should request the given resource after
168the given delay again. Improve your program in that the browser (any modern browser should work)
169automatically reconnects and asks for the status again every 5 seconds or so. The URL would have
170to be composed so that it begins with "http://", followed by the @emph{URI} the server is reachable
171from the client's point of view.
172
173Maybe you want also to visualize the countdown as a status bar by creating a
174@code{<table>} consisting of one row and @code{n} columns whose fields contain small images of either
175a red or a green light.
176
177@end itemize