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.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-02-20 23:26:56 +09:00
parent b3846d6c27
commit e45c523dc7
5 changed files with 43 additions and 16 deletions

View File

@ -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 briefly describe what the library does in this area. In the following
description, without loss of generality we omit CONTINUATION frame description, without loss of generality we omit CONTINUATION frame
since they must follow HEADERS frame and are processed atomically. In 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 For HTTP request, including those carried by PUSH_PROMISE, HTTP
message starts with one HEADERS frame containing request headers. It 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. <https://tools.ietf.org/html/rfc7230#section-3.2>`_. 3.2. <https://tools.ietf.org/html/rfc7230#section-3.2>`_.
Additionally, all field name must be lower cased. 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 nghttp2 enforces "Content-Length" validation as well. All request or
response headers must not contain more than one "Content-Length" response headers must not contain more than one "Content-Length"
header field. If "Content-Length" header field is present, it must be header field. If "Content-Length" header field is present, it must be

View File

@ -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 * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be
* invoked. * invoked.
* *
* The |name| may be ``NULL`` if the |namelen| is 0. The same thing * The |value| may be ``NULL`` if the |valuelen| is 0.
* can be said about the |value|.
* *
* Please note that nghttp2 library does not perform any validity * Please note that unless `nghttp2_option_set_no_http_messaging()` is
* check against the |name| and the |value|. For example, the * used, nghttp2 library does perform validation against the |name|
* |namelen| could be 0, and/or the |value| contains ``0x0a`` or * and the |value| using `nghttp2_check_header_name()` and
* ``0x0d``. The application must check them if it matters. The * `nghttp2_check_header_value()`. In addition to this, nghttp2
* helper function `nghttp2_check_header_name()` and * performs vaidation based on HTTP Messaging rule, which is briefly
* `nghttp2_check_header_value()` provide simple validation against * explained in `HTTP Messaging`_ section.
* 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.
* *
* If the application uses `nghttp2_session_mem_recv()`, it can return * If the application uses `nghttp2_session_mem_recv()`, it can return
* :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()` * :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); 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
* <https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#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 * @function
* *

View File

@ -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->opt_set_mask |= NGHTTP2_OPT_RECV_CLIENT_PREFACE;
option->recv_client_preface = val; 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;
}

View File

@ -58,6 +58,7 @@ typedef enum {
*/ */
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1, NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS = 1 << 1,
NGHTTP2_OPT_RECV_CLIENT_PREFACE = 1 << 2, NGHTTP2_OPT_RECV_CLIENT_PREFACE = 1 << 2,
NGHTTP2_OPT_NO_HTTP_MESSAGING = 1 << 3,
} nghttp2_option_flag; } nghttp2_option_flag;
/** /**
@ -81,6 +82,10 @@ struct nghttp2_option {
* NGHTTP2_OPT_RECV_CLIENT_PREFACE * NGHTTP2_OPT_RECV_CLIENT_PREFACE
*/ */
uint8_t recv_client_preface; uint8_t recv_client_preface;
/**
* NGHTTP2_OPT_NO_HTTP_MESSAGING
*/
uint8_t no_http_messaging;
}; };
#endif /* NGHTTP2_OPTION_H */ #endif /* NGHTTP2_OPTION_H */

View File

@ -414,10 +414,17 @@ static int session_new(nghttp2_session **session_ptr,
option->peer_max_concurrent_streams; 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; (*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; (*session_ptr)->callbacks = *callbacks;