From d23f77b028d6fa1943c0837e0e6d1684a45fc666 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Mon, 5 Apr 2021 04:03:10 +0300 Subject: Version bump. --- src/core/nginx.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/nginx.h b/src/core/nginx.h index ba70b4ceb..8a3560179 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1019009 -#define NGINX_VERSION "1.19.9" +#define nginx_version 1019010 +#define NGINX_VERSION "1.19.10" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD -- cgit From e3797a66a3d8213b5c34cafca5a8882b152fc2c2 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Mon, 5 Apr 2021 04:06:58 +0300 Subject: Gzip: support for zlib-ng. --- src/http/modules/ngx_http_gzip_filter_module.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index c75169c53..59cbad745 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -57,6 +57,7 @@ typedef struct { unsigned nomem:1; unsigned buffering:1; unsigned intel:1; + unsigned zlib_ng:1; size_t zin; size_t zout; @@ -214,6 +215,7 @@ static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; static ngx_uint_t ngx_http_gzip_assume_intel; +static ngx_uint_t ngx_http_gzip_assume_zlib_ng; static ngx_int_t @@ -506,7 +508,7 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) if (!ngx_http_gzip_assume_intel) { ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9)); - } else { + } else if (!ngx_http_gzip_assume_zlib_ng) { /* * A zlib variant from Intel, https://github.com/jtkukunas/zlib. * It can force window bits to 13 for fast compression level, @@ -523,6 +525,20 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) + (1 << (ngx_max(memlevel, 8) + 8)) + (1 << (memlevel + 8)); ctx->intel = 1; + + } else { + /* + * Another zlib variant, https://github.com/zlib-ng/zlib-ng. + * Similar to Intel's variant, though uses 128K hash. + */ + + if (conf->level == 1) { + wbits = ngx_max(wbits, 13); + } + + ctx->allocated = 8192 + 16 + (1 << (wbits + 2)) + + 131072 + (1 << (memlevel + 8)); + ctx->zlib_ng = 1; } } @@ -945,11 +961,14 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size) return p; } - if (ctx->intel) { + if (ctx->zlib_ng) { ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0, "gzip filter failed to use preallocated memory: " "%ud of %ui", items * size, ctx->allocated); + } else if (ctx->intel) { + ngx_http_gzip_assume_zlib_ng = 1; + } else { ngx_http_gzip_assume_intel = 1; } -- cgit From 4af67214ad3d7f0f525bea777d5a43aa7a702ecf Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Mon, 5 Apr 2021 04:07:17 +0300 Subject: Gzip: updated handling of zlib variant from Intel. In current versions (all versions based on zlib 1.2.11, at least since 2018) it no longer uses 64K hash and does not force window bits to 13 if it is less than 13. That is, it needs just 16 bytes more memory than normal zlib, so these bytes are simply added to the normal size calculation. --- src/http/modules/ngx_http_gzip_filter_module.c | 35 +++++++------------------- 1 file changed, 9 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c index 59cbad745..b8c5ccc5c 100644 --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -56,7 +56,6 @@ typedef struct { unsigned done:1; unsigned nomem:1; unsigned buffering:1; - unsigned intel:1; unsigned zlib_ng:1; size_t zin; @@ -214,7 +213,6 @@ static ngx_str_t ngx_http_gzip_ratio = ngx_string("gzip_ratio"); static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_http_output_body_filter_pt ngx_http_next_body_filter; -static ngx_uint_t ngx_http_gzip_assume_intel; static ngx_uint_t ngx_http_gzip_assume_zlib_ng; @@ -503,33 +501,21 @@ ngx_http_gzip_filter_memory(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx) * 8K is for zlib deflate_state, it takes * *) 5816 bytes on i386 and sparc64 (32-bit mode) * *) 5920 bytes on amd64 and sparc64 + * + * A zlib variant from Intel (https://github.com/jtkukunas/zlib) + * uses additional 16-byte padding in one of window-sized buffers. */ - if (!ngx_http_gzip_assume_intel) { - ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9)); - - } else if (!ngx_http_gzip_assume_zlib_ng) { - /* - * A zlib variant from Intel, https://github.com/jtkukunas/zlib. - * It can force window bits to 13 for fast compression level, - * on processors with SSE 4.2 it uses 64K hash instead of scaling - * it from the specified memory level, and also introduces - * 16-byte padding in one out of the two window-sized buffers. - */ - - if (conf->level == 1) { - wbits = ngx_max(wbits, 13); - } - + if (!ngx_http_gzip_assume_zlib_ng) { ctx->allocated = 8192 + 16 + (1 << (wbits + 2)) - + (1 << (ngx_max(memlevel, 8) + 8)) - + (1 << (memlevel + 8)); - ctx->intel = 1; + + (1 << (memlevel + 9)); } else { /* * Another zlib variant, https://github.com/zlib-ng/zlib-ng. - * Similar to Intel's variant, though uses 128K hash. + * It forces window bits to 13 for fast compression level, + * uses 16-byte padding in one of window-sized buffers, and + * uses 128K hash. */ if (conf->level == 1) { @@ -966,11 +952,8 @@ ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size) "gzip filter failed to use preallocated memory: " "%ud of %ui", items * size, ctx->allocated); - } else if (ctx->intel) { - ngx_http_gzip_assume_zlib_ng = 1; - } else { - ngx_http_gzip_assume_intel = 1; + ngx_http_gzip_assume_zlib_ng = 1; } p = ngx_palloc(ctx->request->pool, items * size); -- cgit From 5599731c00bd152f765c7cea24a7d257bf13320c Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Wed, 7 Apr 2021 02:03:29 +0300 Subject: HTTP/2: relaxed PRIORITY frames limit. Firefox uses several idle streams for PRIORITY frames[1], and "http2_max_concurrent_streams 1;" results in "client sent too many PRIORITY frames" errors when a connection is established by Firefox. Fix is to relax the PRIORITY frames limit to use at least 100 as the initial value (which is the recommended by the HTTP/2 protocol minimum limit on the number of concurrent streams, so it is not unreasonable for clients to assume that similar number of idle streams can be used for prioritization). [1] https://hg.mozilla.org/mozilla-central/file/32a9e6e145d6e3071c3993a20bb603a2f388722b/netwerk/protocol/http/Http2Stream.cpp#l1270 --- src/http/v2/ngx_http_v2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 856320589..69a94b6ee 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -277,7 +277,7 @@ ngx_http_v2_init(ngx_event_t *rev) h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); h2c->concurrent_pushes = h2scf->concurrent_pushes; - h2c->priority_limit = h2scf->concurrent_streams; + h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); if (h2c->pool == NULL) { -- cgit From d9996d6f27150bfb9c9c00d77fac940712aa1d28 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Thu, 8 Apr 2021 00:15:48 +0300 Subject: Introduced the "keepalive_time" directive. Similar to lingering_time, it limits total connection lifetime before keepalive is switched off. The default is 1 hour, which is close to the total maximum connection lifetime possible with default keepalive_requests and keepalive_timeout. --- src/core/ngx_connection.h | 1 + src/core/ngx_resolver.c | 4 ++++ src/event/ngx_event_accept.c | 2 ++ src/event/ngx_event_acceptex.c | 2 ++ src/event/ngx_event_connect.c | 2 ++ src/event/ngx_event_udp.c | 2 ++ src/http/modules/ngx_http_upstream_keepalive_module.c | 14 ++++++++++++++ src/http/ngx_http_core_module.c | 15 +++++++++++++++ src/http/ngx_http_core_module.h | 1 + src/http/v2/ngx_http_v2.c | 4 +++- 10 files changed, 46 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index 9d8ac46d2..4716da492 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -162,6 +162,7 @@ struct ngx_connection_s { ngx_atomic_uint_t number; + ngx_msec_t start_time; ngx_uint_t requests; unsigned buffered:8; diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 49616b776..793907010 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -4459,6 +4459,8 @@ ngx_udp_connect(ngx_resolver_connection_t *rec) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + c->start_time = ngx_current_msec; + ngx_log_debug3(NGX_LOG_DEBUG_EVENT, &rec->log, 0, "connect to %V, fd:%d #%uA", &rec->server, s, c->number); @@ -4545,6 +4547,8 @@ ngx_tcp_connect(ngx_resolver_connection_t *rec) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + c->start_time = ngx_current_msec; + if (ngx_add_conn) { if (ngx_add_conn(c) == NGX_ERROR) { goto failed; diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 436424093..b05666c76 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -256,6 +256,8 @@ ngx_event_accept(ngx_event_t *ev) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + c->start_time = ngx_current_msec; + #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); #endif diff --git a/src/event/ngx_event_acceptex.c b/src/event/ngx_event_acceptex.c index 1999faf20..f4a1c4b2b 100644 --- a/src/event/ngx_event_acceptex.c +++ b/src/event/ngx_event_acceptex.c @@ -80,6 +80,8 @@ ngx_event_acceptex(ngx_event_t *rev) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + c->start_time = ngx_current_msec; + ls->handler(c); return; diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c index 1ffa7984c..adbbde633 100644 --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -193,6 +193,8 @@ ngx_event_connect_peer(ngx_peer_connection_t *pc) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + c->start_time = ngx_current_msec; + if (ngx_add_conn) { if (ngx_add_conn(c) == NGX_ERROR) { goto failed; diff --git a/src/event/ngx_event_udp.c b/src/event/ngx_event_udp.c index 557283050..a524ae04d 100644 --- a/src/event/ngx_event_udp.c +++ b/src/event/ngx_event_udp.c @@ -363,6 +363,8 @@ ngx_event_recvmsg(ngx_event_t *ev) c->number = ngx_atomic_fetch_add(ngx_connection_counter, 1); + c->start_time = ngx_current_msec; + #if (NGX_STAT_STUB) (void) ngx_atomic_fetch_add(ngx_stat_handled, 1); #endif diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c index 1560807c6..bbd650b79 100644 --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -13,6 +13,7 @@ typedef struct { ngx_uint_t max_cached; ngx_uint_t requests; + ngx_msec_t time; ngx_msec_t timeout; ngx_queue_t cache; @@ -86,6 +87,13 @@ static ngx_command_t ngx_http_upstream_keepalive_commands[] = { 0, NULL }, + { ngx_string("keepalive_time"), + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_upstream_keepalive_srv_conf_t, time), + NULL }, + { ngx_string("keepalive_timeout"), NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, @@ -149,6 +157,7 @@ ngx_http_upstream_init_keepalive(ngx_conf_t *cf, kcf = ngx_http_conf_upstream_srv_conf(us, ngx_http_upstream_keepalive_module); + ngx_conf_init_msec_value(kcf->time, 3600000); ngx_conf_init_msec_value(kcf->timeout, 60000); ngx_conf_init_uint_value(kcf->requests, 100); @@ -326,6 +335,10 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data, goto invalid; } + if (ngx_current_msec - c->start_time > kp->conf->time) { + goto invalid; + } + if (!u->keepalive) { goto invalid; } @@ -513,6 +526,7 @@ ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf) * conf->max_cached = 0; */ + conf->time = NGX_CONF_UNSET_MSEC; conf->timeout = NGX_CONF_UNSET_MSEC; conf->requests = NGX_CONF_UNSET_UINT; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 9b94b328e..9dda27a10 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -495,6 +495,13 @@ static ngx_command_t ngx_http_core_commands[] = { offsetof(ngx_http_core_loc_conf_t, limit_rate_after), NULL }, + { ngx_string("keepalive_time"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, keepalive_time), + NULL }, + { ngx_string("keepalive_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12, ngx_http_core_keepalive, @@ -1335,6 +1342,11 @@ ngx_http_update_location_config(ngx_http_request_t *r) } else if (r->connection->requests >= clcf->keepalive_requests) { r->keepalive = 0; + } else if (ngx_current_msec - r->connection->start_time + > clcf->keepalive_time) + { + r->keepalive = 0; + } else if (r->headers_in.msie6 && r->method == NGX_HTTP_POST && (clcf->keepalive_disable @@ -3500,6 +3512,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf) clcf->send_timeout = NGX_CONF_UNSET_MSEC; clcf->send_lowat = NGX_CONF_UNSET_SIZE; clcf->postpone_output = NGX_CONF_UNSET_SIZE; + clcf->keepalive_time = NGX_CONF_UNSET_MSEC; clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC; clcf->keepalive_header = NGX_CONF_UNSET; clcf->keepalive_requests = NGX_CONF_UNSET_UINT; @@ -3738,6 +3751,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) conf->limit_rate_after = prev->limit_rate_after; } + ngx_conf_merge_msec_value(conf->keepalive_time, + prev->keepalive_time, 3600000); ngx_conf_merge_msec_value(conf->keepalive_timeout, prev->keepalive_timeout, 75000); ngx_conf_merge_sec_value(conf->keepalive_header, diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h index 2aadae7ff..2341fd463 100644 --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -359,6 +359,7 @@ struct ngx_http_core_loc_conf_s { ngx_msec_t client_body_timeout; /* client_body_timeout */ ngx_msec_t send_timeout; /* send_timeout */ + ngx_msec_t keepalive_time; /* keepalive_time */ ngx_msec_t keepalive_timeout; /* keepalive_timeout */ ngx_msec_t lingering_time; /* lingering_time */ ngx_msec_t lingering_timeout; /* lingering_timeout */ diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c index 69a94b6ee..3611a2e50 100644 --- a/src/http/v2/ngx_http_v2.c +++ b/src/http/v2/ngx_http_v2.c @@ -1369,7 +1369,9 @@ ngx_http_v2_state_headers(ngx_http_v2_connection_t *h2c, u_char *pos, ngx_http_core_module); if (clcf->keepalive_timeout == 0 - || h2c->connection->requests >= clcf->keepalive_requests) + || h2c->connection->requests >= clcf->keepalive_requests + || ngx_current_msec - h2c->connection->start_time + > clcf->keepalive_time) { h2c->goaway = 1; -- cgit From 497acbd0ed4b3f289bde11de207efb0abd1f6fa6 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Thu, 8 Apr 2021 00:16:17 +0300 Subject: Added $connection_time variable. --- src/http/ngx_http_variables.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'src') diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index c2113c843..c25d80ccf 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -129,6 +129,8 @@ static ngx_int_t ngx_http_variable_connection(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_connection_requests(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_connection_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -342,6 +344,9 @@ static ngx_http_variable_t ngx_http_core_variables[] = { { ngx_string("connection_requests"), NULL, ngx_http_variable_connection_requests, 0, 0, 0 }, + { ngx_string("connection_time"), NULL, ngx_http_variable_connection_time, + 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 0, 0, 0 }, @@ -2252,6 +2257,31 @@ ngx_http_variable_connection_requests(ngx_http_request_t *r, } +static ngx_int_t +ngx_http_variable_connection_time(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + u_char *p; + ngx_msec_int_t ms; + + p = ngx_pnalloc(r->pool, NGX_TIME_T_LEN + 4); + if (p == NULL) { + return NGX_ERROR; + } + + ms = ngx_current_msec - r->connection->start_time; + ms = ngx_max(ms, 0); + + v->len = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000) - p; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) -- cgit From eb52de83114e8d98722cd17ec8435c47956b6315 Mon Sep 17 00:00:00 2001 From: Maxim Dounin Date: Thu, 8 Apr 2021 00:16:30 +0300 Subject: Changed keepalive_requests default to 1000 (ticket #2155). It turns out no browsers implement HTTP/2 GOAWAY handling properly, and large enough number of resources on a page results in failures to load some resources. In particular, Chrome seems to experience errors if loading of all resources requires more than 1 connection (while it is usually able to retry requests at least once, even with 2 connections there are occasional failures for some reason), Safari if loading requires more than 3 connections, and Firefox if loading requires more than 10 connections (can be configured with network.http.request.max-attempts, defaults to 10). It does not seem to be possible to resolve this on nginx side, even strict limiting of maximum concurrency does not help, and loading issues seems to be triggered by merely queueing of a request for a particular connection. The only available mitigation seems to use higher keepalive_requests value. The new default is 1000 and matches previously used default for http2_max_requests. It is expected to be enough for 99.98% of the pages (https://httparchive.org/reports/state-of-the-web?start=latest#reqTotal) even in Chrome. --- src/http/modules/ngx_http_upstream_keepalive_module.c | 2 +- src/http/ngx_http_core_module.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c index bbd650b79..1a4dfd776 100644 --- a/src/http/modules/ngx_http_upstream_keepalive_module.c +++ b/src/http/modules/ngx_http_upstream_keepalive_module.c @@ -159,7 +159,7 @@ ngx_http_upstream_init_keepalive(ngx_conf_t *cf, ngx_conf_init_msec_value(kcf->time, 3600000); ngx_conf_init_msec_value(kcf->timeout, 60000); - ngx_conf_init_uint_value(kcf->requests, 100); + ngx_conf_init_uint_value(kcf->requests, 1000); if (kcf->original_init_upstream(cf, us) != NGX_OK) { return NGX_ERROR; diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index 9dda27a10..6664fa6c3 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -3758,7 +3758,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_sec_value(conf->keepalive_header, prev->keepalive_header, 0); ngx_conf_merge_uint_value(conf->keepalive_requests, - prev->keepalive_requests, 100); + prev->keepalive_requests, 1000); ngx_conf_merge_uint_value(conf->lingering_close, prev->lingering_close, NGX_HTTP_LINGERING_ON); ngx_conf_merge_msec_value(conf->lingering_time, -- cgit