[PATCH 3 of 3] HTTP/2: "http2" directive
Roman Arutyunyan
arut at nginx.com
Thu Jan 26 11:50:47 UTC 2023
# HG changeset patch
# User Roman Arutyunyan <arut at nginx.com>
# Date 1674649725 -14400
# Wed Jan 25 16:28:45 2023 +0400
# Branch quic
# Node ID 819737783463d7e38ea80109a976db1d3a9bb2db
# Parent 555913c358221f647bbace26165bef5eb614add4
HTTP/2: "http2" directive.
The directive enables HTTP/2 in the current server. The previous way to
enable HTTP/2 via "listen ... http2" is now deprecated.
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -427,6 +427,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t
#if (NGX_HTTP_V2 || NGX_HTTP_V3)
ngx_http_connection_t *hc;
#endif
+#if (NGX_HTTP_V2)
+ ngx_http_v2_srv_conf_t *h2scf;
+#endif
#if (NGX_HTTP_V3)
ngx_http_v3_srv_conf_t *h3scf;
#endif
@@ -448,12 +451,9 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t
hc = c->data;
#endif
-#if (NGX_HTTP_V2)
- if (hc->addr_conf->http2) {
- srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS;
- srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1;
- } else
-#endif
+ srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS;
+ srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1;
+
#if (NGX_HTTP_V3)
if (hc->addr_conf->quic) {
@@ -479,10 +479,16 @@ ngx_http_ssl_alpn_select(ngx_ssl_conn_t
} else
#endif
+#if (NGX_HTTP_V2)
{
- srv = (unsigned char *) NGX_HTTP_ALPN_PROTOS;
- srvlen = sizeof(NGX_HTTP_ALPN_PROTOS) - 1;
+ h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
+
+ if (hc->addr_conf->http2 || h2scf->enable) {
+ srv = (unsigned char *) NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS;
+ srvlen = sizeof(NGX_HTTP_V2_ALPN_PROTO NGX_HTTP_ALPN_PROTOS) - 1;
+ }
}
+#endif
if (SSL_select_next_proto((unsigned char **) out, outlen, srv, srvlen,
in, inlen)
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -4179,6 +4179,11 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
if (ngx_strcmp(value[n].data, "http2") == 0) {
#if (NGX_HTTP_V2)
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "the \"listen ... http2\" directive "
+ "is deprecated, use "
+ "the \"http2\" directive instead");
+
lsopt.http2 = 1;
continue;
#else
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -52,6 +52,10 @@ static u_char *ngx_http_log_error(ngx_lo
static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
ngx_http_request_t *sr, u_char *buf, size_t len);
+#if (NGX_HTTP_V2)
+static void ngx_http_try_v2(ngx_event_t *rev);
+#endif
+
#if (NGX_HTTP_SSL)
static void ngx_http_ssl_handshake(ngx_event_t *rev);
static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
@@ -319,8 +323,14 @@ ngx_http_init_connection(ngx_connection_
c->write->handler = ngx_http_empty_handler;
#if (NGX_HTTP_V2)
- if (hc->addr_conf->http2) {
- rev->handler = ngx_http_v2_init;
+ {
+ ngx_http_v2_srv_conf_t *h2scf;
+
+ h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
+
+ if (h2scf->enable || hc->addr_conf->http2) {
+ rev->handler = ngx_http_try_v2;
+ }
}
#endif
@@ -638,6 +648,113 @@ ngx_http_alloc_request(ngx_connection_t
}
+#if (NGX_HTTP_V2)
+
+static void
+ngx_http_try_v2(ngx_event_t *rev)
+{
+ u_char *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
+ size_t size;
+ ssize_t n;
+ ngx_err_t err;
+ ngx_connection_t *c;
+ ngx_http_connection_t *hc;
+ ngx_http_core_srv_conf_t *cscf;
+
+ c = rev->data;
+ hc = c->data;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http check v2");
+
+ if (rev->timedout) {
+ ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ if (c->close) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ size = hc->proxy_protocol ? sizeof(buf) : 1;
+
+ n = recv(c->fd, (char *) buf, size, MSG_PEEK);
+
+ err = ngx_socket_errno;
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %z", n);
+
+ if (n == -1) {
+ if (err == NGX_EAGAIN) {
+ rev->ready = 0;
+
+ if (!rev->timer_set) {
+ cscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
+ ngx_http_core_module);
+ ngx_add_timer(rev, cscf->client_header_timeout);
+ ngx_reusable_connection(c, 1);
+ }
+
+ if (ngx_handle_read_event(rev, 0) != NGX_OK) {
+ ngx_http_close_connection(c);
+ }
+
+ return;
+ }
+
+ ngx_connection_error(c, err, "recv() failed");
+ ngx_http_close_connection(c);
+
+ return;
+ }
+
+ if (hc->proxy_protocol) {
+ hc->proxy_protocol = 0;
+
+ p = ngx_proxy_protocol_read(c, buf, buf + n);
+
+ if (p == NULL) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ size = p - buf;
+
+ if (c->recv(c, buf, size) != (ssize_t) size) {
+ ngx_http_close_connection(c);
+ return;
+ }
+
+ if (n == (ssize_t) size) {
+ ngx_post_event(rev, &ngx_posted_events);
+ return;
+ }
+
+ n = 1;
+ buf[0] = *p;
+ }
+
+ if (n == 1) {
+ if (buf[0] == 'P') {
+ /* looks like HTTP/2 preface */
+ ngx_http_v2_init(rev);
+ return;
+ }
+
+ rev->handler = ngx_http_wait_request_handler;
+ ngx_http_wait_request_handler(rev);
+
+ return;
+ }
+
+ ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
+ ngx_http_close_connection(c);
+}
+
+#endif
+
+
#if (NGX_HTTP_SSL)
static void
@@ -808,13 +925,16 @@ ngx_http_ssl_handshake_handler(ngx_conne
#if (NGX_HTTP_V2 \
&& defined TLSEXT_TYPE_application_layer_protocol_negotiation)
{
- unsigned int len;
- const unsigned char *data;
- ngx_http_connection_t *hc;
+ unsigned int len;
+ const unsigned char *data;
+ ngx_http_connection_t *hc;
+ ngx_http_v2_srv_conf_t *h2scf;
hc = c->data;
- if (hc->addr_conf->http2) {
+ h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module);
+
+ if (h2scf->enable || hc->addr_conf->http2) {
SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
diff --git a/src/http/v2/ngx_http_v2.h b/src/http/v2/ngx_http_v2.h
--- a/src/http/v2/ngx_http_v2.h
+++ b/src/http/v2/ngx_http_v2.h
@@ -64,6 +64,16 @@ typedef u_char *(*ngx_http_v2_handler_pt
typedef struct {
+ ngx_flag_t enable;
+ size_t pool_size;
+ ngx_uint_t concurrent_streams;
+ ngx_uint_t concurrent_pushes;
+ size_t preread_size;
+ ngx_uint_t streams_index_mask;
+} ngx_http_v2_srv_conf_t;
+
+
+typedef struct {
ngx_str_t name;
ngx_str_t value;
} ngx_http_v2_header_t;
@@ -413,4 +423,7 @@ u_char *ngx_http_v2_string_encode(u_char
u_char *tmp, ngx_uint_t lower);
+extern ngx_module_t ngx_http_v2_module;
+
+
#endif /* _NGX_HTTP_V2_H_INCLUDED_ */
diff --git a/src/http/v2/ngx_http_v2_module.c b/src/http/v2/ngx_http_v2_module.c
--- a/src/http/v2/ngx_http_v2_module.c
+++ b/src/http/v2/ngx_http_v2_module.c
@@ -75,6 +75,13 @@ static ngx_conf_post_t ngx_http_v2_chun
static ngx_command_t ngx_http_v2_commands[] = {
+ { ngx_string("http2"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_SRV_CONF_OFFSET,
+ offsetof(ngx_http_v2_srv_conf_t, enable),
+ NULL },
+
{ ngx_string("http2_recv_buffer_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
@@ -314,6 +321,8 @@ ngx_http_v2_create_srv_conf(ngx_conf_t *
return NULL;
}
+ h2scf->enable = NGX_CONF_UNSET;
+
h2scf->pool_size = NGX_CONF_UNSET_SIZE;
h2scf->concurrent_streams = NGX_CONF_UNSET_UINT;
@@ -333,6 +342,8 @@ ngx_http_v2_merge_srv_conf(ngx_conf_t *c
ngx_http_v2_srv_conf_t *prev = parent;
ngx_http_v2_srv_conf_t *conf = child;
+ ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
ngx_conf_merge_size_value(conf->pool_size, prev->pool_size, 4096);
ngx_conf_merge_uint_value(conf->concurrent_streams,
diff --git a/src/http/v2/ngx_http_v2_module.h b/src/http/v2/ngx_http_v2_module.h
--- a/src/http/v2/ngx_http_v2_module.h
+++ b/src/http/v2/ngx_http_v2_module.h
@@ -21,15 +21,6 @@ typedef struct {
typedef struct {
- size_t pool_size;
- ngx_uint_t concurrent_streams;
- ngx_uint_t concurrent_pushes;
- size_t preread_size;
- ngx_uint_t streams_index_mask;
-} ngx_http_v2_srv_conf_t;
-
-
-typedef struct {
size_t chunk_size;
ngx_flag_t push_preload;
@@ -39,7 +30,4 @@ typedef struct {
} ngx_http_v2_loc_conf_t;
-extern ngx_module_t ngx_http_v2_module;
-
-
#endif /* _NGX_HTTP_V2_MODULE_H_INCLUDED_ */
More information about the nginx-devel
mailing list