Imported Upstream version 1.46.0
[platform/upstream/nghttp2.git] / doc / programmers-guide.rst
1 Programmers' Guide
2 ==================
3
4 Architecture
5 ------------
6
7 The most notable point in nghttp2 library architecture is it does not
8 perform any I/O.  nghttp2 only performs HTTP/2 protocol stuff based on
9 input byte strings.  It will call callback functions set by
10 applications while processing input.  The output of nghttp2 is just
11 byte string.  An application is responsible to send these output to
12 the remote peer.  The callback functions may be called while producing
13 output.
14
15 Not doing I/O makes embedding nghttp2 library in the existing code
16 base very easy.  Usually, the existing applications have its own I/O
17 event loops.  It is very hard to use nghttp2 in that situation if
18 nghttp2 does its own I/O.  It also makes light weight language wrapper
19 for nghttp2 easy with the same reason.  The down side is that an
20 application author has to write more code to write complete
21 application using nghttp2.  This is especially true for simple "toy"
22 application.  For the real applications, however, this is not the
23 case.  This is because you probably want to support HTTP/1 which
24 nghttp2 does not provide, and to do that, you will need to write your
25 own HTTP/1 stack or use existing third-party library, and bind them
26 together with nghttp2 and I/O event loop.  In this point, not
27 performing I/O in nghttp2 has more point than doing it.
28
29 The primary object that an application uses is :type:`nghttp2_session`
30 object, which is opaque struct and its details are hidden in order to
31 ensure the upgrading its internal architecture without breaking the
32 backward compatibility.  An application can set callbacks to
33 :type:`nghttp2_session` object through the dedicated object and
34 functions, and it also interacts with it via many API function calls.
35
36 An application can create as many :type:`nghttp2_session` object as it
37 wants.  But single :type:`nghttp2_session` object must be used by a
38 single thread at the same time.  This is not so hard to enforce since
39 most event-based architecture applications use is single thread per
40 core, and handling one connection I/O is done by single thread.
41
42 To feed input to :type:`nghttp2_session` object, one can use
43 `nghttp2_session_recv()` or `nghttp2_session_mem_recv()` functions.
44 They behave similarly, and the difference is that
45 `nghttp2_session_recv()` will use :type:`nghttp2_read_callback` to get
46 input.  On the other hand, `nghttp2_session_mem_recv()` will take
47 input as its parameter.  If in doubt, use `nghttp2_session_mem_recv()`
48 since it is simpler, and could be faster since it avoids calling
49 callback function.
50
51 To get output from :type:`nghttp2_session` object, one can use
52 `nghttp2_session_send()` or `nghttp2_session_mem_send()`.  The
53 difference between them is that the former uses
54 :type:`nghttp2_send_callback` to pass output to an application.  On
55 the other hand, the latter returns the output to the caller.  If in
56 doubt, use `nghttp2_session_mem_send()` since it is simpler.  But
57 `nghttp2_session_send()` might be easier to use if the output buffer
58 an application has is fixed sized.
59
60 In general, an application should call `nghttp2_session_mem_send()`
61 when it gets input from underlying connection.  Since there is great
62 chance to get something pushed into transmission queue while the call
63 of `nghttp2_session_mem_send()`, it is recommended to call
64 `nghttp2_session_mem_recv()` after `nghttp2_session_mem_send()`.
65
66 There is a question when we are safe to close HTTP/2 session without
67 waiting for the closure of underlying connection.  We offer 2 API
68 calls for this: `nghttp2_session_want_read()` and
69 `nghttp2_session_want_write()`.  If they both return 0, application
70 can destroy :type:`nghttp2_session`, and then close the underlying
71 connection.  But make sure that the buffered output has been
72 transmitted to the peer before closing the connection when
73 `nghttp2_session_mem_send()` is used, since
74 `nghttp2_session_want_write()` does not take into account the
75 transmission of the buffered data outside of :type:`nghttp2_session`.
76
77 Includes
78 --------
79
80 To use the public APIs, include ``nghttp2/nghttp2.h``::
81
82     #include <nghttp2/nghttp2.h>
83
84 The header files are also available online: :doc:`nghttp2.h` and
85 :doc:`nghttp2ver.h`.
86
87 Remarks
88 -------
89
90 Do not call `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
91 `nghttp2_session_recv()` or `nghttp2_session_mem_recv()` from the
92 nghttp2 callback functions directly or indirectly. It will lead to the
93 crash.  You can submit requests or frames in the callbacks then call
94 these functions outside the callbacks.
95
96 `nghttp2_session_send()` and `nghttp2_session_mem_send()` send first
97 24 bytes of client magic string (MAGIC)
98 (:macro:`NGHTTP2_CLIENT_MAGIC`) on client configuration.  The
99 applications are responsible to send SETTINGS frame as part of
100 connection preface using `nghttp2_submit_settings()`.  Similarly,
101 `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` consume
102 MAGIC on server configuration unless
103 `nghttp2_option_set_no_recv_client_magic()` is used with nonzero
104 option value.
105
106 .. _http-messaging:
107
108 HTTP Messaging
109 --------------
110
111 By default, nghttp2 library checks HTTP messaging rules described in
112 `HTTP/2 specification, section 8
113 <https://tools.ietf.org/html/rfc7540#section-8>`_.  Everything
114 described in that section is not validated however.  We briefly
115 describe what the library does in this area.  In the following
116 description, without loss of generality we omit CONTINUATION frame
117 since they must follow HEADERS frame and are processed atomically.  In
118 other words, they are just one big HEADERS frame.  To disable these
119 validations, use `nghttp2_option_set_no_http_messaging()`.  Please
120 note that disabling this feature does not change the fundamental
121 client and server model of HTTP.  That is, even if the validation is
122 disabled, only client can send requests.
123
124 For HTTP request, including those carried by PUSH_PROMISE, HTTP
125 message starts with one HEADERS frame containing request headers.  It
126 is followed by zero or more DATA frames containing request body, which
127 is followed by zero or one HEADERS containing trailer headers.  The
128 request headers must include ":scheme", ":method" and ":path" pseudo
129 header fields unless ":method" is not "CONNECT".  ":authority" is
130 optional, but nghttp2 requires either ":authority" or "Host" header
131 field must be present.  If ":method" is "CONNECT", the request headers
132 must include ":method" and ":authority" and must omit ":scheme" and
133 ":path".
134
135 For HTTP response, HTTP message starts with zero or more HEADERS
136 frames containing non-final response (status code 1xx).  They are
137 followed by one HEADERS frame containing final response headers
138 (non-1xx).  It is followed by zero or more DATA frames containing
139 response body, which is followed by zero or one HEADERS containing
140 trailer headers.  The non-final and final response headers must
141 contain ":status" pseudo header field containing 3 digits only.
142
143 All request and response headers must include exactly one valid value
144 for each pseudo header field.  Additionally nghttp2 requires all
145 request headers must not include more than one "Host" header field.
146
147 HTTP/2 prohibits connection-specific header fields.  The following
148 header fields must not appear: "Connection", "Keep-Alive",
149 "Proxy-Connection", "Transfer-Encoding" and "Upgrade".  Additionally,
150 "TE" header field must not include any value other than "trailers".
151
152 Each header field name and value must obey the field-name and
153 field-value production rules described in `RFC 7230, section
154 3.2. <https://tools.ietf.org/html/rfc7230#section-3.2>`_.
155 Additionally, all field name must be lower cased.  The invalid header
156 fields are treated as stream error, and that stream is reset.  If
157 application wants to treat these headers in their own way, use
158 `nghttp2_on_invalid_header_callback
159 <https://nghttp2.org/documentation/types.html#c.nghttp2_on_invalid_header_callback>`_.
160
161 For "http" or "https" URIs, ":path" pseudo header fields must start
162 with "/".  The only exception is OPTIONS request, in that case, "*" is
163 allowed in ":path" pseudo header field to represent system-wide
164 OPTIONS request.
165
166 With the above validations, nghttp2 library guarantees that header
167 field name passed to `nghttp2_on_header_callback()` is not empty.
168 Also required pseudo headers are all present and not empty.
169
170 nghttp2 enforces "Content-Length" validation as well.  All request or
171 response headers must not contain more than one "Content-Length"
172 header field.  If "Content-Length" header field is present, it must be
173 parsed as 64 bit signed integer.  The sum of data length in the
174 following DATA frames must match with the number in "Content-Length"
175 header field if it is present (this does not include padding bytes).
176
177 RFC 7230 says that server must not send "Content-Length" in any
178 response with 1xx, and 204 status code.  It also says that
179 "Content-Length" is not allowed in any response with 200 status code
180 to a CONNECT request.  nghttp2 enforces them as well.
181
182 Any deviation results in stream error of type PROTOCOL_ERROR.  If
183 error is found in PUSH_PROMISE frame, stream error is raised against
184 promised stream.
185
186 The order of transmission of the HTTP/2 frames
187 ----------------------------------------------
188
189 This section describes the internals of libnghttp2 about the
190 scheduling of transmission of HTTP/2 frames.  This is pretty much
191 internal stuff, so the details could change in the future versions of
192 the library.
193
194 libnghttp2 categorizes HTTP/2 frames into 4 categories: urgent,
195 regular, syn_stream, and data in the order of higher priority.
196
197 The urgent category includes PING and SETTINGS.  They are sent with
198 highest priority.  The order inside the category is FIFO.
199
200 The regular category includes frames other than PING, SETTINGS, DATA,
201 and HEADERS which does not create stream (which counts toward
202 concurrent stream limit).  The order inside the category is FIFO.
203
204 The syn_stream category includes HEADERS frame which creates stream,
205 that counts toward the concurrent stream limit.
206
207 The data category includes DATA frame, and the scheduling among DATA
208 frames are determined by HTTP/2 dependency tree.
209
210 If the application wants to send frames in the specific order, and the
211 default transmission order does not fit, it has to schedule frames by
212 itself using the callbacks (e.g.,
213 :type:`nghttp2_on_frame_send_callback`).
214
215 RST_STREAM has special side effect when it is submitted by
216 `nghttp2_submit_rst_stream()`.  It cancels all pending HEADERS and
217 DATA frames whose stream ID matches the one in the RST_STREAM frame.
218 This may cause unexpected behaviour for the application in some cases.
219 For example, suppose that application wants to send RST_STREAM after
220 sending response HEADERS and DATA.  Because of the reason we mentioned
221 above, the following code does not work:
222
223 .. code-block:: c
224
225     nghttp2_submit_response(...)
226     nghttp2_submit_rst_stream(...)
227
228 RST_STREAM cancels HEADERS (and DATA), and just RST_STREAM is sent.
229 The correct way is use :type:`nghttp2_on_frame_send_callback`, and
230 after HEADERS and DATA frames are sent, issue
231 `nghttp2_submit_rst_stream()`.  FYI,
232 :type:`nghttp2_on_frame_not_send_callback` tells you why frames are
233 not sent.
234
235 Implement user defined HTTP/2 non-critical extensions
236 -----------------------------------------------------
237
238 As of nghttp2 v1.8.0, we have added HTTP/2 non-critical extension
239 framework, which lets application send and receive user defined custom
240 HTTP/2 non-critical extension frames.  nghttp2 also offers built-in
241 functionality to send and receive official HTTP/2 extension frames
242 (e.g., ALTSVC frame).  For these built-in handler, refer to the next
243 section.
244
245 To send extension frame, use `nghttp2_submit_extension()`, and
246 implement :type:`nghttp2_pack_extension_callback`.  The callback
247 implements how to encode data into wire format.  The callback must be
248 set to :type:`nghttp2_session_callbacks` using
249 `nghttp2_session_callbacks_set_pack_extension_callback()`.
250
251 For example, we will illustrate how to send `ALTSVC
252 <https://tools.ietf.org/html/rfc7838>`_ frame.
253
254 .. code-block:: c
255
256     typedef struct {
257       const char *origin;
258       const char *field;
259     } alt_svc;
260
261     ssize_t pack_extension_callback(nghttp2_session *session, uint8_t *buf,
262                                     size_t len, const nghttp2_frame *frame,
263                                     void *user_data) {
264       const alt_svc *altsvc = (const alt_svc *)frame->ext.payload;
265       size_t originlen = strlen(altsvc->origin);
266       size_t fieldlen = strlen(altsvc->field);
267
268       uint8_t *p;
269
270       if (len < 2 + originlen + fieldlen || originlen > 0xffff) {
271         return NGHTTP2_ERR_CANCEL;
272       }
273
274       p = buf;
275       *p++ = originlen >> 8;
276       *p++ = originlen & 0xff;
277       memcpy(p, altsvc->origin, originlen);
278       p += originlen;
279       memcpy(p, altsvc->field, fieldlen);
280       p += fieldlen;
281
282       return p - buf;
283     }
284
285 This implements :type:`nghttp2_pack_extension_callback`.  We have to
286 set this callback to :type:`nghttp2_session_callbacks`:
287
288 .. code-block:: c
289
290     nghttp2_session_callbacks_set_pack_extension_callback(
291         callbacks, pack_extension_callback);
292
293 To send ALTSVC frame, call `nghttp2_submit_extension()`:
294
295 .. code-block:: c
296
297   static const alt_svc altsvc = {"example.com", "h2=\":8000\""};
298
299   nghttp2_submit_extension(session, 0xa, NGHTTP2_FLAG_NONE, 0,
300                            (void *)&altsvc);
301
302 Notice that ALTSVC is use frame type ``0xa``.
303
304 To receive extension frames, implement 2 callbacks:
305 :type:`nghttp2_unpack_extension_callback` and
306 :type:`nghttp2_on_extension_chunk_recv_callback`.
307 :type:`nghttp2_unpack_extension_callback` implements the way how to
308 decode wire format.  :type:`nghttp2_on_extension_chunk_recv_callback`
309 implements how to buffer the incoming extension payload.  These
310 callbacks must be set using
311 `nghttp2_session_callbacks_set_unpack_extension_callback()` and
312 `nghttp2_session_callbacks_set_on_extension_chunk_recv_callback()`
313 respectively.  The application also must tell the library which
314 extension frame type it is willing to receive using
315 `nghttp2_option_set_user_recv_extension_type()`.  Note that the
316 application has to create :type:`nghttp2_option` object for that
317 purpose, and initialize session with it.
318
319 We use ALTSVC again to illustrate how to receive extension frames.  We
320 use different ``alt_svc`` struct than the previous one.
321
322 First implement 2 callbacks.  We store incoming ALTSVC payload to
323 global variable ``altsvc_buffer``.  Don't do this in production code
324 since this is not thread safe:
325
326 .. code-block:: c
327
328     typedef struct {
329       const uint8_t *origin;
330       size_t originlen;
331       const uint8_t *field;
332       size_t fieldlen;
333     } alt_svc;
334
335     /* buffers incoming ALTSVC payload */
336     uint8_t altsvc_buffer[4096];
337     /* The length of byte written to altsvc_buffer */
338     size_t altsvc_bufferlen = 0;
339
340     int on_extension_chunk_recv_callback(nghttp2_session *session,
341                                          const nghttp2_frame_hd *hd,
342                                          const uint8_t *data, size_t len,
343                                          void *user_data) {
344       if (sizeof(altsvc_buffer) < altsvc_bufferlen + len) {
345         altsvc_bufferlen = 0;
346         return NGHTTP2_ERR_CANCEL;
347       }
348
349       memcpy(altsvc_buffer + altsvc_bufferlen, data, len);
350       altsvc_bufferlen += len;
351
352       return 0;
353     }
354
355     int unpack_extension_callback(nghttp2_session *session, void **payload,
356                                   const nghttp2_frame_hd *hd, void *user_data) {
357       uint8_t *origin, *field;
358       size_t originlen, fieldlen;
359       uint8_t *p, *end;
360       alt_svc *altsvc;
361
362       if (altsvc_bufferlen < 2) {
363         altsvc_bufferlen = 0;
364         return NGHTTP2_ERR_CANCEL;
365       }
366
367       p = altsvc_buffer;
368       end = altsvc_buffer + altsvc_bufferlen;
369
370       originlen = ((*p) << 8) + *(p + 1);
371       p += 2;
372
373       if (p + originlen > end) {
374         altsvc_bufferlen = 0;
375         return NGHTTP2_ERR_CANCEL;
376       }
377
378       origin = p;
379       field = p + originlen;
380       fieldlen = end - field;
381
382       altsvc = (alt_svc *)malloc(sizeof(alt_svc));
383       altsvc->origin = origin;
384       altsvc->originlen = originlen;
385       altsvc->field = field;
386       altsvc->fieldlen = fieldlen;
387
388       *payload = altsvc;
389
390       altsvc_bufferlen = 0;
391
392       return 0;
393     }
394
395 Set these callbacks to :type:`nghttp2_session_callbacks`:
396
397 .. code-block:: c
398
399     nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
400         callbacks, on_extension_chunk_recv_callback);
401
402     nghttp2_session_callbacks_set_unpack_extension_callback(
403         callbacks, unpack_extension_callback);
404
405
406 In ``unpack_extension_callback`` above, we set unpacked ``alt_svc``
407 object to ``*payload``.  nghttp2 library then, calls
408 :type:`nghttp2_on_frame_recv_callback`, and ``*payload`` will be
409 available as ``frame->ext.payload``:
410
411 .. code-block:: c
412
413     int on_frame_recv_callback(nghttp2_session *session,
414                                const nghttp2_frame *frame, void *user_data) {
415
416       switch (frame->hd.type) {
417       ...
418       case 0xa: {
419         alt_svc *altsvc = (alt_svc *)frame->ext.payload;
420         fprintf(stderr, "ALTSVC frame received\n");
421         fprintf(stderr, " origin: %.*s\n", (int)altsvc->originlen, altsvc->origin);
422         fprintf(stderr, " field : %.*s\n", (int)altsvc->fieldlen, altsvc->field);
423         free(altsvc);
424         break;
425       }
426       }
427
428       return 0;
429     }
430
431 Finally, application should set the extension frame types it is
432 willing to receive:
433
434 .. code-block:: c
435
436     nghttp2_option_set_user_recv_extension_type(option, 0xa);
437
438 The :type:`nghttp2_option` must be set to :type:`nghttp2_session` on
439 its creation:
440
441 .. code-block:: c
442
443     nghttp2_session_client_new2(&session, callbacks, user_data, option);
444
445 How to use built-in HTTP/2 extension frame handlers
446 ---------------------------------------------------
447
448 In the previous section, we talked about the user defined HTTP/2
449 extension frames.  In this section, we talk about HTTP/2 extension
450 frame support built into nghttp2 library.
451
452 As of this writing, nghttp2 supports ALTSVC extension frame.  To send
453 ALTSVC frame, use `nghttp2_submit_altsvc()` function.
454
455 To receive ALTSVC frame through built-in functionality, application
456 has to use `nghttp2_option_set_builtin_recv_extension_type()` to
457 indicate the willingness of receiving ALTSVC frame:
458
459 .. code-block:: c
460
461     nghttp2_option_set_builtin_recv_extension_type(option, NGHTTP2_ALTSVC);
462
463 This is very similar to the case when we used to receive user defined
464 frames.
465
466 If the same frame type is set using
467 `nghttp2_option_set_builtin_recv_extension_type()` and
468 `nghttp2_option_set_user_recv_extension_type()`, the latter takes
469 precedence.  Application can implement its own frame handler rather
470 than using built-in handler.
471
472 The :type:`nghttp2_option` must be set to :type:`nghttp2_session` on
473 its creation, like so:
474
475 .. code-block:: c
476
477     nghttp2_session_client_new2(&session, callbacks, user_data, option);
478
479 When ALTSVC is received, :type:`nghttp2_on_frame_recv_callback` will
480 be called as usual.
481