From e45c523dc72de55b9734e3c9d63972d37d4f3345 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Fri, 20 Feb 2015 23:26:56 +0900 Subject: [PATCH] Add nghttp2_option_set_no_http_messaging() API function This API function with nonzero |val| parameter disables HTTP Messaging validation in nghttp2 library, so that application can use nghttp2 library for non-HTTP use. --- doc/apiref-header.rst | 7 ++++++- lib/includes/nghttp2/nghttp2.h | 33 +++++++++++++++++++-------------- lib/nghttp2_option.c | 5 +++++ lib/nghttp2_option.h | 5 +++++ lib/nghttp2_session.c | 9 ++++++++- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/doc/apiref-header.rst b/doc/apiref-header.rst index fcaaf8ce..79542028 100644 --- a/doc/apiref-header.rst +++ b/doc/apiref-header.rst @@ -42,7 +42,8 @@ Everything described in that section is not validated however. We briefly describe what the library does in this area. In the following description, without loss of generality we omit CONTINUATION frame since they must follow HEADERS frame and are processed atomically. In -other words, they are just one big HEADERS frame. +other words, they are just one big HEADERS frame. To disable these +validations, use `nghttp2_option_set_no_http_messaging()`. For HTTP request, including those carried by PUSH_PROMISE, HTTP message starts with one HEADERS frame containing request headers. It @@ -72,6 +73,10 @@ field-value production rules described in `RFC 7230, section 3.2. `_. Additionally, all field name must be lower cased. +With the above validations, nghttp2 library guarantees that header +field name passed to `nghttp2_on_header_callback()` is not empty. +Also required pseudo headers are all present and not empty. + nghttp2 enforces "Content-Length" validation as well. All request or response headers must not contain more than one "Content-Length" header field. If "Content-Length" header field is present, it must be diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index ebcbccea..fe4a357a 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -1408,21 +1408,14 @@ typedef int (*nghttp2_on_begin_headers_callback)(nghttp2_session *session, * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be * invoked. * - * The |name| may be ``NULL`` if the |namelen| is 0. The same thing - * can be said about the |value|. + * The |value| may be ``NULL`` if the |valuelen| is 0. * - * Please note that nghttp2 library does not perform any validity - * check against the |name| and the |value|. For example, the - * |namelen| could be 0, and/or the |value| contains ``0x0a`` or - * ``0x0d``. The application must check them if it matters. The - * helper function `nghttp2_check_header_name()` and - * `nghttp2_check_header_value()` provide simple validation against - * HTTP2 header field construction rule. - * - * HTTP/2 specification requires that pseudo header fields (header - * field starting with ':') must appear in front of regular header - * fields. The library does not validate this requirement. The - * application must check them if it matters. + * Please note that unless `nghttp2_option_set_no_http_messaging()` is + * used, nghttp2 library does perform validation against the |name| + * and the |value| using `nghttp2_check_header_name()` and + * `nghttp2_check_header_value()`. In addition to this, nghttp2 + * performs vaidation based on HTTP Messaging rule, which is briefly + * explained in `HTTP Messaging`_ section. * * If the application uses `nghttp2_session_mem_recv()`, it can return * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` @@ -1890,6 +1883,18 @@ void nghttp2_option_set_peer_max_concurrent_streams(nghttp2_option *option, */ void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val); +/** + * @function + * + * By default, nghttp2 library enforces subset of HTTP Messaging rules + * described in `HTTP/2 specification, section 8 + * `_. + * See `HTTP Messaging`_ section for details. For those applications + * who use nghttp2 library as non-HTTP use, give nonzero to |val| to + * disable this enforcement. + */ +void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val); + /** * @function * diff --git a/lib/nghttp2_option.c b/lib/nghttp2_option.c index 3acb0b99..db2a27aa 100644 --- a/lib/nghttp2_option.c +++ b/lib/nghttp2_option.c @@ -51,3 +51,8 @@ void nghttp2_option_set_recv_client_preface(nghttp2_option *option, int val) { option->opt_set_mask |= NGHTTP2_OPT_RECV_CLIENT_PREFACE; option->recv_client_preface = val; } + +void nghttp2_option_set_no_http_messaging(nghttp2_option *option, int val) { + option->opt_set_mask |= NGHTTP2_OPT_NO_HTTP_MESSAGING; + option->no_http_messaging = val; +} diff --git a/lib/nghttp2_option.h b/lib/nghttp2_option.h index c9f2d92e..db94be55 100644 --- a/lib/nghttp2_option.h +++ b/lib/nghttp2_option.h @@ -58,6 +58,7 @@ typedef enum { */ NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1, NGHTTP2_OPT_RECV_CLIENT_PREFACE = 1 << 2, + NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3, } nghttp2_option_flag; /** @@ -81,6 +82,10 @@ struct nghttp2_option { * NGHTTP2_OPT_RECV_CLIENT_PREFACE */ uint8_t recv_client_preface; + /** + * NGHTTP2_OPT_NO_HTTP_MESSAGING + */ + uint8_t no_http_messaging; }; #endif /* NGHTTP2_OPTION_H */ diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index de06c5a4..1642e5f3 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -414,10 +414,17 @@ static int session_new(nghttp2_session **session_ptr, option->peer_max_concurrent_streams; } - if (option->opt_set_mask & NGHTTP2_OPT_RECV_CLIENT_PREFACE) { + if ((option->opt_set_mask & NGHTTP2_OPT_RECV_CLIENT_PREFACE) && + option->recv_client_preface) { (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_RECV_CLIENT_PREFACE; } + + if ((option->opt_set_mask & NGHTTP2_OPT_NO_HTTP_MESSAGING) && + option->no_http_messaging) { + + (*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_HTTP_MESSAGING; + } } (*session_ptr)->callbacks = *callbacks;