aboutsummaryrefslogtreecommitdiff
path: root/doc/chapters/responseheaders.inc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/chapters/responseheaders.inc')
-rw-r--r--doc/chapters/responseheaders.inc177
1 files changed, 177 insertions, 0 deletions
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