Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / doc / sources / tutorial-server.rst
1 Tutorial: HTTP/2 server
2 =========================
3
4 In this tutorial, we are going to write single-threaded, event-based
5 HTTP/2 web server, which supports HTTPS only. It can handle
6 concurrent multiple requests, but only the GET method is supported. The
7 complete source code, `libevent-server.c`_, is attached at the end of
8 this page.  It also resides in examples directory in the archive or
9 repository.
10
11 This simple server takes 3 arguments, a port number to listen to, a path to
12 your SSL/TLS private key file and a path to your certificate file.  Its
13 synopsis is like this::
14
15     $ libevent-server PORT /path/to/server.key /path/to/server.crt
16
17 We use libevent in this tutorial to handle networking I/O.  Please
18 note that nghttp2 itself does not depend on libevent.
19
20 First we create a setup routine for libevent and OpenSSL in the functions
21 ``main()`` and ``run()``. One thing in there you should look at, is the setup
22 of the NPN callback.  The NPN callback is used for the server to advertise
23 which application protocols the server supports to a client.  In this example
24 program, when creating ``SSL_CTX`` object, we store the application protocol
25 name in the wire format of NPN in a statically allocated buffer. This is safe
26 because we only create one ``SSL_CTX`` object in the program's entire life
27 time::
28
29     static unsigned char next_proto_list[256];
30     static size_t next_proto_list_len;
31
32     static int next_proto_cb(SSL *s _U_, const unsigned char **data,
33                              unsigned int *len, void *arg _U_) {
34       *data = next_proto_list;
35       *len = (unsigned int)next_proto_list_len;
36       return SSL_TLSEXT_ERR_OK;
37     }
38
39     static SSL_CTX *create_ssl_ctx(const char *key_file, const char *cert_file) {
40       SSL_CTX *ssl_ctx;
41       EC_KEY *ecdh;
42
43       ssl_ctx = SSL_CTX_new(SSLv23_server_method());
44
45       ...
46
47       next_proto_list[0] = NGHTTP2_PROTO_VERSION_ID_LEN;
48       memcpy(&next_proto_list[1], NGHTTP2_PROTO_VERSION_ID,
49              NGHTTP2_PROTO_VERSION_ID_LEN);
50       next_proto_list_len = 1 + NGHTTP2_PROTO_VERSION_ID_LEN;
51
52       SSL_CTX_set_next_protos_advertised_cb(ssl_ctx, next_proto_cb, NULL);
53       return ssl_ctx;
54     }
55
56 The wire format of NPN is a sequence of length prefixed string. Exactly one
57 byte is used to specify the length of each protocol identifier.  In this
58 tutorial, we advertise the specific HTTP/2 protocol version the current
59 nghttp2 library supports. The nghttp2 library exports its identifier in
60 :macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function is the
61 server-side NPN callback. In the OpenSSL implementation, we just assign the
62 pointer to the NPN buffers we filled in earlier. The NPN callback function is
63 set to the ``SSL_CTX`` object using
64 ``SSL_CTX_set_next_protos_advertised_cb()``.
65
66 We use the ``app_content`` structure to store application-wide data::
67
68     struct app_context {
69       SSL_CTX *ssl_ctx;
70       struct event_base *evbase;
71     };
72
73 We use the ``http2_session_data`` structure to store session-level
74 (which corresponds to one HTTP/2 connection) data::
75
76     typedef struct http2_session_data {
77       struct http2_stream_data root;
78       struct bufferevent *bev;
79       app_context *app_ctx;
80       nghttp2_session *session;
81       char *client_addr;
82     } http2_session_data;
83
84 We use the ``http2_stream_data`` structure to store stream-level data::
85
86     typedef struct http2_stream_data {
87       struct http2_stream_data *prev, *next;
88       char *request_path;
89       int32_t stream_id;
90       int fd;
91     } http2_stream_data;
92
93 A single HTTP/2 session can have multiple streams.  We manage these
94 multiple streams with a doubly linked list.  The first element of this
95 list is pointed to by the ``root->next`` in ``http2_session_data``.
96 Initially, ``root->next`` is ``NULL``.  We use libevent's bufferevent
97 structure to perform network I/O.  Note that the bufferevent object is
98 kept in ``http2_session_data`` and not in ``http2_stream_data``.  This
99 is because ``http2_stream_data`` is just a logical stream multiplexed
100 over the single connection managed by bufferevent in
101 ``http2_session_data``.
102
103 We first create a listener object to accept incoming connections.  We use
104 libevent's ``struct evconnlistener`` for this purpose::
105
106     static void start_listen(struct event_base *evbase, const char *service,
107                              app_context *app_ctx) {
108       int rv;
109       struct addrinfo hints;
110       struct addrinfo *res, *rp;
111
112       memset(&hints, 0, sizeof(hints));
113       hints.ai_family = AF_UNSPEC;
114       hints.ai_socktype = SOCK_STREAM;
115       hints.ai_flags = AI_PASSIVE;
116     #ifdef AI_ADDRCONFIG
117       hints.ai_flags |= AI_ADDRCONFIG;
118     #endif /* AI_ADDRCONFIG */
119
120       rv = getaddrinfo(NULL, service, &hints, &res);
121       if (rv != 0) {
122         errx(1, NULL);
123       }
124       for (rp = res; rp; rp = rp->ai_next) {
125         struct evconnlistener *listener;
126         listener = evconnlistener_new_bind(
127             evbase, acceptcb, app_ctx, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
128             16, rp->ai_addr, rp->ai_addrlen);
129         if (listener) {
130           freeaddrinfo(res);
131
132           return;
133         }
134       }
135       errx(1, "Could not start listener");
136     }
137
138 We specify the ``acceptcb`` callback which is called when a new connection is
139 accepted::
140
141     static void acceptcb(struct evconnlistener *listener _U_, int fd,
142                          struct sockaddr *addr, int addrlen, void *arg) {
143       app_context *app_ctx = (app_context *)arg;
144       http2_session_data *session_data;
145
146       session_data = create_http2_session_data(app_ctx, fd, addr, addrlen);
147
148       bufferevent_setcb(session_data->bev, readcb, writecb, eventcb, session_data);
149     }
150
151 Here we create the ``http2_session_data`` object. The bufferevent for
152 this connection is also initialized at this time. We specify three
153 callbacks for the bufferevent: ``readcb``, ``writecb`` and
154 ``eventcb``.
155
156 The ``eventcb()`` callback is invoked by the libevent event loop when an event
157 (e.g., connection has been established, timeout, etc) happens on the
158 underlying network socket::
159
160     static void eventcb(struct bufferevent *bev _U_, short events, void *ptr) {
161       http2_session_data *session_data = (http2_session_data *)ptr;
162       if (events & BEV_EVENT_CONNECTED) {
163         fprintf(stderr, "%s connected\n", session_data->client_addr);
164
165         initialize_nghttp2_session(session_data);
166
167         if (send_server_connection_header(session_data) != 0) {
168           delete_http2_session_data(session_data);
169           return;
170         }
171
172         return;
173       }
174       if (events & BEV_EVENT_EOF) {
175         fprintf(stderr, "%s EOF\n", session_data->client_addr);
176       } else if (events & BEV_EVENT_ERROR) {
177         fprintf(stderr, "%s network error\n", session_data->client_addr);
178       } else if (events & BEV_EVENT_TIMEOUT) {
179         fprintf(stderr, "%s timeout\n", session_data->client_addr);
180       }
181       delete_http2_session_data(session_data);
182     }
183
184 For the ``BEV_EVENT_EOF``, ``BEV_EVENT_ERROR`` and
185 ``BEV_EVENT_TIMEOUT`` events, we just simply tear down the connection.
186 The ``delete_http2_session_data()`` function destroys the
187 ``http2_session_data`` object and thus also its bufferevent member.
188 As a result, the underlying connection is closed.  The
189 ``BEV_EVENT_CONNECTED`` event is invoked when SSL/TLS handshake is
190 finished successfully.  Now we are ready to start the HTTP/2
191 communication.
192
193 We initialize a nghttp2 session object which is done in
194 ``initialize_nghttp2_session()``::
195
196     static void initialize_nghttp2_session(http2_session_data *session_data) {
197       nghttp2_session_callbacks *callbacks;
198
199       nghttp2_session_callbacks_new(&callbacks);
200
201       nghttp2_session_callbacks_set_send_callback(callbacks, send_callback);
202
203       nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
204                                                            on_frame_recv_callback);
205
206       nghttp2_session_callbacks_set_on_stream_close_callback(
207           callbacks, on_stream_close_callback);
208
209       nghttp2_session_callbacks_set_on_header_callback(callbacks,
210                                                        on_header_callback);
211
212       nghttp2_session_callbacks_set_on_begin_headers_callback(
213           callbacks, on_begin_headers_callback);
214
215       nghttp2_session_server_new(&session_data->session, callbacks, session_data);
216
217       nghttp2_session_callbacks_del(callbacks);
218     }
219
220 Since we are creating a server and uses options, the nghttp2 session
221 object is created using `nghttp2_session_server_new2()` function.  We
222 registers five callbacks for nghttp2 session object.  We'll talk about
223 these callbacks later.
224
225 After initialization of the nghttp2 session object, we are going to send
226 a server connection header in ``send_server_connection_header()``::
227
228     static int send_server_connection_header(http2_session_data *session_data) {
229       nghttp2_settings_entry iv[1] = {
230           {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100}};
231       int rv;
232
233       rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, iv,
234                                    ARRLEN(iv));
235       if (rv != 0) {
236         warnx("Fatal error: %s", nghttp2_strerror(rv));
237         return -1;
238       }
239       return 0;
240     }
241
242 The server connection header is a SETTINGS frame. We specify
243 SETTINGS_MAX_CONCURRENT_STREAMS to 100 in the SETTINGS frame.  To queue
244 the SETTINGS frame for the transmission, we use
245 `nghttp2_submit_settings()`. Note that `nghttp2_submit_settings()`
246 function only queues the frame and it does not actually send it. All
247 functions in the ``nghttp2_submit_*()`` family have this property. To
248 actually send the frame, `nghttp2_session_send()` should be used, as
249 described later.
250
251 Since bufferevent may buffer more than the first 24 bytes from the client, we
252 have to process them here since libevent won't invoke callback functions for
253 this pending data. To process the received data, we call the
254 ``session_recv()`` function::
255
256     static int session_recv(http2_session_data *session_data) {
257       ssize_t readlen;
258       struct evbuffer *input = bufferevent_get_input(session_data->bev);
259       size_t datalen = evbuffer_get_length(input);
260       unsigned char *data = evbuffer_pullup(input, -1);
261
262       readlen = nghttp2_session_mem_recv(session_data->session, data, datalen);
263       if (readlen < 0) {
264         warnx("Fatal error: %s", nghttp2_strerror((int)readlen));
265         return -1;
266       }
267       if (evbuffer_drain(input, readlen) != 0) {
268         warnx("Fatal error: evbuffer_drain failed");
269         return -1;
270       }
271       if (session_send(session_data) != 0) {
272         return -1;
273       }
274       return 0;
275     }
276
277 In this function, we feed all unprocessed but already received data to the
278 nghttp2 session object using the `nghttp2_session_mem_recv()` function. The
279 `nghttp2_session_mem_recv()` function processes the data and may invoke the
280 nghttp2 callbacks and also queue outgoing frames. Since there may be pending
281 outgoing frames, we call ``session_send()`` function to send off those
282 frames. The ``session_send()`` function is defined as follows::
283
284     static int session_send(http2_session_data *session_data) {
285       int rv;
286       rv = nghttp2_session_send(session_data->session);
287       if (rv != 0) {
288         warnx("Fatal error: %s", nghttp2_strerror(rv));
289         return -1;
290       }
291       return 0;
292     }
293
294 The `nghttp2_session_send()` function serializes the frame into wire
295 format and calls ``send_callback()`` of type
296 :type:`nghttp2_send_callback`.  The ``send_callback()`` is defined as
297 follows::
298
299     static ssize_t send_callback(nghttp2_session *session _U_, const uint8_t *data,
300                                  size_t length, int flags _U_, void *user_data) {
301       http2_session_data *session_data = (http2_session_data *)user_data;
302       struct bufferevent *bev = session_data->bev;
303       /* Avoid excessive buffering in server side. */
304       if (evbuffer_get_length(bufferevent_get_output(session_data->bev)) >=
305           OUTPUT_WOULDBLOCK_THRESHOLD) {
306         return NGHTTP2_ERR_WOULDBLOCK;
307       }
308       bufferevent_write(bev, data, length);
309       return length;
310     }
311
312 Since we use bufferevent to abstract network I/O, we just write the
313 data to the bufferevent object. Note that `nghttp2_session_send()`
314 continues to write all frames queued so far. If we were writing the
315 data to a non-blocking socket directly using ``write()`` system call
316 in the ``send_callback()``, we would surely get ``EAGAIN`` or
317 ``EWOULDBLOCK`` back since the socket has limited send buffer. If that
318 happens, we can return :macro:`NGHTTP2_ERR_WOULDBLOCK` to signal the
319 nghttp2 library to stop sending further data. But when writing to the
320 bufferevent, we have to regulate the amount data to get buffered
321 ourselves to avoid using huge amounts of memory. To achieve this, we
322 check the size of the output buffer and if it reaches more than or
323 equal to ``OUTPUT_WOULDBLOCK_THRESHOLD`` bytes, we stop writing data
324 and return :macro:`NGHTTP2_ERR_WOULDBLOCK` to tell the library to stop
325 calling send_callback.
326
327 The next bufferevent callback is ``readcb()``, which is invoked when
328 data is available to read in the bufferevent input buffer::
329
330     static void readcb(struct bufferevent *bev _U_, void *ptr) {
331       http2_session_data *session_data = (http2_session_data *)ptr;
332       if (session_recv(session_data) != 0) {
333         delete_http2_session_data(session_data);
334         return;
335       }
336     }
337
338 In this function, we just call ``session_recv()`` to process incoming
339 data.
340
341 The third bufferevent callback is ``writecb()``, which is invoked when all
342 data in the bufferevent output buffer has been sent::
343
344     static void writecb(struct bufferevent *bev, void *ptr) {
345       http2_session_data *session_data = (http2_session_data *)ptr;
346       if (evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
347         return;
348       }
349       if (nghttp2_session_want_read(session_data->session) == 0 &&
350           nghttp2_session_want_write(session_data->session) == 0) {
351         delete_http2_session_data(session_data);
352         return;
353       }
354       if (session_send(session_data) != 0) {
355         delete_http2_session_data(session_data);
356         return;
357       }
358     }
359
360 First we check whether we should drop the connection or not. The nghttp2
361 session object keeps track of reception and transmission of GOAWAY frames and
362 other error conditions as well. Using this information, the nghttp2 session
363 object will tell whether the connection should be dropped or not. More
364 specifically, if both `nghttp2_session_want_read()` and
365 `nghttp2_session_want_write()` return 0, we have no business left in the
366 connection. But since we are using bufferevent and its deferred callback
367 option, the bufferevent output buffer may contain pending data when the
368 ``writecb()`` is called. To handle this, we check whether the output buffer is
369 empty or not. If all these conditions are met, we drop connection.
370
371 Otherwise, we call ``session_send()`` to process the pending output
372 data. Remember that in ``send_callback()``, we must not write all data to
373 bufferevent to avoid excessive buffering. We continue processing pending data
374 when the output buffer becomes empty.
375
376 We have already described the nghttp2 callback ``send_callback()``.  Let's
377 learn about the remaining nghttp2 callbacks we setup in
378 ``initialize_nghttp2_setup()`` function.
379
380 The ``on_begin_headers_callback()`` function is invoked when the reception of
381 a header block in HEADERS or PUSH_PROMISE frame is started::
382
383     static int on_begin_headers_callback(nghttp2_session *session,
384                                          const nghttp2_frame *frame,
385                                          void *user_data) {
386       http2_session_data *session_data = (http2_session_data *)user_data;
387       http2_stream_data *stream_data;
388
389       if (frame->hd.type != NGHTTP2_HEADERS ||
390           frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
391         return 0;
392       }
393       stream_data = create_http2_stream_data(session_data, frame->hd.stream_id);
394       nghttp2_session_set_stream_user_data(session, frame->hd.stream_id,
395                                            stream_data);
396       return 0;
397     }
398
399 We are only interested in the HEADERS frame in this function. Since the
400 HEADERS frame has several roles in the HTTP/2 protocol, we check that it is a
401 request HEADERS, which opens new stream. If the frame is a request HEADERS, we
402 create a ``http2_stream_data`` object to store the stream related data. We
403 associate the created ``http2_stream_data`` object with the stream in the
404 nghttp2 session object using `nghttp2_set_stream_user_data()` to get the
405 object without searching through the doubly linked list.
406
407 In this example server, we want to serve files relative to the current working
408 directory in which the program was invoked. Each header name/value pair is
409 emitted via ``on_header_callback`` function, which is called after
410 ``on_begin_headers_callback()``::
411
412     static int on_header_callback(nghttp2_session *session,
413                                   const nghttp2_frame *frame, const uint8_t *name,
414                                   size_t namelen, const uint8_t *value,
415                                   size_t valuelen, uint8_t flags _U_,
416                                   void *user_data _U_) {
417       http2_stream_data *stream_data;
418       const char PATH[] = ":path";
419       switch (frame->hd.type) {
420       case NGHTTP2_HEADERS:
421         if (frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
422           break;
423         }
424         stream_data =
425             nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
426         if (!stream_data || stream_data->request_path) {
427           break;
428         }
429         if (namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
430           size_t j;
431           for (j = 0; j < valuelen && value[j] != '?'; ++j)
432             ;
433           stream_data->request_path = percent_decode(value, j);
434         }
435         break;
436       }
437       return 0;
438     }
439
440 We search for the ``:path`` header field among the request headers and store
441 the requested path in the ``http2_stream_data`` object. In this example
442 program, we ignore ``:method`` header field and always treat the request as a
443 GET request.
444
445 The ``on_frame_recv_callback()`` function is invoked when a frame is
446 fully received::
447
448     static int on_frame_recv_callback(nghttp2_session *session,
449                                       const nghttp2_frame *frame, void *user_data) {
450       http2_session_data *session_data = (http2_session_data *)user_data;
451       http2_stream_data *stream_data;
452       switch (frame->hd.type) {
453       case NGHTTP2_DATA:
454       case NGHTTP2_HEADERS:
455         /* Check that the client request has finished */
456         if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
457           stream_data =
458               nghttp2_session_get_stream_user_data(session, frame->hd.stream_id);
459           /* For DATA and HEADERS frame, this callback may be called after
460              on_stream_close_callback. Check that stream still alive. */
461           if (!stream_data) {
462             return 0;
463           }
464           return on_request_recv(session, session_data, stream_data);
465         }
466         break;
467       default:
468         break;
469       }
470       return 0;
471     }
472
473 First we retrieve the ``http2_stream_data`` object associated with the stream
474 in ``on_begin_headers_callback()``. It is done using
475 `nghttp2_session_get_stream_user_data()`. If the requested path cannot be
476 served for some reason (e.g., file is not found), we send a 404 response,
477 which is done in ``error_reply()``.  Otherwise, we open the requested file and
478 send its content. We send the header field ``:status`` as a single response
479 header.
480
481 Sending the content of the file is done in ``send_response()`` function::
482
483     static int send_response(nghttp2_session *session, int32_t stream_id,
484                              nghttp2_nv *nva, size_t nvlen, int fd) {
485       int rv;
486       nghttp2_data_provider data_prd;
487       data_prd.source.fd = fd;
488       data_prd.read_callback = file_read_callback;
489
490       rv = nghttp2_submit_response(session, stream_id, nva, nvlen, &data_prd);
491       if (rv != 0) {
492         warnx("Fatal error: %s", nghttp2_strerror(rv));
493         return -1;
494       }
495       return 0;
496     }
497
498 The nghttp2 library uses the :type:`nghttp2_data_provider` structure to
499 send entity body to the remote peer. The ``source`` member of this
500 structure is a union and it can be either void pointer or int which is
501 intended to be used as file descriptor. In this example server, we use
502 the file descriptor. We also set the ``file_read_callback()`` callback
503 function to read the contents of the file::
504
505     static ssize_t file_read_callback(nghttp2_session *session _U_,
506                                       int32_t stream_id _U_, uint8_t *buf,
507                                       size_t length, uint32_t *data_flags,
508                                       nghttp2_data_source *source,
509                                       void *user_data _U_) {
510       int fd = source->fd;
511       ssize_t r;
512       while ((r = read(fd, buf, length)) == -1 && errno == EINTR)
513         ;
514       if (r == -1) {
515         return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
516       }
517       if (r == 0) {
518         *data_flags |= NGHTTP2_DATA_FLAG_EOF;
519       }
520       return r;
521     }
522
523 If an error happens while reading the file, we return
524 :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE`.  This tells the
525 library to send RST_STREAM to the stream.  When all data has been read, set
526 the :macro:`NGHTTP2_DATA_FLAG_EOF` flag to ``*data_flags`` to tell the
527 nghttp2 library that we have finished reading the file.
528
529 The `nghttp2_submit_response()` function is used to send the response to the
530 remote peer.
531
532 The ``on_stream_close_callback()`` function is invoked when the stream
533 is about to close::
534
535     static int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
536                                         uint32_t error_code _U_, void *user_data) {
537       http2_session_data *session_data = (http2_session_data *)user_data;
538       http2_stream_data *stream_data;
539
540       stream_data = nghttp2_session_get_stream_user_data(session, stream_id);
541       if (!stream_data) {
542         return 0;
543       }
544       remove_stream(session_data, stream_data);
545       delete_http2_stream_data(stream_data);
546       return 0;
547     }
548
549 We destroy the ``http2_stream_data`` object in this function since the stream
550 is about to close and we no longer use that object.