From pluknet at nginx.com Mon Dec 1 11:53:15 2014 From: pluknet at nginx.com (Sergey Kandaurov) Date: Mon, 01 Dec 2014 11:53:15 +0000 Subject: [nginx] Access log: restricted "log_format" to "http" level. Message-ID: details: http://hg.nginx.org/nginx/rev/ac2a8e4d8f01 branches: changeset: 5927:ac2a8e4d8f01 user: Sergey Kandaurov date: Mon Dec 01 14:51:36 2014 +0300 description: Access log: restricted "log_format" to "http" level. Specifying the "log_format" directive on levels other than "http" is deprecated since 73d37e1ccb91 (1.1.11). diffstat: src/http/modules/ngx_http_log_module.c | 8 +------- 1 files changed, 1 insertions(+), 7 deletions(-) diffs (25 lines): diff -r 08bfc7188a41 -r ac2a8e4d8f01 src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c Fri Nov 28 16:58:39 2014 +0300 +++ b/src/http/modules/ngx_http_log_module.c Mon Dec 01 14:51:36 2014 +0300 @@ -152,7 +152,7 @@ static ngx_int_t ngx_http_log_init(ngx_c static ngx_command_t ngx_http_log_commands[] = { { ngx_string("log_format"), - NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE, + NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE, ngx_http_log_set_format, NGX_HTTP_MAIN_CONF_OFFSET, 0, @@ -1448,12 +1448,6 @@ ngx_http_log_set_format(ngx_conf_t *cf, ngx_uint_t i; ngx_http_log_fmt_t *fmt; - if (cf->cmd_type != NGX_HTTP_MAIN_CONF) { - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "the \"log_format\" directive may be used " - "only on \"http\" level"); - } - value = cf->args->elts; fmt = lmcf->formats.elts; From mdounin at mdounin.ru Tue Dec 2 02:56:03 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 02 Dec 2014 02:56:03 +0000 Subject: [nginx] Upstream: improved subrequest logging. Message-ID: details: http://hg.nginx.org/nginx/rev/8dfee01ff0bd branches: changeset: 5928:8dfee01ff0bd user: Maxim Dounin date: Tue Dec 02 05:54:54 2014 +0300 description: Upstream: improved subrequest logging. To ensure proper logging make sure to set current_request in all event handlers, including resolve, ssl handshake, cache lock wait timer and aio read handlers. A macro ngx_http_set_log_request() introduced to simplify this. diffstat: src/http/ngx_http_file_cache.c | 43 ++++++++++++++++++++++++++++++----------- src/http/ngx_http_request.c | 8 +----- src/http/ngx_http_request.h | 4 +++ src/http/ngx_http_upstream.c | 11 +++++++-- 4 files changed, 45 insertions(+), 21 deletions(-) diffs (176 lines): diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -14,6 +14,8 @@ static ngx_int_t ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c); static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev); +static void ngx_http_file_cache_lock_wait(ngx_http_request_t *r, + ngx_http_cache_t *c); static ngx_int_t ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c); static ssize_t ngx_http_file_cache_aio_read(ngx_http_request_t *r, @@ -448,25 +450,35 @@ ngx_http_file_cache_lock(ngx_http_reques static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev) { - ngx_uint_t wait; - ngx_msec_t now, timer; - ngx_http_cache_t *c; - ngx_http_request_t *r; - ngx_http_file_cache_t *cache; + ngx_connection_t *c; + ngx_http_request_t *r; r = ev->data; - c = r->cache; + c = r->connection; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http file cache wait: \"%V?%V\"", &r->uri, &r->args); + + ngx_http_file_cache_lock_wait(r, r->cache); +} + + +static void +ngx_http_file_cache_lock_wait(ngx_http_request_t *r, ngx_http_cache_t *c) +{ + ngx_uint_t wait; + ngx_msec_t now, timer; + ngx_http_file_cache_t *cache; now = ngx_current_msec; - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0, - "http file cache wait handler wt:%M cur:%M", - c->wait_time, now); - timer = c->wait_time - now; if ((ngx_msec_int_t) timer <= 0) { - ngx_log_error(NGX_LOG_INFO, ev->log, 0, "cache lock timeout"); + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "cache lock timeout"); c->lock_timeout = 0; goto wakeup; } @@ -485,7 +497,7 @@ ngx_http_file_cache_lock_wait_handler(ng ngx_shmtx_unlock(&cache->shpool->mutex); if (wait) { - ngx_add_timer(ev, (timer > 500) ? 500 : timer); + ngx_add_timer(&c->wait_event, (timer > 500) ? 500 : timer); return; } @@ -665,10 +677,17 @@ static void ngx_http_cache_aio_event_handler(ngx_event_t *ev) { ngx_event_aio_t *aio; + ngx_connection_t *c; ngx_http_request_t *r; aio = ev->data; r = aio->data; + c = r->connection; + + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http file cache aio: \"%V?%V\"", &r->uri, &r->args); r->main->blocked--; r->aio = 0; 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 @@ -2169,13 +2169,11 @@ ngx_http_request_handler(ngx_event_t *ev { ngx_connection_t *c; ngx_http_request_t *r; - ngx_http_log_ctx_t *ctx; c = ev->data; r = c->data; - ctx = c->log->data; - ctx->current_request = r; + ngx_http_set_log_request(c->log, r); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http run request: \"%V?%V\"", &r->uri, &r->args); @@ -2195,7 +2193,6 @@ void ngx_http_run_posted_requests(ngx_connection_t *c) { ngx_http_request_t *r; - ngx_http_log_ctx_t *ctx; ngx_http_posted_request_t *pr; for ( ;; ) { @@ -2215,8 +2212,7 @@ ngx_http_run_posted_requests(ngx_connect r = pr->request; - ctx = c->log->data; - ctx->current_request = r; + ngx_http_set_log_request(c->log, r); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http posted request: \"%V?%V\"", &r->uri, &r->args); diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -595,4 +595,8 @@ extern ngx_http_header_out_t ngx_http_ } +#define ngx_http_set_log_request(log, r) \ + ((ngx_http_log_ctx_t *) log->data)->current_request = r + + #endif /* _NGX_HTTP_REQUEST_H_INCLUDED_ */ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -942,6 +942,11 @@ ngx_http_upstream_resolve_handler(ngx_re u = r->upstream; ur = u->resolved; + ngx_http_set_log_request(c->log, r); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, + "http upstream resolve: \"%V?%V\"", &r->uri, &r->args); + if (ctx->state) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V could not be resolved (%i: %s)", @@ -1003,7 +1008,6 @@ ngx_http_upstream_handler(ngx_event_t *e { ngx_connection_t *c; ngx_http_request_t *r; - ngx_http_log_ctx_t *ctx; ngx_http_upstream_t *u; c = ev->data; @@ -1012,8 +1016,7 @@ ngx_http_upstream_handler(ngx_event_t *e u = r->upstream; c = r->connection; - ctx = c->log->data; - ctx->current_request = r; + ngx_http_set_log_request(c->log, r); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "http upstream request: \"%V?%V\"", &r->uri, &r->args); @@ -1447,6 +1450,8 @@ ngx_http_upstream_ssl_handshake(ngx_conn r = c->data; u = r->upstream; + ngx_http_set_log_request(c->log, r); + if (c->ssl->handshaked) { if (u->conf->ssl_verify) { From mdounin at mdounin.ru Tue Dec 2 02:56:07 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 02 Dec 2014 02:56:07 +0000 Subject: [nginx] Cache: proper wakeup of subrequests. Message-ID: details: http://hg.nginx.org/nginx/rev/f436e9a60b8f branches: changeset: 5929:f436e9a60b8f user: Maxim Dounin date: Tue Dec 02 05:54:56 2014 +0300 description: Cache: proper wakeup of subrequests. In case of a cache lock timeout and in the aio handler we now call r->write_event_handler() instead of a connection write handler, to make sure to run appropriate subrequest. Previous code failed to run inactive subrequests and hence resulted in suboptimal behaviour, see report by Yichun Zhang: http://mailman.nginx.org/pipermail/nginx-devel/2013-October/004435.html (Infinite hang claimed in the report seems impossible without 3rd party modules, as subrequests will be eventually woken up by the postpone filter.) diffstat: src/http/ngx_http_file_cache.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diffs (32 lines): diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -462,6 +462,8 @@ ngx_http_file_cache_lock_wait_handler(ng "http file cache wait: \"%V?%V\"", &r->uri, &r->args); ngx_http_file_cache_lock_wait(r, r->cache); + + ngx_http_run_posted_requests(c); } @@ -505,7 +507,7 @@ wakeup: c->waiting = 0; r->main->blocked--; - r->connection->write->handler(r->connection->write); + r->write_event_handler(r); } @@ -692,7 +694,9 @@ ngx_http_cache_aio_event_handler(ngx_eve r->main->blocked--; r->aio = 0; - r->connection->write->handler(r->connection->write); + r->write_event_handler(r); + + ngx_http_run_posted_requests(c); } #endif From mdounin at mdounin.ru Tue Dec 2 02:58:08 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 2 Dec 2014 05:58:08 +0300 Subject: [PATCH] Request hang when cache_lock is used in subrequests In-Reply-To: References: <20141127153131.GY31620@mdounin.ru> Message-ID: <20141202025808.GL24053@mdounin.ru> Hello! On Fri, Nov 28, 2014 at 09:38:43PM -0800, Yichun Zhang (agentzh) wrote: > Hi Maxim! > > On Thu, Nov 27, 2014 at 7:31 AM, Maxim Dounin wrote: > > Yichun, I've spent some time looking in this, and I don't see how > > it can cause infinite hang at least with stock nginx modules. It > > certainly can cause suboptimal behaviour though, both with proxy > > cache locks and with AIO. > > > > You're right. I'm not using the stock nginx modules nor the stock > subrequest model :P > > > Here are two patches to address this (and also logging issues with > > subrequests): > > > > I've just confirmed that you patches fix my issue. Thank you very much! Committed, thanks for testing. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Dec 2 04:02:26 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 02 Dec 2014 04:02:26 +0000 Subject: [nginx] Trailing spaces removed, typo fixed. Message-ID: details: http://hg.nginx.org/nginx/rev/b791b8e366ad branches: changeset: 5930:b791b8e366ad user: Maxim Dounin date: Tue Dec 02 07:01:37 2014 +0300 description: Trailing spaces removed, typo fixed. diffstat: docs/xml/nginx/changes.xml | 28 ++++++++++++++-------------- 1 files changed, 14 insertions(+), 14 deletions(-) diffs (122 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -46,7 +46,7 @@ the "proxy_limit_rate", "fastcgi_limit_r scgi_ignore_headers ? uwsgi_ignore_headers. -the "Vary" parameter of the "proxy_ignore_headers", "fastcgi_ignore_headers", +the "Vary" parameter of the "proxy_ignore_headers", "fastcgi_ignore_headers", "scgi_ignore_headers", and "uwsgi_ignore_headers" directives. @@ -90,7 +90,7 @@ Thanks to Yichun Zhang and Daniil Bondar -? ?????????? +? ?????????? proxy_next_upstream_tries ? proxy_next_upstream_timeout.
??????? Feng Gu.
@@ -847,7 +847,7 @@ in the ngx_http_spdy_module. Sadosky, Buenos Aires, Argentina. -a heap memory buffer overflow might occur in a worker process +a heap memory buffer overflow might occur in a worker process while handling a specially crafted request by ngx_http_spdy_module, potentially resulting in arbitrary code execution (CVE-2014-0133).
@@ -1145,7 +1145,7 @@ nginx incorrectly handled escaped "?" ch -?????? ngx_http_dav_module ?? ???????????? ??????? URI ??? +?????? ngx_http_dav_module ?? ???????????? ??????? URI ??? ????????? ??????? COPY ? MOVE. @@ -1840,7 +1840,7 @@ Thanks to Serguei Ivantsov. -????????? ssi_last_modified, sub_filter_last_modified ? +????????? ssi_last_modified, sub_filter_last_modified ? xslt_last_modified.
??????? ??????? ?????????.
@@ -2128,7 +2128,7 @@ the mail proxy module now supports IPv6 ??? ????????? ???????? ??????? ?? ?????? -???? ??????? ????? ???????????? ???????????; +???? ??????? ????? ???????????? ???????????; ?????? ????????? ? 1.3.9.
??????? Piotr Sikora.
@@ -2280,7 +2280,7 @@ Thanks to Apcera and CloudBees for spons ??????? Louis Opter.
-the "auth_basic_user_file" directive supports "{SHA}" +the "auth_basic_user_file" directive supports "{SHA}" password encryption method.
Thanks to Louis Opter.
@@ -3486,7 +3486,7 @@ if they were used with IPv6 addresses. ????? ????????????? ???????????.
-the "modern_browser" and "ancient_browser" directives +the "modern_browser" and "ancient_browser" directives might be inherited incorrectly.
@@ -4190,8 +4190,8 @@ Thanks to Yichun Zhang. -????????? read_ahead ????? ?? ???????? ??? ????????????? ????????? ? -try_files ? open_file_cache. +????????? read_ahead ????? ?? ???????? ??? ????????????? ????????? ? +try_files ? open_file_cache. the "read_ahead" directive might not work combined with "try_files" @@ -4414,7 +4414,7 @@ nginx could not be built on AIX. the ngx_http_limit_zone_module was renamed to the ngx_http_limit_conn_module. - + @@ -4521,7 +4521,7 @@ Thanks to Kirill A. Korinskiy. ssl_certificate. -a segmentation fault occurred on start or during reconfiguration +a segmentation fault occurred on start or during reconfiguration if the "ssl" directive was used at http level and there was no "ssl_certificate" defined. @@ -4631,7 +4631,7 @@ Thanks to Alexey Kuts. -????????? ?????? ngx_http_rewrite_module, ???????? ?? ?????? server, +????????? ?????? ngx_http_rewrite_module, ???????? ?? ?????? server, ??????????? ????????, ???? ??? ??????? ?? ?????????? ?? ?????? location'?. @@ -11289,7 +11289,7 @@ the "proxy_ssl_session_reuse" directive. a "proxy_pass" directive without URI part might use original request -after the "X-Accel-Redirect" redirection was used; +after the "X-Accel-Redirect" redirection was used. From mdounin at mdounin.ru Tue Dec 2 13:05:10 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 02 Dec 2014 13:05:10 +0000 Subject: [nginx] nginx-1.7.8-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/d5ea659b8bab branches: changeset: 5931:d5ea659b8bab user: Maxim Dounin date: Tue Dec 02 16:02:14 2014 +0300 description: nginx-1.7.8-RELEASE diffstat: docs/xml/nginx/changes.xml | 166 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 166 insertions(+), 0 deletions(-) diffs (176 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,172 @@ + + + + +?????? ?????? "If-Modified-Since", "If-Range" ? ?? ???????? +? ????????? ??????? ??????? ?????????? ??????? ??? ?????????? ???????????, +???? nginx ??????? ?????, ??? ?? ????? ?????????? ????? +(????????, ??? ????????????? proxy_cache_min_uses). + + +now the "If-Modified-Since", "If-Range", etc. +client request header lines are passed to a backend while caching +if nginx knows in advance that the response will not be cached +(e.g., when using proxy_cache_min_uses). + + + + + +?????? ????? ????????? proxy_cache_lock_timeout +nginx ?????????? ?????? ?? ?????? ??? ???????????; +????? ????????? proxy_cache_lock_age, fastcgi_cache_lock_age, +scgi_cache_lock_age ? uwsgi_cache_lock_age ????????? ???????, +????? ????? ????? ?????????? ????? ????????????? ????? +? ????? ??????? ??? ???? ??????? ???????????? ?????. + + +now after proxy_cache_lock_timeout +nginx sends a request to a backend with caching disabled; +the new directives "proxy_cache_lock_age", "fastcgi_cache_lock_age", +"scgi_cache_lock_age", and "uwsgi_cache_lock_age" specify a time +after which the lock will be released +and another attempt to cache a response will be made. + + + + + +????????? log_format ?????? ????? ?????????????? ?????? ?? ?????? http. + + +the "log_format" directive can now be used only at http level. + + + + + +????????? proxy_ssl_certificate, proxy_ssl_certificate_key, +proxy_ssl_password_file, uwsgi_ssl_certificate, +uwsgi_ssl_certificate_key ? uwsgi_ssl_password_file.
+??????? Piotr Sikora. +
+ +the "proxy_ssl_certificate", "proxy_ssl_certificate_key", +"proxy_ssl_password_file", "uwsgi_ssl_certificate", +"uwsgi_ssl_certificate_key", and "uwsgi_ssl_password_file" directives.
+Thanks to Piotr Sikora. +
+
+ + + +?????? ? ??????? X-Accel-Redirect +????? ??????? ? ??????????? location.
+??????? Toshikuni Fukaya. +
+ +it is now possible to switch to a named location +using "X-Accel-Redirect".
+Thanks to Toshikuni Fukaya. +
+
+ + + +?????? ????????? tcp_nodelay ???????? ??? SPDY-??????????. + + +now the "tcp_nodelay" directive works with SPDY connections. + + + + + +????? ????????? ? ???????? ????????? ?????????? ??? vim.
+??????? Peter Wu. +
+ +new directives in vim syntax highliting scripts.
+Thanks to Peter Wu. +
+
+ + + +nginx ??????????? ???????? "s-maxage" +? ?????? "Cache-Control" ? ????????? ?????? ???????.
+??????? Piotr Sikora. +
+ +nginx ignored the "s-maxage" value +in the "Cache-Control" backend response header line.
+Thanks to Piotr Sikora. +
+
+ + + +? ?????? ngx_http_spdy_module.
+??????? Piotr Sikora. +
+ +in the ngx_http_spdy_module.
+Thanks to Piotr Sikora. +
+
+ + + +? ????????? ssl_password_file +??? ????????????? OpenSSL 0.9.8zc, 1.0.0o, 1.0.1j. + + +in the "ssl_password_file" directive +when using OpenSSL 0.9.8zc, 1.0.0o, 1.0.1j. + + + + + +??? ????????????? ????????? post_action +? ??? ???????? ????????? "header already sent"; +?????? ????????? ? nginx 1.5.4. + + +alerts "header already sent" appeared in logs +if the "post_action" directive was used; +the bug had appeared in 1.5.4. + + + + + +??? ????????????? ????????? "postpone_output 0" ? SSI-???????????? +? ??? ????? ???????? ????????? "the http output chain is empty". + + +alerts "the http output chain is empty" might appear in logs +if the "postpone_output 0" directive was used with SSI includes. + + + + + +? ????????? proxy_cache_lock ??? ????????????? SSI-???????????.
+??????? Yichun Zhang. +
+ +in the "proxy_cache_lock" directive with SSI subrequests.
+Thanks to Yichun Zhang. +
+
+ +
+ + From mdounin at mdounin.ru Tue Dec 2 13:05:13 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 02 Dec 2014 13:05:13 +0000 Subject: [nginx] release-1.7.8 tag Message-ID: details: http://hg.nginx.org/nginx/rev/16be523be8e4 branches: changeset: 5932:16be523be8e4 user: Maxim Dounin date: Tue Dec 02 16:02:14 2014 +0300 description: release-1.7.8 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -377,3 +377,4 @@ cbb146b120296852e781079d5138b04495bab6df fe129aa02db9001d220f1db7c3c056f79482c111 release-1.7.5 a8d111bb68847f61d682a3c8792fecb2e52efa2c release-1.7.6 6d2fbc30f8a7f70136cf08f32d5ff3179d524873 release-1.7.7 +d5ea659b8bab2d6402a2266efa691f705e84001e release-1.7.8 From mdounin at mdounin.ru Wed Dec 3 21:25:21 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Dec 2014 00:25:21 +0300 Subject: [PATCH] allow to use engine keyform for server private key In-Reply-To: <20141121130901.GE73155@mdounin.ru> References: <20140801165839.GT1849@mdounin.ru> <53E8483C.8020507@cryptopro.ru> <20140812004334.GN1849@mdounin.ru> <5450FE27.2070702@cryptopro.ru> <546ECC05.5020009@cryptopro.ru> <20141121130901.GE73155@mdounin.ru> Message-ID: <20141203212521.GF24053@mdounin.ru> Hello! On Fri, Nov 21, 2014 at 04:09:01PM +0300, Maxim Dounin wrote: > On Fri, Nov 21, 2014 at 08:22:13AM +0300, Dmitrii Pichulin wrote: > > > Ping. > > > > Patch: > > http://mailman.nginx.org/pipermail/nginx-devel/2014-August/005740.html > > > > Example: > > http://mailman.nginx.org/pipermail/nginx-devel/2014-October/006151.html > > Thanks again and sorry, still no time. I hope I'll be able to > look into it in the next week or so. Below is the patch with some minor tweaking to better match nginx code style, please check if it looks ok for you. And, BTW, thanks for the detailed usage example, it was really helpful even on FreeBSD (just one side note: "ssl_engine pkcs11" in nginx config isn't needed). # HG changeset patch # User Dmitrii Pichulin # Date 1407135800 -14400 # Mon Aug 04 11:03:20 2014 +0400 # Node ID 33d24b89fa274b7fdbfaec9c28f4b553ddc14712 # Parent 16be523be8e4541f45ba98c8071295f267ff14ff SSL: loading certificate keys via ENGINE_load_private_key(). diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -376,6 +376,67 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ BIO_free(bio); + if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) { + +#ifndef OPENSSL_NO_ENGINE + + u_char *p, *last; + ENGINE *engine; + EVP_PKEY *pkey; + + p = key->data + sizeof("engine:") - 1; + last = (u_char *) ngx_strchr(p, ':'); + + if (last == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid syntax in \"%V\"", key); + return NGX_ERROR; + } + + *last = '\0'; + + engine = ENGINE_by_id((char *) p); + + if (engine == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "ENGINE_by_id(\"%s\") failed", p); + return NGX_ERROR; + } + + *last++ = ':'; + + pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0); + + if (pkey == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "ENGINE_load_private_key(\"%s\") failed", last); + ENGINE_free(engine); + return NGX_ERROR; + } + + ENGINE_free(engine); + + if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_PrivateKey(\"%s\") failed", last); + EVP_PKEY_free(pkey); + return NGX_ERROR; + } + + EVP_PKEY_free(pkey); + + return NGX_OK; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "loading \"engine:...\" certificate keys " + "is not supported"); + return NGX_ERROR; + +#endif + } + if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { return NGX_ERROR; } -- Maxim Dounin http://nginx.org/ From pdn at cryptopro.ru Thu Dec 4 10:57:49 2014 From: pdn at cryptopro.ru (Dmitrii Pichulin) Date: Thu, 4 Dec 2014 13:57:49 +0300 Subject: [PATCH] allow to use engine keyform for server private key In-Reply-To: <20141203212521.GF24053@mdounin.ru> References: <20140801165839.GT1849@mdounin.ru> <53E8483C.8020507@cryptopro.ru> <20140812004334.GN1849@mdounin.ru> <5450FE27.2070702@cryptopro.ru> <546ECC05.5020009@cryptopro.ru> <20141121130901.GE73155@mdounin.ru> <20141203212521.GF24053@mdounin.ru> Message-ID: <54803E2D.1050207@cryptopro.ru> Pretty good style fixes, thank you. Waiting for a commit. On 04.12.2014 0:25, Maxim Dounin wrote: > Hello! > > On Fri, Nov 21, 2014 at 04:09:01PM +0300, Maxim Dounin wrote: > >> On Fri, Nov 21, 2014 at 08:22:13AM +0300, Dmitrii Pichulin wrote: >> >>> Ping. >>> >>> Patch: >>> http://mailman.nginx.org/pipermail/nginx-devel/2014-August/005740.html >>> >>> Example: >>> http://mailman.nginx.org/pipermail/nginx-devel/2014-October/006151.html >> >> Thanks again and sorry, still no time. I hope I'll be able to >> look into it in the next week or so. > > Below is the patch with some minor tweaking to better match nginx > code style, please check if it looks ok for you. > > And, BTW, thanks for the detailed usage example, it was really > helpful even on FreeBSD (just one side note: "ssl_engine pkcs11" > in nginx config isn't needed). From mdounin at mdounin.ru Thu Dec 4 14:18:00 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 04 Dec 2014 14:18:00 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/0eaa65af0d21 branches: changeset: 5933:0eaa65af0d21 user: Maxim Dounin date: Thu Dec 04 16:37:31 2014 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1007008 -#define NGINX_VERSION "1.7.8" +#define nginx_version 1007009 +#define NGINX_VERSION "1.7.9" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Thu Dec 4 14:18:02 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 04 Dec 2014 14:18:02 +0000 Subject: [nginx] SSL: loading certificate keys via ENGINE_load_private_ke... Message-ID: details: http://hg.nginx.org/nginx/rev/2c33ed82cde1 branches: changeset: 5934:2c33ed82cde1 user: Dmitrii Pichulin date: Mon Aug 04 11:03:20 2014 +0400 description: SSL: loading certificate keys via ENGINE_load_private_key(). diffstat: src/event/ngx_event_openssl.c | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 61 insertions(+), 0 deletions(-) diffs (71 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -376,6 +376,67 @@ ngx_ssl_certificate(ngx_conf_t *cf, ngx_ BIO_free(bio); + if (ngx_strncmp(key->data, "engine:", sizeof("engine:") - 1) == 0) { + +#ifndef OPENSSL_NO_ENGINE + + u_char *p, *last; + ENGINE *engine; + EVP_PKEY *pkey; + + p = key->data + sizeof("engine:") - 1; + last = (u_char *) ngx_strchr(p, ':'); + + if (last == NULL) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid syntax in \"%V\"", key); + return NGX_ERROR; + } + + *last = '\0'; + + engine = ENGINE_by_id((char *) p); + + if (engine == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "ENGINE_by_id(\"%s\") failed", p); + return NGX_ERROR; + } + + *last++ = ':'; + + pkey = ENGINE_load_private_key(engine, (char *) last, 0, 0); + + if (pkey == NULL) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "ENGINE_load_private_key(\"%s\") failed", last); + ENGINE_free(engine); + return NGX_ERROR; + } + + ENGINE_free(engine); + + if (SSL_CTX_use_PrivateKey(ssl->ctx, pkey) == 0) { + ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, + "SSL_CTX_use_PrivateKey(\"%s\") failed", last); + EVP_PKEY_free(pkey); + return NGX_ERROR; + } + + EVP_PKEY_free(pkey); + + return NGX_OK; + +#else + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "loading \"engine:...\" certificate keys " + "is not supported"); + return NGX_ERROR; + +#endif + } + if (ngx_conf_full_name(cf->cycle, key, 1) != NGX_OK) { return NGX_ERROR; } From mdounin at mdounin.ru Thu Dec 4 14:40:40 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Dec 2014 17:40:40 +0300 Subject: [PATCH] allow to use engine keyform for server private key In-Reply-To: <54803E2D.1050207@cryptopro.ru> References: <20140801165839.GT1849@mdounin.ru> <53E8483C.8020507@cryptopro.ru> <20140812004334.GN1849@mdounin.ru> <5450FE27.2070702@cryptopro.ru> <546ECC05.5020009@cryptopro.ru> <20141121130901.GE73155@mdounin.ru> <20141203212521.GF24053@mdounin.ru> <54803E2D.1050207@cryptopro.ru> Message-ID: <20141204144040.GK24053@mdounin.ru> Hello! On Thu, Dec 04, 2014 at 01:57:49PM +0300, Dmitrii Pichulin wrote: > Pretty good style fixes, thank you. Waiting for a commit. Committed, thanks. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 4 18:11:50 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Dec 2014 21:11:50 +0300 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> Message-ID: <20141204181150.GE62402@mdounin.ru> Hello! On Mon, Nov 24, 2014 at 07:27:53PM -0800, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1416886025 28800 > # Mon Nov 24 19:27:05 2014 -0800 > # Node ID 01f07fc7932b64f261c9e6cb778c87279fabcde2 > # Parent 2c10db908b8c4a9c0532c58830275d5ad84ae686 > Cache: don't update cache if revalidated response is not cacheable. > > Signed-off-by: Piotr Sikora > > diff -r 2c10db908b8c -r 01f07fc7932b src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Fri Nov 21 22:51:49 2014 +0300 > +++ b/src/http/ngx_http_upstream.c Mon Nov 24 19:27:05 2014 -0800 > @@ -2002,14 +2002,13 @@ ngx_http_upstream_test_next(ngx_http_req > && u->cache_status == NGX_HTTP_CACHE_EXPIRED > && u->conf->cache_revalidate) > { > - time_t now, valid; > + time_t valid; > ngx_int_t rc; > > ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > "http upstream not modified"); > > - now = ngx_time(); > - valid = r->cache->valid_sec; > + valid = u->cacheable ? r->cache->valid_sec : 0; > > rc = u->reinit_request(r); > > @@ -2021,25 +2020,31 @@ ngx_http_upstream_test_next(ngx_http_req > u->cache_status = NGX_HTTP_CACHE_REVALIDATED; > rc = ngx_http_upstream_cache_send(r, u); > > - if (valid == 0) { > - valid = r->cache->valid_sec; > - } > - > - if (valid == 0) { > - valid = ngx_http_file_cache_valid(u->conf->cache_valid, > - u->headers_in.status_n); > + if (u->cacheable || valid) { I don't really understand the logic you suggest. Previous behaviour is as follows: - We don't check if the response is cacheable or not, but rather rely on the fact that it's already in the cache (hence it, at least was, cacheable). This kind of agree with what nginx normally does for cache items - cacheability is determined when we are placing a response into the cache, and not changed after this even if settings are changed. With the suggested change, you do the following: - If the 304 response is cacheable and there is a validity known in advance (from Expires, Cache-Control or X-Accel-Expires), the response will be cached. - If the 304 response is cacheable and the cached response is cacheable according to current settings, the response will be cached. This doesn't look consistent. In particular, - If the cached response is not cacheable according to current settings, it's still can be cached if the 304 response can be cached and have a validity explicitly set. Doesn't look like a good change to me. > + time_t now; Please do not put declarations inside blocks, with the exception of dedicated conditionally compiled blocks. > + > + now = ngx_time(); > + > + if (valid == 0) { > + valid = r->cache->valid_sec; > + } > + > + if (valid == 0) { > + valid = ngx_http_file_cache_valid(u->conf->cache_valid, > + u->headers_in.status_n); > + if (valid) { > + valid = now + valid; > + } > + } > + > if (valid) { > - valid = now + valid; > + r->cache->valid_sec = valid; > + r->cache->date = now; > + > + ngx_http_file_cache_update_header(r); > } > } > > - if (valid) { > - r->cache->valid_sec = valid; > - r->cache->date = now; > - > - ngx_http_file_cache_update_header(r); > - } > - > ngx_http_upstream_finalize_request(r, u, rc); > return NGX_OK; > } > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 4 18:13:50 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Dec 2014 21:13:50 +0300 Subject: [PATCH 2 of 2] Cache: test proxy_no_cache predicates before updating cache In-Reply-To: References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> Message-ID: <20141204181349.GF62402@mdounin.ru> Hello! On Mon, Nov 24, 2014 at 07:27:54PM -0800, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1416886025 28800 > # Mon Nov 24 19:27:05 2014 -0800 > # Node ID ab6cff701ca23bee8f24e9efcdbcef2ca938b68f > # Parent 01f07fc7932b64f261c9e6cb778c87279fabcde2 > Cache: test proxy_no_cache predicates before updating cache. > > Signed-off-by: Piotr Sikora > > diff -r 01f07fc7932b -r ab6cff701ca2 src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Mon Nov 24 19:27:05 2014 -0800 > +++ b/src/http/ngx_http_upstream.c Mon Nov 24 19:27:05 2014 -0800 > @@ -2008,6 +2008,20 @@ ngx_http_upstream_test_next(ngx_http_req > ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, > "http upstream not modified"); > > + switch (ngx_http_test_predicates(r, u->conf->no_cache)) { > + > + case NGX_ERROR: > + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); > + return NGX_OK; > + > + case NGX_DECLINED: > + u->cacheable = 0; > + break; > + > + default: /* NGX_OK */ > + break; > + } > + > valid = u->cacheable ? r->cache->valid_sec : 0; > > rc = u->reinit_request(r); Again, not sure it's a good change. In particular, suggested code checks proxy_no_cache against a 304 response, not against a response which will be cached (or, rather, already cached), and this looks very questionable. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 4 18:15:12 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 04 Dec 2014 18:15:12 +0000 Subject: [nginx] Cache: send conditional requests only for cached 200/206... Message-ID: details: http://hg.nginx.org/nginx/rev/1573fc7875fa branches: changeset: 5935:1573fc7875fa user: Piotr Sikora date: Wed Nov 26 18:35:37 2014 -0800 description: Cache: send conditional requests only for cached 200/206 responses. RFC7232 says: The 304 (Not Modified) status code indicates that a conditional GET or HEAD request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition evaluated to false. which means that there is no reason to send requests with "If-None-Match" and/or "If-Modified-Since" headers for responses cached with other status codes. Also, sending conditional requests for responses cached with other status codes could result in a strange behavior, e.g. upstream server returning 304 Not Modified for cached 404 Not Found responses, etc. Signed-off-by: Piotr Sikora diffstat: src/http/ngx_http_file_cache.c | 2 ++ src/http/ngx_http_upstream.c | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diffs (36 lines): diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -177,6 +177,8 @@ ngx_http_file_cache_new(ngx_http_request c->file.log = r->connection->log; c->file.fd = NGX_INVALID_FILE; + c->last_modified = -1; + return NGX_OK; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -2565,12 +2565,17 @@ ngx_http_upstream_send_response(ngx_http } if (valid) { - r->cache->last_modified = u->headers_in.last_modified_time; r->cache->date = now; r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start); - if (u->headers_in.etag) { - r->cache->etag = u->headers_in.etag->value; + if (u->headers_in.status_n == NGX_HTTP_OK + || u->headers_in.status_n == NGX_HTTP_PARTIAL_CONTENT) + { + r->cache->last_modified = u->headers_in.last_modified_time; + + if (u->headers_in.etag) { + r->cache->etag = u->headers_in.etag->value; + } } ngx_http_file_cache_set_header(r, u->buffer.start); From mdounin at mdounin.ru Thu Dec 4 18:15:36 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Dec 2014 21:15:36 +0300 Subject: [PATCH] Cache: send conditional requests only for cached 200/206 responses In-Reply-To: References: Message-ID: <20141204181536.GG62402@mdounin.ru> Hello! On Wed, Nov 26, 2014 at 06:38:31PM -0800, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1417055737 28800 > # Wed Nov 26 18:35:37 2014 -0800 > # Node ID ec4837c14647c6745b41f0a8c55fcc5fcb6f336b > # Parent 2c10db908b8c4a9c0532c58830275d5ad84ae686 > Cache: send conditional requests only for cached 200/206 responses. Committed, thanks. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 4 19:37:57 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 4 Dec 2014 22:37:57 +0300 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests In-Reply-To: <0c3c06fabfc3b1c57710.1416925333@blade26.multiplay.co.uk> References: <0c3c06fabfc3b1c57710.1416925333@blade26.multiplay.co.uk> Message-ID: <20141204193757.GH62402@mdounin.ru> Hello! On Tue, Nov 25, 2014 at 02:22:13PM +0000, Steven Hartland wrote: > # HG changeset patch > # User Steven Hartland > # Date 1416925134 0 > # Tue Nov 25 14:18:54 2014 +0000 > # Node ID 0c3c06fabfc3b1c57710c0cced4837c10e3e9bbb > # Parent 7d7eac6e31df1d962a644f8093c1fbb8f91620ce > Allow Partial Content responses to satisfy Range requests. [...] > - if (ctx->ranges.nelts == 1) { > - return ngx_http_range_singlepart_header(r, ctx); > + return ngx_http_range_multipart_header(r, ctx); > + > + case NGX_HTTP_RANGE_NOT_SATISFIABLE: > + return ngx_http_range_not_satisfiable(r); [...] > static ngx_int_t > -ngx_http_range_not_satisfiable(ngx_http_request_t *r) > +ngx_http_range_not_satisfiable(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx) > { Expectedly fails to build here: src/http/modules/ngx_http_range_filter_module.c: In function 'ngx_http_range_header_filter': src/http/modules/ngx_http_range_filter_module.c:254: error: too few arguments to function 'ngx_http_range_not_satisfiable' *** [objs/src/http/modules/ngx_http_range_filter_module.o] Error code 1 -- Maxim Dounin http://nginx.org/ From steven.hartland at multiplay.co.uk Thu Dec 4 20:34:07 2014 From: steven.hartland at multiplay.co.uk (Steven Hartland) Date: Thu, 04 Dec 2014 20:34:07 +0000 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests In-Reply-To: <20141204193757.GH62402@mdounin.ru> References: <0c3c06fabfc3b1c57710.1416925333@blade26.multiplay.co.uk> <20141204193757.GH62402@mdounin.ru> Message-ID: <5480C53F.5090701@multiplay.co.uk> On 04/12/2014 19:37, Maxim Dounin wrote: > Hello! > > On Tue, Nov 25, 2014 at 02:22:13PM +0000, Steven Hartland wrote: > >> # HG changeset patch >> # User Steven Hartland >> # Date 1416925134 0 >> # Tue Nov 25 14:18:54 2014 +0000 >> # Node ID 0c3c06fabfc3b1c57710c0cced4837c10e3e9bbb >> # Parent 7d7eac6e31df1d962a644f8093c1fbb8f91620ce >> Allow Partial Content responses to satisfy Range requests. > [...] > >> - if (ctx->ranges.nelts == 1) { >> - return ngx_http_range_singlepart_header(r, ctx); >> + return ngx_http_range_multipart_header(r, ctx); >> + >> + case NGX_HTTP_RANGE_NOT_SATISFIABLE: >> + return ngx_http_range_not_satisfiable(r); > [...] > >> static ngx_int_t >> -ngx_http_range_not_satisfiable(ngx_http_request_t *r) >> +ngx_http_range_not_satisfiable(ngx_http_request_t *r, >> + ngx_http_range_filter_ctx_t *ctx) >> { > Expectedly fails to build here: > > src/http/modules/ngx_http_range_filter_module.c: In function 'ngx_http_range_header_filter': > src/http/modules/ngx_http_range_filter_module.c:254: error: too few arguments to function 'ngx_http_range_not_satisfiable' > *** [objs/src/http/modules/ngx_http_range_filter_module.o] Error code 1 Apologies about that, teach me to do a last minute rebase without re-running tests. Will re-submit once that's done. Regards Steve From steven.hartland at multiplay.co.uk Thu Dec 4 21:07:57 2014 From: steven.hartland at multiplay.co.uk (Steven Hartland) Date: Thu, 04 Dec 2014 21:07:57 +0000 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests Message-ID: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> # HG changeset patch # User Steven Hartland # Date 1417727204 0 # Thu Dec 04 21:06:44 2014 +0000 # Node ID 05d3973ece9af030d0312932938fc3d1f2f139dd # Parent 1573fc7875fa09ee55763ce7ddc4e98d61e1deaf Allow Partial Content responses to satisfy Range requests diff -r 1573fc7875fa -r 05d3973ece9a src/http/modules/ngx_http_range_filter_module.c --- a/src/http/modules/ngx_http_range_filter_module.c Wed Nov 26 18:35:37 2014 -0800 +++ b/src/http/modules/ngx_http_range_filter_module.c Thu Dec 04 21:06:44 2014 +0000 @@ -54,6 +54,7 @@ typedef struct { off_t offset; + off_t content_length; ngx_str_t boundary_header; ngx_array_t ranges; } ngx_http_range_filter_ctx_t; @@ -65,7 +66,8 @@ ngx_http_range_filter_ctx_t *ctx); static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx); -static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r); +static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx); static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r, @@ -76,6 +78,9 @@ static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf); static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf); +static ngx_int_t ngx_http_content_range_parse(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx); + static ngx_http_module_t ngx_http_range_header_filter_module_ctx = { NULL, /* preconfiguration */ @@ -153,8 +158,8 @@ ngx_http_range_filter_ctx_t *ctx; if (r->http_version < NGX_HTTP_VERSION_10 - || r->headers_out.status != NGX_HTTP_OK - || r != r->main + || (r->headers_out.status != NGX_HTTP_OK + && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) || r->headers_out.content_length_n == -1 || !r->allow_ranges) { @@ -230,26 +235,31 @@ ranges = r->single_range ? 1 : clcf->max_ranges; - switch (ngx_http_range_parse(r, ctx, ranges)) { + switch (ngx_http_content_range_parse(r, ctx)) { + case NGX_OK: + switch (ngx_http_range_parse(r, ctx, ranges)) { + case NGX_OK: + ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); - case NGX_OK: - ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); + r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; + r->headers_out.status_line.len = 0; - r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; - r->headers_out.status_line.len = 0; + if (ctx->ranges.nelts == 1) { + return ngx_http_range_singlepart_header(r, ctx); + } - if (ctx->ranges.nelts == 1) { - return ngx_http_range_singlepart_header(r, ctx); + return ngx_http_range_multipart_header(r, ctx); + + case NGX_HTTP_RANGE_NOT_SATISFIABLE: + return ngx_http_range_not_satisfiable(r, ctx); + + case NGX_ERROR: + return NGX_ERROR; + + default: /* NGX_DECLINED */ + break; } - - return ngx_http_range_multipart_header(r, ctx); - - case NGX_HTTP_RANGE_NOT_SATISFIABLE: - return ngx_http_range_not_satisfiable(r); - - case NGX_ERROR: - return NGX_ERROR; - + break; default: /* NGX_DECLINED */ break; } @@ -274,13 +284,12 @@ ngx_uint_t ranges) { u_char *p; - off_t start, end, size, content_length; + off_t start, end, size; ngx_uint_t suffix; ngx_http_range_t *range; p = r->headers_in.range->value.data + 6; size = 0; - content_length = r->headers_out.content_length_n; for ( ;; ) { start = 0; @@ -298,6 +307,10 @@ start = start * 10 + *p++ - '0'; } + if (start < ctx->offset) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + while (*p == ' ') { p++; } if (*p++ != '-') { @@ -307,7 +320,7 @@ while (*p == ' ') { p++; } if (*p == ',' || *p == '\0') { - end = content_length; + end = ctx->content_length; goto found; } @@ -331,12 +344,12 @@ } if (suffix) { - start = content_length - end; - end = content_length - 1; + start = ctx->content_length - end; + end = ctx->content_length - 1; } - if (end >= content_length) { - end = content_length; + if (end >= ctx->content_length) { + end = ctx->content_length; } else { end++; @@ -369,7 +382,7 @@ return NGX_HTTP_RANGE_NOT_SATISFIABLE; } - if (size > content_length) { + if (size > ctx->content_length) { return NGX_DECLINED; } @@ -384,16 +397,18 @@ ngx_table_elt_t *content_range; ngx_http_range_t *range; - content_range = ngx_list_push(&r->headers_out.headers); - if (content_range == NULL) { - return NGX_ERROR; + if (r->headers_out.content_range == NULL) { + content_range = ngx_list_push(&r->headers_out.headers); + if (content_range == NULL) { + return NGX_ERROR; + } + r->headers_out.content_range = content_range; + content_range->hash = 1; + ngx_str_set(&content_range->key, "Content-Range"); + } else { + content_range = r->headers_out.content_range; } - r->headers_out.content_range = content_range; - - content_range->hash = 1; - ngx_str_set(&content_range->key, "Content-Range"); - content_range->value.data = ngx_pnalloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN); if (content_range->value.data == NULL) { @@ -407,7 +422,7 @@ content_range->value.len = ngx_sprintf(content_range->value.data, "bytes %O-%O/%O", range->start, range->end - 1, - r->headers_out.content_length_n) + ctx->content_length) - content_range->value.data; r->headers_out.content_length_n = range->end - range->start; @@ -546,22 +561,25 @@ static ngx_int_t -ngx_http_range_not_satisfiable(ngx_http_request_t *r) +ngx_http_range_not_satisfiable(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx) { ngx_table_elt_t *content_range; r->headers_out.status = NGX_HTTP_RANGE_NOT_SATISFIABLE; - content_range = ngx_list_push(&r->headers_out.headers); - if (content_range == NULL) { - return NGX_ERROR; + if (r->headers_out.content_range == NULL) { + content_range = ngx_list_push(&r->headers_out.headers); + if (content_range == NULL) { + return NGX_ERROR; + } + r->headers_out.content_range = content_range; + content_range->hash = 1; + ngx_str_set(&content_range->key, "Content-Range"); + } else { + content_range = r->headers_out.content_range; } - r->headers_out.content_range = content_range; - - content_range->hash = 1; - ngx_str_set(&content_range->key, "Content-Range"); - content_range->value.data = ngx_pnalloc(r->pool, sizeof("bytes */") - 1 + NGX_OFF_T_LEN); if (content_range->value.data == NULL) { @@ -570,7 +588,7 @@ content_range->value.len = ngx_sprintf(content_range->value.data, "bytes */%O", - r->headers_out.content_length_n) + ctx->content_length) - content_range->value.data; ngx_http_clear_content_length(r); @@ -888,3 +906,76 @@ return NGX_OK; } + + +static ngx_int_t +ngx_http_content_range_parse(ngx_http_request_t *r, + ngx_http_range_filter_ctx_t *ctx) +{ + u_char *p; + off_t start, end, len; + + ctx->offset = 0; + ctx->content_length = r->headers_out.content_length_n; + + if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) { + return NGX_OK; + } + + if (r->headers_out.content_range == NULL + || r->headers_out.content_range->value.len == 0) { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + if (r->headers_out.content_range->value.len < 7 + || ngx_strncasecmp(r->headers_out.content_range->value.data, + (u_char *) "bytes ", 6) != 0) { + return NGX_DECLINED; + } + + start = 0; + end = 0; + len = 0; + + p = r->headers_out.content_range->value.data + 6; + + while (*p == ' ') { p++; } + + if (*p < '0' || *p > '9') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + while (*p >= '0' && *p <= '9') { + start = start * 10 + *p++ - '0'; + } + + if (*p++ != '-') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + while (*p >= '0' && *p <= '9') { + end = end * 10 + *p++ - '0'; + } + + if (*p++ != '/') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + if (*p < '0' || *p > '9') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + while (*p >= '0' && *p <= '9') { + len = len * 10 + *p++ - '0'; + } + + if (*p != '\0') { + return NGX_HTTP_RANGE_NOT_SATISFIABLE; + } + + ctx->offset = start; + ctx->content_length = len; + + return NGX_OK; +} + diff -r 1573fc7875fa -r 05d3973ece9a src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Nov 26 18:35:37 2014 -0800 +++ b/src/http/ngx_http_upstream.c Thu Dec 04 21:06:44 2014 +0000 @@ -292,6 +292,11 @@ ngx_http_upstream_copy_content_encoding, 0, 0 }, #endif + { ngx_string("Content-Range"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_allow_ranges, + offsetof(ngx_http_headers_out_t, content_range), 1 }, + { ngx_null_string, NULL, 0, NULL, 0, 0 } }; @@ -4516,37 +4521,26 @@ ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - ngx_table_elt_t *ho; - if (r->upstream->conf->force_ranges) { return NGX_OK; } - #if (NGX_HTTP_CACHE) - if (r->cached) { r->allow_ranges = 1; - return NGX_OK; + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { + return NGX_OK; + } } if (r->upstream->cacheable) { r->allow_ranges = 1; r->single_range = 1; - return NGX_OK; - } - + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { + return NGX_OK; + } + } #endif - - ho = ngx_list_push(&r->headers_out.headers); - if (ho == NULL) { - return NGX_ERROR; - } - - *ho = *h; - - r->headers_out.accept_ranges = ho; - - return NGX_OK; + return ngx_http_upstream_copy_header_line(r, h, offset); } From steven.hartland at multiplay.co.uk Thu Dec 4 21:20:15 2014 From: steven.hartland at multiplay.co.uk (Steven Hartland) Date: Thu, 04 Dec 2014 21:20:15 +0000 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests In-Reply-To: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> References: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> Message-ID: <5480D00F.3060704@multiplay.co.uk> This time test suite passes on default compile: All tests successful. Files=141, Tests=964, 86 wallclock secs ( 0.49 usr 0.22 sys + 10.05 cusr 2.55 csys = 13.31 CPU) Result: PASS On 04/12/2014 21:07, Steven Hartland wrote: > # HG changeset patch > # User Steven Hartland > # Date 1417727204 0 > # Thu Dec 04 21:06:44 2014 +0000 > # Node ID 05d3973ece9af030d0312932938fc3d1f2f139dd > # Parent 1573fc7875fa09ee55763ce7ddc4e98d61e1deaf > Allow Partial Content responses to satisfy Range requests > > diff -r 1573fc7875fa -r 05d3973ece9a src/http/modules/ngx_http_range_filter_module.c > --- a/src/http/modules/ngx_http_range_filter_module.c Wed Nov 26 18:35:37 2014 -0800 > +++ b/src/http/modules/ngx_http_range_filter_module.c Thu Dec 04 21:06:44 2014 +0000 > @@ -54,6 +54,7 @@ > > typedef struct { > off_t offset; > + off_t content_length; > ngx_str_t boundary_header; > ngx_array_t ranges; > } ngx_http_range_filter_ctx_t; > @@ -65,7 +66,8 @@ > ngx_http_range_filter_ctx_t *ctx); > static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, > ngx_http_range_filter_ctx_t *ctx); > -static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r); > +static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx); > static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r, > ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); > static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r, > @@ -76,6 +78,9 @@ > static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf); > static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf); > > +static ngx_int_t ngx_http_content_range_parse(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx); > + > > static ngx_http_module_t ngx_http_range_header_filter_module_ctx = { > NULL, /* preconfiguration */ > @@ -153,8 +158,8 @@ > ngx_http_range_filter_ctx_t *ctx; > > if (r->http_version < NGX_HTTP_VERSION_10 > - || r->headers_out.status != NGX_HTTP_OK > - || r != r->main > + || (r->headers_out.status != NGX_HTTP_OK > + && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) > || r->headers_out.content_length_n == -1 > || !r->allow_ranges) > { > @@ -230,26 +235,31 @@ > > ranges = r->single_range ? 1 : clcf->max_ranges; > > - switch (ngx_http_range_parse(r, ctx, ranges)) { > + switch (ngx_http_content_range_parse(r, ctx)) { > + case NGX_OK: > + switch (ngx_http_range_parse(r, ctx, ranges)) { > + case NGX_OK: > + ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); > > - case NGX_OK: > - ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); > + r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; > + r->headers_out.status_line.len = 0; > > - r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; > - r->headers_out.status_line.len = 0; > + if (ctx->ranges.nelts == 1) { > + return ngx_http_range_singlepart_header(r, ctx); > + } > > - if (ctx->ranges.nelts == 1) { > - return ngx_http_range_singlepart_header(r, ctx); > + return ngx_http_range_multipart_header(r, ctx); > + > + case NGX_HTTP_RANGE_NOT_SATISFIABLE: > + return ngx_http_range_not_satisfiable(r, ctx); > + > + case NGX_ERROR: > + return NGX_ERROR; > + > + default: /* NGX_DECLINED */ > + break; > } > - > - return ngx_http_range_multipart_header(r, ctx); > - > - case NGX_HTTP_RANGE_NOT_SATISFIABLE: > - return ngx_http_range_not_satisfiable(r); > - > - case NGX_ERROR: > - return NGX_ERROR; > - > + break; > default: /* NGX_DECLINED */ > break; > } > @@ -274,13 +284,12 @@ > ngx_uint_t ranges) > { > u_char *p; > - off_t start, end, size, content_length; > + off_t start, end, size; > ngx_uint_t suffix; > ngx_http_range_t *range; > > p = r->headers_in.range->value.data + 6; > size = 0; > - content_length = r->headers_out.content_length_n; > > for ( ;; ) { > start = 0; > @@ -298,6 +307,10 @@ > start = start * 10 + *p++ - '0'; > } > > + if (start < ctx->offset) { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > while (*p == ' ') { p++; } > > if (*p++ != '-') { > @@ -307,7 +320,7 @@ > while (*p == ' ') { p++; } > > if (*p == ',' || *p == '\0') { > - end = content_length; > + end = ctx->content_length; > goto found; > } > > @@ -331,12 +344,12 @@ > } > > if (suffix) { > - start = content_length - end; > - end = content_length - 1; > + start = ctx->content_length - end; > + end = ctx->content_length - 1; > } > > - if (end >= content_length) { > - end = content_length; > + if (end >= ctx->content_length) { > + end = ctx->content_length; > > } else { > end++; > @@ -369,7 +382,7 @@ > return NGX_HTTP_RANGE_NOT_SATISFIABLE; > } > > - if (size > content_length) { > + if (size > ctx->content_length) { > return NGX_DECLINED; > } > > @@ -384,16 +397,18 @@ > ngx_table_elt_t *content_range; > ngx_http_range_t *range; > > - content_range = ngx_list_push(&r->headers_out.headers); > - if (content_range == NULL) { > - return NGX_ERROR; > + if (r->headers_out.content_range == NULL) { > + content_range = ngx_list_push(&r->headers_out.headers); > + if (content_range == NULL) { > + return NGX_ERROR; > + } > + r->headers_out.content_range = content_range; > + content_range->hash = 1; > + ngx_str_set(&content_range->key, "Content-Range"); > + } else { > + content_range = r->headers_out.content_range; > } > > - r->headers_out.content_range = content_range; > - > - content_range->hash = 1; > - ngx_str_set(&content_range->key, "Content-Range"); > - > content_range->value.data = ngx_pnalloc(r->pool, > sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN); > if (content_range->value.data == NULL) { > @@ -407,7 +422,7 @@ > content_range->value.len = ngx_sprintf(content_range->value.data, > "bytes %O-%O/%O", > range->start, range->end - 1, > - r->headers_out.content_length_n) > + ctx->content_length) > - content_range->value.data; > > r->headers_out.content_length_n = range->end - range->start; > @@ -546,22 +561,25 @@ > > > static ngx_int_t > -ngx_http_range_not_satisfiable(ngx_http_request_t *r) > +ngx_http_range_not_satisfiable(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx) > { > ngx_table_elt_t *content_range; > > r->headers_out.status = NGX_HTTP_RANGE_NOT_SATISFIABLE; > > - content_range = ngx_list_push(&r->headers_out.headers); > - if (content_range == NULL) { > - return NGX_ERROR; > + if (r->headers_out.content_range == NULL) { > + content_range = ngx_list_push(&r->headers_out.headers); > + if (content_range == NULL) { > + return NGX_ERROR; > + } > + r->headers_out.content_range = content_range; > + content_range->hash = 1; > + ngx_str_set(&content_range->key, "Content-Range"); > + } else { > + content_range = r->headers_out.content_range; > } > > - r->headers_out.content_range = content_range; > - > - content_range->hash = 1; > - ngx_str_set(&content_range->key, "Content-Range"); > - > content_range->value.data = ngx_pnalloc(r->pool, > sizeof("bytes */") - 1 + NGX_OFF_T_LEN); > if (content_range->value.data == NULL) { > @@ -570,7 +588,7 @@ > > content_range->value.len = ngx_sprintf(content_range->value.data, > "bytes */%O", > - r->headers_out.content_length_n) > + ctx->content_length) > - content_range->value.data; > > ngx_http_clear_content_length(r); > @@ -888,3 +906,76 @@ > > return NGX_OK; > } > + > + > +static ngx_int_t > +ngx_http_content_range_parse(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx) > +{ > + u_char *p; > + off_t start, end, len; > + > + ctx->offset = 0; > + ctx->content_length = r->headers_out.content_length_n; > + > + if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) { > + return NGX_OK; > + } > + > + if (r->headers_out.content_range == NULL > + || r->headers_out.content_range->value.len == 0) { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + if (r->headers_out.content_range->value.len < 7 > + || ngx_strncasecmp(r->headers_out.content_range->value.data, > + (u_char *) "bytes ", 6) != 0) { > + return NGX_DECLINED; > + } > + > + start = 0; > + end = 0; > + len = 0; > + > + p = r->headers_out.content_range->value.data + 6; > + > + while (*p == ' ') { p++; } > + > + if (*p < '0' || *p > '9') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + while (*p >= '0' && *p <= '9') { > + start = start * 10 + *p++ - '0'; > + } > + > + if (*p++ != '-') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + while (*p >= '0' && *p <= '9') { > + end = end * 10 + *p++ - '0'; > + } > + > + if (*p++ != '/') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + if (*p < '0' || *p > '9') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + while (*p >= '0' && *p <= '9') { > + len = len * 10 + *p++ - '0'; > + } > + > + if (*p != '\0') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + ctx->offset = start; > + ctx->content_length = len; > + > + return NGX_OK; > +} > + > diff -r 1573fc7875fa -r 05d3973ece9a src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Wed Nov 26 18:35:37 2014 -0800 > +++ b/src/http/ngx_http_upstream.c Thu Dec 04 21:06:44 2014 +0000 > @@ -292,6 +292,11 @@ > ngx_http_upstream_copy_content_encoding, 0, 0 }, > #endif > > + { ngx_string("Content-Range"), > + ngx_http_upstream_ignore_header_line, 0, > + ngx_http_upstream_copy_allow_ranges, > + offsetof(ngx_http_headers_out_t, content_range), 1 }, > + > { ngx_null_string, NULL, 0, NULL, 0, 0 } > }; > > @@ -4516,37 +4521,26 @@ > ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, > ngx_table_elt_t *h, ngx_uint_t offset) > { > - ngx_table_elt_t *ho; > - > if (r->upstream->conf->force_ranges) { > return NGX_OK; > } > - > #if (NGX_HTTP_CACHE) > - > if (r->cached) { > r->allow_ranges = 1; > - return NGX_OK; > + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { > + return NGX_OK; > + } > } > > if (r->upstream->cacheable) { > r->allow_ranges = 1; > r->single_range = 1; > - return NGX_OK; > - } > - > + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { > + return NGX_OK; > + } > + } > #endif > - > - ho = ngx_list_push(&r->headers_out.headers); > - if (ho == NULL) { > - return NGX_ERROR; > - } > - > - *ho = *h; > - > - r->headers_out.accept_ranges = ho; > - > - return NGX_OK; > + return ngx_http_upstream_copy_header_line(r, h, offset); > } > > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Fri Dec 5 16:00:43 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 5 Dec 2014 19:00:43 +0300 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests In-Reply-To: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> References: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> Message-ID: <20141205160043.GM62402@mdounin.ru> Hello! On Thu, Dec 04, 2014 at 09:07:57PM +0000, Steven Hartland wrote: > # HG changeset patch > # User Steven Hartland > # Date 1417727204 0 > # Thu Dec 04 21:06:44 2014 +0000 > # Node ID 05d3973ece9af030d0312932938fc3d1f2f139dd > # Parent 1573fc7875fa09ee55763ce7ddc4e98d61e1deaf > Allow Partial Content responses to satisfy Range requests I would suggest something like: Range filter: support for 206 Partial Content responses. Some explanation on how to use these changes may be also helpful, as out of the box nginx won't be able to do anything good with it. In general I think that this change is interesting, but there are some rough edges. See below for various comments. > > diff -r 1573fc7875fa -r 05d3973ece9a src/http/modules/ngx_http_range_filter_module.c > --- a/src/http/modules/ngx_http_range_filter_module.c Wed Nov 26 18:35:37 2014 -0800 > +++ b/src/http/modules/ngx_http_range_filter_module.c Thu Dec 04 21:06:44 2014 +0000 > @@ -54,6 +54,7 @@ > > typedef struct { > off_t offset; > + off_t content_length; > ngx_str_t boundary_header; > ngx_array_t ranges; > } ngx_http_range_filter_ctx_t; > @@ -65,7 +66,8 @@ > ngx_http_range_filter_ctx_t *ctx); > static ngx_int_t ngx_http_range_multipart_header(ngx_http_request_t *r, > ngx_http_range_filter_ctx_t *ctx); > -static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r); > +static ngx_int_t ngx_http_range_not_satisfiable(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx); > static ngx_int_t ngx_http_range_test_overlapped(ngx_http_request_t *r, > ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in); > static ngx_int_t ngx_http_range_singlepart_body(ngx_http_request_t *r, > @@ -76,6 +78,9 @@ > static ngx_int_t ngx_http_range_header_filter_init(ngx_conf_t *cf); > static ngx_int_t ngx_http_range_body_filter_init(ngx_conf_t *cf); > > +static ngx_int_t ngx_http_content_range_parse(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx); > + Functions in the range filter use "ngx_http_range_*" prefix, so there should be a better name. Also, both the declaration and function body should be placed eslewhere, see below. > > static ngx_http_module_t ngx_http_range_header_filter_module_ctx = { > NULL, /* preconfiguration */ > @@ -153,8 +158,8 @@ > ngx_http_range_filter_ctx_t *ctx; > > if (r->http_version < NGX_HTTP_VERSION_10 > - || r->headers_out.status != NGX_HTTP_OK > - || r != r->main > + || (r->headers_out.status != NGX_HTTP_OK > + && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) > || r->headers_out.content_length_n == -1 > || !r->allow_ranges) > { Style, should be: @@ -153,8 +158,8 @@ ngx_http_range_header_filter(ngx_http_re ngx_http_range_filter_ctx_t *ctx; if (r->http_version < NGX_HTTP_VERSION_10 - || r->headers_out.status != NGX_HTTP_OK - || r != r->main + || (r->headers_out.status != NGX_HTTP_OK + && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) || r->headers_out.content_length_n == -1 || !r->allow_ranges) { > @@ -230,26 +235,31 @@ > > ranges = r->single_range ? 1 : clcf->max_ranges; > > - switch (ngx_http_range_parse(r, ctx, ranges)) { > + switch (ngx_http_content_range_parse(r, ctx)) { > + case NGX_OK: If there are only two possible results of ngx_http_content_range_parse(), there is no real reason to use switch here. Just an if with "goto next_filter" should do. > + switch (ngx_http_range_parse(r, ctx, ranges)) { > + case NGX_OK: > + ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); > > - case NGX_OK: > - ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module); > + r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; > + r->headers_out.status_line.len = 0; > > - r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT; > - r->headers_out.status_line.len = 0; > + if (ctx->ranges.nelts == 1) { > + return ngx_http_range_singlepart_header(r, ctx); > + } > > - if (ctx->ranges.nelts == 1) { > - return ngx_http_range_singlepart_header(r, ctx); > + return ngx_http_range_multipart_header(r, ctx); > + > + case NGX_HTTP_RANGE_NOT_SATISFIABLE: > + return ngx_http_range_not_satisfiable(r, ctx); > + > + case NGX_ERROR: > + return NGX_ERROR; > + > + default: /* NGX_DECLINED */ > + break; > } > - > - return ngx_http_range_multipart_header(r, ctx); > - > - case NGX_HTTP_RANGE_NOT_SATISFIABLE: > - return ngx_http_range_not_satisfiable(r); > - > - case NGX_ERROR: > - return NGX_ERROR; > - > + break; > default: /* NGX_DECLINED */ > break; > } > @@ -274,13 +284,12 @@ Please put [diff] showfunc=1 into your ~/.hgrc, it'll make patches more readable. Thanks. > ngx_uint_t ranges) > { > u_char *p; > - off_t start, end, size, content_length; > + off_t start, end, size; > ngx_uint_t suffix; > ngx_http_range_t *range; > > p = r->headers_in.range->value.data + 6; > size = 0; > - content_length = r->headers_out.content_length_n; Just using ctx->content_length here may be a better option. > > for ( ;; ) { > start = 0; > @@ -298,6 +307,10 @@ > start = start * 10 + *p++ - '0'; > } > > + if (start < ctx->offset) { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + That's wrong return code. Additionally, this probably needs some logging, as this situation indicates a problem elsewhere: a 206 Partial Content response was used to answer a request for a range not covered by the response. > while (*p == ' ') { p++; } > > if (*p++ != '-') { > @@ -307,7 +320,7 @@ > while (*p == ' ') { p++; } > > if (*p == ',' || *p == '\0') { > - end = content_length; > + end = ctx->content_length; > goto found; > } > > @@ -331,12 +344,12 @@ > } > > if (suffix) { > - start = content_length - end; > - end = content_length - 1; > + start = ctx->content_length - end; > + end = ctx->content_length - 1; > } > > - if (end >= content_length) { > - end = content_length; > + if (end >= ctx->content_length) { > + end = ctx->content_length; > > } else { > end++; > @@ -369,7 +382,7 @@ > return NGX_HTTP_RANGE_NOT_SATISFIABLE; > } > > - if (size > content_length) { > + if (size > ctx->content_length) { > return NGX_DECLINED; > } > > @@ -384,16 +397,18 @@ > ngx_table_elt_t *content_range; > ngx_http_range_t *range; > > - content_range = ngx_list_push(&r->headers_out.headers); > - if (content_range == NULL) { > - return NGX_ERROR; > + if (r->headers_out.content_range == NULL) { > + content_range = ngx_list_push(&r->headers_out.headers); > + if (content_range == NULL) { > + return NGX_ERROR; > + } > + r->headers_out.content_range = content_range; > + content_range->hash = 1; > + ngx_str_set(&content_range->key, "Content-Range"); > + } else { > + content_range = r->headers_out.content_range; > } > > - r->headers_out.content_range = content_range; > - > - content_range->hash = 1; > - ngx_str_set(&content_range->key, "Content-Range"); > - > content_range->value.data = ngx_pnalloc(r->pool, > sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN); > if (content_range->value.data == NULL) { It might be easier to just remove an old header if it's here, like this: @@ -389,6 +389,10 @@ ngx_http_range_singlepart_header(ngx_htt return NGX_ERROR; } + if (r->headers_out.content_range) { + r->headers_out.content_range->hash = 0; + } + r->headers_out.content_range = content_range; content_range->hash = 1; Additionally, it looks like appropriate modifications to ngx_http_range_multipart_header() are missing. This will result in unneeded/confusing Content-Range header in multipart/ranges responses produced from 206 responses. > @@ -407,7 +422,7 @@ > content_range->value.len = ngx_sprintf(content_range->value.data, > "bytes %O-%O/%O", > range->start, range->end - 1, > - r->headers_out.content_length_n) > + ctx->content_length) > - content_range->value.data; > > r->headers_out.content_length_n = range->end - range->start; > @@ -546,22 +561,25 @@ > > > static ngx_int_t > -ngx_http_range_not_satisfiable(ngx_http_request_t *r) > +ngx_http_range_not_satisfiable(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx) > { > ngx_table_elt_t *content_range; > > r->headers_out.status = NGX_HTTP_RANGE_NOT_SATISFIABLE; > > - content_range = ngx_list_push(&r->headers_out.headers); > - if (content_range == NULL) { > - return NGX_ERROR; > + if (r->headers_out.content_range == NULL) { > + content_range = ngx_list_push(&r->headers_out.headers); > + if (content_range == NULL) { > + return NGX_ERROR; > + } > + r->headers_out.content_range = content_range; > + content_range->hash = 1; > + ngx_str_set(&content_range->key, "Content-Range"); > + } else { > + content_range = r->headers_out.content_range; > } > > - r->headers_out.content_range = content_range; > - > - content_range->hash = 1; > - ngx_str_set(&content_range->key, "Content-Range"); > - > content_range->value.data = ngx_pnalloc(r->pool, > sizeof("bytes */") - 1 + NGX_OFF_T_LEN); > if (content_range->value.data == NULL) { Same here. > @@ -570,7 +588,7 @@ > > content_range->value.len = ngx_sprintf(content_range->value.data, > "bytes */%O", > - r->headers_out.content_length_n) > + ctx->content_length) > - content_range->value.data; > > ngx_http_clear_content_length(r); > @@ -888,3 +906,76 @@ > > return NGX_OK; > } > + > + > +static ngx_int_t > +ngx_http_content_range_parse(ngx_http_request_t *r, > + ngx_http_range_filter_ctx_t *ctx) > +{ This should be placed elsewhere. Normally we functions in the order of execution. That is, as this function is called from ngx_http_range_header_filter(), it should be placed after ngx_http_range_header_filter(). And as it's called just before ngx_http_range_parse(), it should be placed somewhere above ngx_http_range_parse(). > + u_char *p; > + off_t start, end, len; Style, should be: off_t start, end, len; u_char *p; > + > + ctx->offset = 0; > + ctx->content_length = r->headers_out.content_length_n; > + > + if (r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT) { > + return NGX_OK; > + } Style, should be 4 spaces. > + > + if (r->headers_out.content_range == NULL > + || r->headers_out.content_range->value.len == 0) { Style, "{" should be on it's own line. > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } NGX_HTTP_RANGE_NOT_SATISFIABLE is wrong and confusing here. It's not checked/used by the calling code, but nevertheless shouldn't be here. The same applies to other uses of NGX_HTTP_RANGE_NOT_SATISFIABLE in this function. > + > + if (r->headers_out.content_range->value.len < 7 > + || ngx_strncasecmp(r->headers_out.content_range->value.data, > + (u_char *) "bytes ", 6) != 0) { > + return NGX_DECLINED; > + } Style, "{" should be on it's own line. > + > + start = 0; > + end = 0; > + len = 0; > + > + p = r->headers_out.content_range->value.data + 6; > + > + while (*p == ' ') { p++; } > + > + if (*p < '0' || *p > '9') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + while (*p >= '0' && *p <= '9') { > + start = start * 10 + *p++ - '0'; > + } > + > + if (*p++ != '-') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + while (*p >= '0' && *p <= '9') { > + end = end * 10 + *p++ - '0'; > + } > + > + if (*p++ != '/') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + if (*p < '0' || *p > '9') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + while (*p >= '0' && *p <= '9') { > + len = len * 10 + *p++ - '0'; > + } > + > + if (*p != '\0') { > + return NGX_HTTP_RANGE_NOT_SATISFIABLE; > + } > + > + ctx->offset = start; > + ctx->content_length = len; > + > + return NGX_OK; > +} > + > diff -r 1573fc7875fa -r 05d3973ece9a src/http/ngx_http_upstream.c > --- a/src/http/ngx_http_upstream.c Wed Nov 26 18:35:37 2014 -0800 > +++ b/src/http/ngx_http_upstream.c Thu Dec 04 21:06:44 2014 +0000 > @@ -292,6 +292,11 @@ > ngx_http_upstream_copy_content_encoding, 0, 0 }, > #endif > > + { ngx_string("Content-Range"), > + ngx_http_upstream_ignore_header_line, 0, > + ngx_http_upstream_copy_allow_ranges, > + offsetof(ngx_http_headers_out_t, content_range), 1 }, > + Placing this right after Accept-Ranges may be better. > { ngx_null_string, NULL, 0, NULL, 0, 0 } > }; > > @@ -4516,37 +4521,26 @@ > ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, > ngx_table_elt_t *h, ngx_uint_t offset) > { > - ngx_table_elt_t *ho; > - > if (r->upstream->conf->force_ranges) { > return NGX_OK; > } > - > #if (NGX_HTTP_CACHE) > - Style, empty lines should be here. > if (r->cached) { > r->allow_ranges = 1; > - return NGX_OK; > + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { > + return NGX_OK; > + } > } It may be better idea to introduce a separate copy function instead. > > if (r->upstream->cacheable) { > r->allow_ranges = 1; > r->single_range = 1; > - return NGX_OK; > - } > - > + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { > + return NGX_OK; > + } > + } > #endif > - > - ho = ngx_list_push(&r->headers_out.headers); > - if (ho == NULL) { > - return NGX_ERROR; > - } > - > - *ho = *h; > - > - r->headers_out.accept_ranges = ho; > - > - return NGX_OK; > + return ngx_http_upstream_copy_header_line(r, h, offset); I don't think that ngx_http_upstream_copy_header_line() worth it. > } > > > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel -- Maxim Dounin http://nginx.org/ From steven.hartland at multiplay.co.uk Fri Dec 5 19:38:18 2014 From: steven.hartland at multiplay.co.uk (Steven Hartland) Date: Fri, 05 Dec 2014 19:38:18 +0000 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests In-Reply-To: <20141205160043.GM62402@mdounin.ru> References: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> <20141205160043.GM62402@mdounin.ru> Message-ID: <548209AA.3030900@multiplay.co.uk> First off thanks for reviewing, comments / questions inline below On 05/12/2014 16:00, Maxim Dounin wrote: > Hello! > > On Thu, Dec 04, 2014 at 09:07:57PM +0000, Steven Hartland wrote: > >> # HG changeset patch >> # User Steven Hartland >> # Date 1417727204 0 >> # Thu Dec 04 21:06:44 2014 +0000 >> # Node ID 05d3973ece9af030d0312932938fc3d1f2f139dd >> # Parent 1573fc7875fa09ee55763ce7ddc4e98d61e1deaf >> Allow Partial Content responses to satisfy Range requests > I would suggest something like: > > Range filter: support for 206 Partial Content responses. > > Some explanation on how to use these changes may be also helpful, > as out of the box nginx won't be able to do anything good with it. Looks like I lost the full comment when trying to make hg do a squash, its not as nice to work with as git, which I guess is why Google are migrating their golang repo to github ;-) I'll restore this in the next patch but for now here's some details. The driver for the changes is an additional module we've been developing which based on this core enhancement can use predictably split range requests to satisfy other requests. This allows nginx to cache the responses to client downloads that use random ranges to achieve full file downloads, such clients include EA's Origin, Microsoft's XBox and Blizzard's downloaders which source from CDN's such as Akamai and Limelight Networks. What the module does is rewrite the random range request sent by the client into one or more ranges with predictable boundaries. Then in the uncached case it makes the required requests to the origin allowing nginx core to cache the results. As the responses come in it combines them to satisfy the initial range request sent by the client. Of course some may be previously cached responses. The result is a caching proxy that can build up a full copy of the file by downloading individual ranges, none of which overlap; without which you see massive duplication in the cache, resulting not only in wasted local space but also slower downloads as the cache does multiple requests for the same data from the origin server. This could also be used to return a quicker response to the client when caching a large file from an upstream source. Currently in a multi client scenario where you want to avoid duplicate requests its requires the entire file to be downloaded and cached before the responses start. If the file where split into ranges the clients would only have to wait until the current chunk processed until it could start getting data, reducing the risk for timeouts with large files. More information on this can be seen on our blog here: http://blog.multiplay.co.uk/2014/04/lancache-dynamically-caching-game-installs-at-lans-using-nginx/ > In general I think that this change is interesting, but there are > some rough edges. See below for various comments. > >> ngx_uint_t ranges) >> { >> u_char *p; >> - off_t start, end, size, content_length; >> + off_t start, end, size; >> ngx_uint_t suffix; >> ngx_http_range_t *range; >> >> p = r->headers_in.range->value.data + 6; >> size = 0; >> - content_length = r->headers_out.content_length_n; > Just using ctx->content_length here may be a better option. Sorry I'm not sure I follow you correctly, do you mean set the old content_length local from ctx->content_lenght keeping the diff minimal? > @@ -384,16 +397,18 @@ > ngx_table_elt_t *content_range; > ngx_http_range_t *range; > > - content_range = ngx_list_push(&r->headers_out.headers); > - if (content_range == NULL) { > - return NGX_ERROR; > + if (r->headers_out.content_range == NULL) { > + content_range = ngx_list_push(&r->headers_out.headers); > + if (content_range == NULL) { > + return NGX_ERROR; > + } > + r->headers_out.content_range = content_range; > + content_range->hash = 1; > + ngx_str_set(&content_range->key, "Content-Range"); > + } else { > + content_range = r->headers_out.content_range; > } > ... > > Additionally, it looks like appropriate modifications to > ngx_http_range_multipart_header() are missing. This will result > in unneeded/confusing Content-Range header in multipart/ranges > responses produced from 206 responses. Nice catch will need to work on this one. >> + return NGX_HTTP_RANGE_NOT_SATISFIABLE; >> + } > NGX_HTTP_RANGE_NOT_SATISFIABLE is wrong and confusing here. It's > not checked/used by the calling code, but nevertheless shouldn't > be here. > > The same applies to other uses of NGX_HTTP_RANGE_NOT_SATISFIABLE > in this function. Will look into these >> { ngx_null_string, NULL, 0, NULL, 0, 0 } >> }; >> >> @@ -4516,37 +4521,26 @@ >> ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, >> ngx_table_elt_t *h, ngx_uint_t offset) >> { >> - ngx_table_elt_t *ho; >> - >> if (r->upstream->conf->force_ranges) { >> return NGX_OK; >> } >> - >> #if (NGX_HTTP_CACHE) >> - > Style, empty lines should be here. I removed as it was inconsistent with the function above, could you confirm the details of this style requirement please so I know for the future? > >> if (r->cached) { >> r->allow_ranges = 1; >> - return NGX_OK; >> + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { >> + return NGX_OK; >> + } >> } > It may be better idea to introduce a separate copy function > instead. > >> >> if (r->upstream->cacheable) { >> r->allow_ranges = 1; >> r->single_range = 1; >> - return NGX_OK; >> - } >> - >> + if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { >> + return NGX_OK; >> + } >> + } >> #endif >> - >> - ho = ngx_list_push(&r->headers_out.headers); >> - if (ho == NULL) { >> - return NGX_ERROR; >> - } >> - >> - *ho = *h; >> - >> - r->headers_out.accept_ranges = ho; >> - >> - return NGX_OK; >> + return ngx_http_upstream_copy_header_line(r, h, offset); > I don't think that ngx_http_upstream_copy_header_line() worth it. I thought it would be wasteful to copy the function instead of making the small amendments to make it more generic and reuse ngx_http_upstream_copy_header_line instead of a hand rolled version of it. Its easy enough to make it independent if you think that's the better option? Regards Steve From agentzh at gmail.com Fri Dec 5 23:41:09 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Fri, 5 Dec 2014 15:41:09 -0800 Subject: Document the changeability of the nginx builtin variables? Message-ID: Hello! I suggest that the official nginx documentation should explicitly document whether a particular built-in variable is changeable or readonly. For example, $http_name variables do not allow overwrites but $args does. Such explicit documentation and avoid a lot of confusion for new comers. Thanks! -agentzh From agentzh at gmail.com Fri Dec 5 23:45:50 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Fri, 5 Dec 2014 15:45:50 -0800 Subject: Document the affected running phases of configuration directive? Message-ID: Hello! It'll be great if the official nginx documentation documents the affected request running phase of each configuration directive. For example, proxy_pass affects the content phase while set_real_ip_from affects the post-read and pre-access phases. This can help a lot when the users try to combine directives of different modules and predict their relative running order. Right now we have to look into the nginx internals to be sure (either source code or debugging tools like gdb and systemtap). Thanks! -agentzh From grrm77 at gmail.com Sat Dec 6 17:25:10 2014 From: grrm77 at gmail.com (grrm grrm) Date: Sat, 6 Dec 2014 19:25:10 +0200 Subject: Unix domain sockets and relative paths Message-ID: Hello. Currently nginx uses the current working directory when instructed to listen on unix domain sockets. (which is probably the behaviour of the bind system call). Would it be possible to actually use the configuration prefix in place of cwd? Thanks. From mdounin at mdounin.ru Mon Dec 8 00:25:40 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Dec 2014 03:25:40 +0300 Subject: [PATCH] Allow Partial Content responses to satisfy Range requests In-Reply-To: <548209AA.3030900@multiplay.co.uk> References: <05d3973ece9af030d031.1417727277@blade26.multiplay.co.uk> <20141205160043.GM62402@mdounin.ru> <548209AA.3030900@multiplay.co.uk> Message-ID: <20141208002540.GO62402@mdounin.ru> Hello! On Fri, Dec 05, 2014 at 07:38:18PM +0000, Steven Hartland wrote: > First off thanks for reviewing, comments / questions inline below > > On 05/12/2014 16:00, Maxim Dounin wrote: > >Hello! > > > >On Thu, Dec 04, 2014 at 09:07:57PM +0000, Steven Hartland wrote: > > > >># HG changeset patch > >># User Steven Hartland > >># Date 1417727204 0 > >># Thu Dec 04 21:06:44 2014 +0000 > >># Node ID 05d3973ece9af030d0312932938fc3d1f2f139dd > >># Parent 1573fc7875fa09ee55763ce7ddc4e98d61e1deaf > >>Allow Partial Content responses to satisfy Range requests > >I would suggest something like: > > > >Range filter: support for 206 Partial Content responses. > > > >Some explanation on how to use these changes may be also helpful, > >as out of the box nginx won't be able to do anything good with it. > Looks like I lost the full comment when trying to make hg do a squash, its > not as nice to work with as git, Rebase and MQ extensions make "rewriting history" tasks easier in Mercurial. > which I guess is why Google are migrating > their golang repo to github ;-) Yes, we are also wonder how golang folks are going to maintain their "new VCS every year" trend. It's not that easy unless they will try some of them again, as they already used svn, p4, hg and now git. ;) > I'll restore this in the next patch but for now here's some details. > > The driver for the changes is an additional module we've been developing > which based on this core enhancement can use predictably split range > requests to satisfy other requests. [...] > More information on this can be seen on our blog here: > http://blog.multiplay.co.uk/2014/04/lancache-dynamically-caching-game-installs-at-lans-using-nginx/ The question is mostly about "native" use, if possible. I understand that your main goal is the module your are working on, but I suspect that this change may be used with some minimal configuration changes to improve range caching configs as in your blog post. > > >In general I think that this change is interesting, but there are > >some rough edges. See below for various comments. > > > >> ngx_uint_t ranges) > >> { > >> u_char *p; > >>- off_t start, end, size, content_length; > >>+ off_t start, end, size; > >> ngx_uint_t suffix; > >> ngx_http_range_t *range; > >> p = r->headers_in.range->value.data + 6; > >> size = 0; > >>- content_length = r->headers_out.content_length_n; > >Just using ctx->content_length here may be a better option. > Sorry I'm not sure I follow you correctly, do you mean set the old > content_length local from ctx->content_lenght keeping the diff minimal? Yes, I think that preserving content_length local variable should be a better option. [...] > >>@@ -4516,37 +4521,26 @@ > >> ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, > >> ngx_table_elt_t *h, ngx_uint_t offset) > >> { > >>- ngx_table_elt_t *ho; > >>- > >> if (r->upstream->conf->force_ranges) { > >> return NGX_OK; > >> } > >>- > >> #if (NGX_HTTP_CACHE) > >>- > >Style, empty lines should be here. > I removed as it was inconsistent with the function above, could you confirm > the details of this style requirement please so I know for the future? There are no strict rules on how to put empty lines, but in general preprocessor conditionals are separated by empty lines if conditional content is complex enough (e.g., contains an empty line). In the function about the content is trivial and so no empty lines there. [...] > >> if (r->cached) { > >> r->allow_ranges = 1; > >>- return NGX_OK; > >>+ if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { > >>+ return NGX_OK; > >>+ } > >> } > >It may be better idea to introduce a separate copy function > >instead. > > > >> if (r->upstream->cacheable) { > >> r->allow_ranges = 1; > >> r->single_range = 1; > >>- return NGX_OK; > >>- } > >>- > >>+ if (offsetof(ngx_http_headers_out_t, accept_ranges) == offset) { > >>+ return NGX_OK; > >>+ } > >>+ } > >> #endif > >>- > >>- ho = ngx_list_push(&r->headers_out.headers); > >>- if (ho == NULL) { > >>- return NGX_ERROR; > >>- } > >>- > >>- *ho = *h; > >>- > >>- r->headers_out.accept_ranges = ho; > >>- > >>- return NGX_OK; > >>+ return ngx_http_upstream_copy_header_line(r, h, offset); > >I don't think that ngx_http_upstream_copy_header_line() worth it. > > I thought it would be wasteful to copy the function instead of making the > small amendments to make it more generic and reuse > ngx_http_upstream_copy_header_line instead of a hand rolled version of it. > > Its easy enough to make it independent if you think that's the better > option? I think that separate copy function would be better option here. The code is going to be different enough to satisfy this. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Dec 8 00:33:48 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Dec 2014 03:33:48 +0300 Subject: Document the changeability of the nginx builtin variables? In-Reply-To: References: Message-ID: <20141208003348.GP62402@mdounin.ru> Hello! On Fri, Dec 05, 2014 at 03:41:09PM -0800, Yichun Zhang (agentzh) wrote: > Hello! > > I suggest that the official nginx documentation should explicitly > document whether a particular built-in variable is changeable or > readonly. For example, $http_name variables do not allow overwrites > but $args does. Such explicit documentation and avoid a lot of > confusion for new comers. The general rule is "built-in variables are not changeable", and I think that few exceptions are mostly results of some experiments. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Dec 8 00:38:26 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 8 Dec 2014 03:38:26 +0300 Subject: Document the affected running phases of configuration directive? In-Reply-To: References: Message-ID: <20141208003826.GQ62402@mdounin.ru> Hello! On Fri, Dec 05, 2014 at 03:45:50PM -0800, Yichun Zhang (agentzh) wrote: > Hello! > > It'll be great if the official nginx documentation documents the > affected request running phase of each configuration directive. For > example, proxy_pass affects the content phase while set_real_ip_from > affects the post-read and pre-access phases. This can help a lot when > the users try to combine directives of different modules and predict > their relative running order. Right now we have to look into the nginx > internals to be sure (either source code or debugging tools like gdb > and systemtap). Phases of processing is an implementation detail, and while understanding them sometimes helps to understand what goes on in some complex cases, it's not something to be exposed into the documentation. -- Maxim Dounin http://nginx.org/ From agentzh at gmail.com Mon Dec 8 03:56:42 2014 From: agentzh at gmail.com (Yichun Zhang (agentzh)) Date: Sun, 7 Dec 2014 19:56:42 -0800 Subject: [ANN] Test::Nginx 0.24 released Message-ID: Hi folks! I've just uploaded Test::Nginx 0.24 to CPAN: https://metacpan.org/release/Test-Nginx It will appear on the CPAN mirror near you in the next few hours or so. The highlights of this release are * the new benchmark testing mode [1] that can use ab or weighttp to load each test case, with configurable warm-up support, * the new "--- curl" section [2] that can output a curl command-line for the current test case, and * an enhanced Perl API [3] that allows custom subclasses of the Test::Nginx::Socket class to extend or even override the existing "--- xxx" sections in the test spec language ( this also makes it easy to build much more advanced test scaffolds for complicated Nginx/OpenResty-based web applications, for example, CloudFlare's Lua CDN, Lua SSL, and Lua WAF products' unit test suites are already powered by our own subclasses of Test::Nginx::Socket.) [1] https://metacpan.org/pod/Test::Nginx::Socket#TEST_NGINX_BENCHMARK [2] https://metacpan.org/pod/Test::Nginx::Socket#curl [3] https://metacpan.org/pod/Test::Nginx::Socket#add_block_preprocessor Special thanks go to all our contributors and users :) Here's the complete change log for this release (compared to the last CPAN release, 0.23): * feature: added support for the "benchmark" testing mode enabled by the TEST_NGINX_BENCHMARK environment variable. * feature: added support for the TEST_NGINX_BENCHMARK_WARMUP environment to specify the number of warm-up requests before the actual benchmark testing. * feature: added support for the "--- curl" section that generates a "curl" command line for the corresponding test request. * feature: added new section "--- server_name" to control the value of the server_name nginx config directive used for the default server {}. * feature: added new section "--- error_log_file". * feature: automatically print out warnings for [emerg] messages in nginx's error.log to stderr if it is not mentioned in "--- error_log" nor "--- no_error_log". * feature: Test::Nginx::Socket: "--- request" now supports leading comment lines prefixed by "#". * feature: the "--- user_files" section supports raw Perl data structures for specifying the user files. * feature: the "--- more_headers" section now supports perl array-ref typed values for pipelined requests. * feature: exported the "add_response_body_check" and "is_str" utility functions. * feature: the "--- udp_reply" section now accepts a Perl subroutine as its value which can be used to generate dynamic replies based on the actual query. thanks blablacio for the original patch. * feature: Test::Nginx::Socket: exported new Perl utility functions "add_cleanup_handler", "add_block_preprocessor", and "bail_out". * feature: made the special $LIBxxx_PATH variable more general in the "--- stap" section. * feature: the "--- no_error_log" section now tries to find all the matched lines in error logs instead of stopping on the first hit. * feature: added new section "--- tcp_shutdown" for shutting down read, write, or both parts of the connection in the embedded TCP server immedately after the connection is established. * feature: the value of "--- tcp_query_len" now defaults to the lenghth of the value of "--- tcp_query" (if any). * feature: added new section "--- must_die" for testing the cases that nginx fail to start (like invalid nginx configurations and etc). thanks Markus Linnala for the patch. * bugfix: when user specifies "Host" and "Connection" in "--- more_headers", then we should not add our own Host request headers. * bugfix: made the default value of the "Connection" request header to be "close" instead of "Close". * bugfix: the "check leak" testing mode might send a bogus request header via ab or weighttp. * bugfix: we should also wait for the time specified by the "--- abort" section before checking error logs for the repeated requests that are not the last one. * optimize disabled accept_mutex by default in the auto-generated nginx.conf. * bugfix: "--- skip_nginx" and "--- skip_nginx2" did not skip tests related to the mocked TCP and UDP servers. * bugfix: we did not automatically remove the .stp and .stp-out temp files created by the "--- stap" sections in the systemtap testing mode. * bugfix: "--- request" did not provide the guilty request line that it failed to parse. * bugfix: Test::Nginx::Socket: "--- error_code" might take bad values. * bugfix: we incorrectly discarded all the query data read in the mocked TCP server when timeout errors happen (due to the actual query is shorter than the expected data specified "--- tcp_query", for example). * bugfix: the "check leak" testing mode could not parse raw HTTP requests using LF instead of CRLF for line terminators. * doc: documented the section "--- init". * doc: added info for the openresty and openresty-en mailing lists for discussions. * doc: spelling fixes from Markus Linnala. This Perl module provides a test scaffold based on IO::Socket or LWP for automated testing in Nginx C module or ngx_lua-based Lua library development. This class inherits from Test::Base, thus bringing all its declarative power to the NginxC module testing practices. Please check out the full documentation on CPAN: https://metacpan.org/pod/Test::Nginx::Socket All of our Nginx modules (as well as our lua-resty-* libraries) are using Test::Nginx to drive their test suites. And it is also driving my test cluster running on Amazon EC2: http://qa.openresty.org Please note that this module is completely different from the Test::Nginx module created by Maxim Dounin. The git repository for this Perl module is hosted on GitHub: https://github.com/openresty/test-nginx Enjoy! Best regards, -agentzh From faskiri.devel at gmail.com Tue Dec 9 04:06:05 2014 From: faskiri.devel at gmail.com (Fasih) Date: Mon, 8 Dec 2014 20:06:05 -0800 Subject: Enabling SPDY per server block Message-ID: Hi I see that SPDY is enabled per ip and not per server. I hacked up the code to use the SNI information to find the virtual server and negotiate spdy only if it is enabled for that server block. This seems to work but I was wondering if there was any reason to do it per ip. Regards, +Fasih -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Tue Dec 9 13:25:12 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 09 Dec 2014 16:25:12 +0300 Subject: Enabling SPDY per server block In-Reply-To: References: Message-ID: <8649953.QaLloj509H@vbart-workstation> On Monday 08 December 2014 20:06:05 Fasih wrote: > Hi > > I see that SPDY is enabled per ip and not per server. I hacked up the code > to use the SNI information to find the virtual server and negotiate spdy > only if it is enabled for that server block. This seems to work but I was > wondering if there was any reason to do it per ip. > http://mailman.nginx.org/pipermail/nginx/2014-February/042048.html wbr, Valentin V. Bartenev From mdounin at mdounin.ru Tue Dec 9 15:21:03 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 09 Dec 2014 15:21:03 +0000 Subject: [nginx] Proxy: the "TE" header now stripped by default (ticket #... Message-ID: details: http://hg.nginx.org/nginx/rev/2d3908516101 branches: changeset: 5936:2d3908516101 user: Maxim Dounin date: Tue Dec 09 18:20:19 2014 +0300 description: Proxy: the "TE" header now stripped by default (ticket #537). diffstat: src/http/modules/ngx_http_proxy_module.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (19 lines): diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -715,6 +715,7 @@ static ngx_keyval_t ngx_http_proxy_head { ngx_string("Host"), ngx_string("$proxy_host") }, { ngx_string("Connection"), ngx_string("close") }, { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") }, + { ngx_string("TE"), ngx_string("") }, { ngx_string("Transfer-Encoding"), ngx_string("") }, { ngx_string("Keep-Alive"), ngx_string("") }, { ngx_string("Expect"), ngx_string("") }, @@ -742,6 +743,7 @@ static ngx_keyval_t ngx_http_proxy_cach { ngx_string("Host"), ngx_string("$proxy_host") }, { ngx_string("Connection"), ngx_string("close") }, { ngx_string("Content-Length"), ngx_string("$proxy_internal_body_length") }, + { ngx_string("TE"), ngx_string("") }, { ngx_string("Transfer-Encoding"), ngx_string("") }, { ngx_string("Keep-Alive"), ngx_string("") }, { ngx_string("Expect"), ngx_string("") }, From mdounin at mdounin.ru Tue Dec 9 15:53:36 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 09 Dec 2014 15:53:36 +0000 Subject: [nginx] Upstream: inheritance of proxy_pass and friends (ticket ... Message-ID: details: http://hg.nginx.org/nginx/rev/5b9f711dc819 branches: changeset: 5937:5b9f711dc819 user: Maxim Dounin date: Tue Dec 09 18:21:55 2014 +0300 description: Upstream: inheritance of proxy_pass and friends (ticket #645). Instead of independant inheritance of conf->upstream.upstream (proxy_pass without variables) and conf->proxy_lengths (proxy_pass with variables) we now test them both and inherit only if neither is set. Additionally, SSL context is also inherited only in this case now. Based on the patch by Alexey Radkov. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 5 +---- src/http/modules/ngx_http_proxy_module.c | 16 ++++++---------- src/http/modules/ngx_http_scgi_module.c | 5 +---- src/http/modules/ngx_http_uwsgi_module.c | 14 ++++++-------- 4 files changed, 14 insertions(+), 26 deletions(-) diffs (103 lines): diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2697,11 +2697,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL) { + if (conf->upstream.upstream == NULL && conf->fastcgi_lengths == NULL) { conf->upstream.upstream = prev->upstream.upstream; - } - - if (conf->fastcgi_lengths == NULL) { conf->fastcgi_lengths = prev->fastcgi_lengths; conf->fastcgi_values = prev->fastcgi_values; } diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -2968,12 +2968,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL); -#if (NGX_HTTP_SSL) - if (conf->upstream.ssl == NULL) { - conf->upstream.ssl = prev->upstream.ssl; - } -#endif - ngx_conf_merge_uint_value(conf->http_version, prev->http_version, NGX_HTTP_VERSION_10); @@ -2997,14 +2991,16 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL) { + if (conf->upstream.upstream == NULL && conf->proxy_lengths == NULL) { conf->upstream.upstream = prev->upstream.upstream; conf->vars = prev->vars; - } - - if (conf->proxy_lengths == NULL) { + conf->proxy_lengths = prev->proxy_lengths; conf->proxy_values = prev->proxy_values; + +#if (NGX_HTTP_SSL) + conf->upstream.ssl = prev->upstream.ssl; +#endif } if (conf->upstream.upstream || conf->proxy_lengths) { diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -1443,11 +1443,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL) { + if (conf->upstream.upstream == NULL && conf->scgi_lengths == NULL) { conf->upstream.upstream = prev->upstream.upstream; - } - - if (conf->scgi_lengths == NULL) { conf->scgi_lengths = prev->scgi_lengths; conf->scgi_values = prev->scgi_values; } diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1683,10 +1683,6 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.ssl == NULL) { - conf->upstream.ssl = prev->upstream.ssl; - } - #endif ngx_conf_merge_str_value(conf->uwsgi_string, prev->uwsgi_string, ""); @@ -1702,13 +1698,15 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL) { + if (conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL) { conf->upstream.upstream = prev->upstream.upstream; - } - - if (conf->uwsgi_lengths == NULL) { + conf->uwsgi_lengths = prev->uwsgi_lengths; conf->uwsgi_values = prev->uwsgi_values; + +#if (NGX_HTTP_SSL) + conf->upstream.ssl = prev->upstream.ssl; +#endif } if (conf->upstream.upstream || conf->uwsgi_lengths) { From mdounin at mdounin.ru Tue Dec 9 15:53:39 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 09 Dec 2014 15:53:39 +0000 Subject: [nginx] Upstream: fixed unexpected inheritance into limit_except... Message-ID: details: http://hg.nginx.org/nginx/rev/cd2abf7e7740 branches: changeset: 5938:cd2abf7e7740 user: Maxim Dounin date: Tue Dec 09 18:22:31 2014 +0300 description: Upstream: fixed unexpected inheritance into limit_except blocks. The proxy_pass directive and other handlers are not expected to be inherited into nested locations, but there is a special code to inherit upstream handlers into limit_except blocks, as well as a configuration into if{} blocks. This caused incorrect behaviour in configurations with nested locations and limit_except blocks, like this: location / { proxy_pass http://u; location /inner/ { # no proxy_pass here limit_except GET { # nothing } } } In such a configuration the limit_except block inside "location /inner/" unexpectedly used proxy_pass defined in "location /", while it shouldn't. Fix is to avoid inheritance of conf->upstream.upstream (and conf->proxy_lengths) into locations which don't have noname flag. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 15 +++++++++------ src/http/modules/ngx_http_proxy_module.c | 17 ++++++++++------- src/http/modules/ngx_http_scgi_module.c | 15 +++++++++------ src/http/modules/ngx_http_uwsgi_module.c | 15 +++++++++------ 4 files changed, 37 insertions(+), 25 deletions(-) diffs (126 lines): diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -2697,17 +2697,20 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL && conf->fastcgi_lengths == NULL) { + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + if (clcf->noname + && conf->upstream.upstream == NULL && conf->fastcgi_lengths == NULL) + { conf->upstream.upstream = prev->upstream.upstream; conf->fastcgi_lengths = prev->fastcgi_lengths; conf->fastcgi_values = prev->fastcgi_values; } - if (conf->upstream.upstream || conf->fastcgi_lengths) { - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - if (clcf->handler == NULL && clcf->lmt_excpt) { - clcf->handler = ngx_http_fastcgi_handler; - } + if (clcf->lmt_excpt && clcf->handler == NULL + && (conf->upstream.upstream || conf->fastcgi_lengths)) + { + clcf->handler = ngx_http_fastcgi_handler; } #if (NGX_PCRE) diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -2991,7 +2991,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL && conf->proxy_lengths == NULL) { + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + if (clcf->noname + && conf->upstream.upstream == NULL && conf->proxy_lengths == NULL) + { conf->upstream.upstream = prev->upstream.upstream; conf->vars = prev->vars; @@ -3003,12 +3007,11 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #endif } - if (conf->upstream.upstream || conf->proxy_lengths) { - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - if (clcf->handler == NULL && clcf->lmt_excpt) { - clcf->handler = ngx_http_proxy_handler; - conf->location = prev->location; - } + if (clcf->lmt_excpt && clcf->handler == NULL + && (conf->upstream.upstream || conf->proxy_lengths)) + { + clcf->handler = ngx_http_proxy_handler; + conf->location = prev->location; } if (conf->body_source.data == NULL) { diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -1443,17 +1443,20 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL && conf->scgi_lengths == NULL) { + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + if (clcf->noname + && conf->upstream.upstream == NULL && conf->scgi_lengths == NULL) + { conf->upstream.upstream = prev->upstream.upstream; conf->scgi_lengths = prev->scgi_lengths; conf->scgi_values = prev->scgi_values; } - if (conf->upstream.upstream || conf->scgi_lengths) { - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - if (clcf->handler == NULL && clcf->lmt_excpt) { - clcf->handler = ngx_http_scgi_handler; - } + if (clcf->lmt_excpt && clcf->handler == NULL + && (conf->upstream.upstream || conf->scgi_lengths)) + { + clcf->handler = ngx_http_scgi_handler; } if (conf->params_source == NULL) { diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -1698,7 +1698,11 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } - if (conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL) { + clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); + + if (clcf->noname + && conf->upstream.upstream == NULL && conf->uwsgi_lengths == NULL) + { conf->upstream.upstream = prev->upstream.upstream; conf->uwsgi_lengths = prev->uwsgi_lengths; @@ -1709,11 +1713,10 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t #endif } - if (conf->upstream.upstream || conf->uwsgi_lengths) { - clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); - if (clcf->handler == NULL && clcf->lmt_excpt) { - clcf->handler = ngx_http_uwsgi_handler; - } + if (clcf->lmt_excpt && clcf->handler == NULL + && (conf->upstream.upstream || conf->uwsgi_lengths)) + { + clcf->handler = ngx_http_uwsgi_handler; } ngx_conf_merge_uint_value(conf->modifier1, prev->modifier1, 0); From mdounin at mdounin.ru Tue Dec 9 15:53:41 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 09 Dec 2014 15:53:41 +0000 Subject: [nginx] Proxy: fixed incorrect URI change due to if (ticket #86). Message-ID: details: http://hg.nginx.org/nginx/rev/aeea0522332f branches: changeset: 5939:aeea0522332f user: Maxim Dounin date: Tue Dec 09 18:22:39 2014 +0300 description: Proxy: fixed incorrect URI change due to if (ticket #86). In the following configuration request was sent to a backend without URI changed to '/' due to if: location /proxy-pass-uri { proxy_pass http://127.0.0.1:8080/; set $true 1; if ($true) { # nothing } } Fix is to inherit conf->location from the location where proxy_pass was configured, much like it's done with conf->vars. diffstat: src/http/modules/ngx_http_proxy_module.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (19 lines): diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -2997,6 +2997,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t && conf->upstream.upstream == NULL && conf->proxy_lengths == NULL) { conf->upstream.upstream = prev->upstream.upstream; + conf->location = prev->location; conf->vars = prev->vars; conf->proxy_lengths = prev->proxy_lengths; @@ -3011,7 +3012,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t && (conf->upstream.upstream || conf->proxy_lengths)) { clcf->handler = ngx_http_proxy_handler; - conf->location = prev->location; } if (conf->body_source.data == NULL) { From vbart at nginx.com Thu Dec 11 13:32:54 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Thu, 11 Dec 2014 13:32:54 +0000 Subject: [nginx] Upstream: fixed inheritance of proxy_store and friends. Message-ID: details: http://hg.nginx.org/nginx/rev/e3b3b89d74e8 branches: changeset: 5940:e3b3b89d74e8 user: Valentin Bartenev date: Thu Oct 09 20:30:11 2014 +0400 description: Upstream: fixed inheritance of proxy_store and friends. The proxy_store, fastcgi_store, scgi_store and uwsgi_store were inherited incorrectly if a directive with variables was defined, and then redefined to the "on" value, i.e. in configurations like: proxy_store /data/www$upstream_http_x_store; location / { proxy_store on; } diffstat: src/http/modules/ngx_http_fastcgi_module.c | 2 +- src/http/modules/ngx_http_proxy_module.c | 2 +- src/http/modules/ngx_http_scgi_module.c | 2 +- src/http/modules/ngx_http_uwsgi_module.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diffs (48 lines): diff -r aeea0522332f -r e3b3b89d74e8 src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Tue Dec 09 18:22:39 2014 +0300 +++ b/src/http/modules/ngx_http_fastcgi_module.c Thu Oct 09 20:30:11 2014 +0400 @@ -2432,7 +2432,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; - if (conf->upstream.store != 0) { + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); diff -r aeea0522332f -r e3b3b89d74e8 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Tue Dec 09 18:22:39 2014 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Thu Oct 09 20:30:11 2014 +0400 @@ -2624,7 +2624,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_http_proxy_rewrite_t *pr; ngx_http_script_compile_t sc; - if (conf->upstream.store != 0) { + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); diff -r aeea0522332f -r e3b3b89d74e8 src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c Tue Dec 09 18:22:39 2014 +0300 +++ b/src/http/modules/ngx_http_scgi_module.c Thu Oct 09 20:30:11 2014 +0400 @@ -1186,7 +1186,7 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; - if (conf->upstream.store != 0) { + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); if (conf->upstream.store_lengths == NULL) { diff -r aeea0522332f -r e3b3b89d74e8 src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Tue Dec 09 18:22:39 2014 +0300 +++ b/src/http/modules/ngx_http_uwsgi_module.c Thu Oct 09 20:30:11 2014 +0400 @@ -1400,7 +1400,7 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; - if (conf->upstream.store != 0) { + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); if (conf->upstream.store_lengths == NULL) { From mdounin at mdounin.ru Thu Dec 11 20:42:59 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Dec 2014 20:42:59 +0000 Subject: [nginx] Headers filter: local variables for config, no functiona... Message-ID: details: http://hg.nginx.org/nginx/rev/36e61455a8f4 branches: changeset: 5941:36e61455a8f4 user: Maxim Dounin date: Thu Dec 11 23:42:06 2014 +0300 description: Headers filter: local variables for config, no functional changes. diffstat: src/http/modules/ngx_http_headers_filter_module.c | 58 ++++++++++++---------- 1 files changed, 31 insertions(+), 27 deletions(-) diffs (113 lines): diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -209,28 +209,32 @@ ngx_http_headers_filter(ngx_http_request static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) { - size_t len; - time_t now, expires_time, max_age; - ngx_uint_t i; - ngx_table_elt_t *expires, *cc, **ccp; + size_t len; + time_t now, expires_time, max_age; + ngx_uint_t i; + ngx_table_elt_t *e, *cc, **ccp; + ngx_http_expires_t expires; - expires = r->headers_out.expires; + expires = conf->expires; + expires_time = conf->expires_time; - if (expires == NULL) { + e = r->headers_out.expires; - expires = ngx_list_push(&r->headers_out.headers); - if (expires == NULL) { + if (e == NULL) { + + e = ngx_list_push(&r->headers_out.headers); + if (e == NULL) { return NGX_ERROR; } - r->headers_out.expires = expires; + r->headers_out.expires = e; - expires->hash = 1; - ngx_str_set(&expires->key, "Expires"); + e->hash = 1; + ngx_str_set(&e->key, "Expires"); } len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT"); - expires->value.len = len - 1; + e->value.len = len - 1; ccp = r->headers_out.cache_control.elts; @@ -265,26 +269,26 @@ ngx_http_set_expires(ngx_http_request_t cc = ccp[0]; } - if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) { - expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT"; + if (expires == NGX_HTTP_EXPIRES_EPOCH) { + e->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT"; ngx_str_set(&cc->value, "no-cache"); return NGX_OK; } - if (conf->expires == NGX_HTTP_EXPIRES_MAX) { - expires->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT"; + if (expires == NGX_HTTP_EXPIRES_MAX) { + e->value.data = (u_char *) "Thu, 31 Dec 2037 23:55:55 GMT"; /* 10 years */ ngx_str_set(&cc->value, "max-age=315360000"); return NGX_OK; } - expires->value.data = ngx_pnalloc(r->pool, len); - if (expires->value.data == NULL) { + e->value.data = ngx_pnalloc(r->pool, len); + if (e->value.data == NULL) { return NGX_ERROR; } - if (conf->expires_time == 0 && conf->expires != NGX_HTTP_EXPIRES_DAILY) { - ngx_memcpy(expires->value.data, ngx_cached_http_time.data, + if (expires_time == 0 && expires != NGX_HTTP_EXPIRES_DAILY) { + ngx_memcpy(e->value.data, ngx_cached_http_time.data, ngx_cached_http_time.len + 1); ngx_str_set(&cc->value, "max-age=0"); return NGX_OK; @@ -292,22 +296,22 @@ ngx_http_set_expires(ngx_http_request_t now = ngx_time(); - if (conf->expires == NGX_HTTP_EXPIRES_DAILY) { - expires_time = ngx_next_time(conf->expires_time); + if (expires == NGX_HTTP_EXPIRES_DAILY) { + expires_time = ngx_next_time(expires_time); max_age = expires_time - now; - } else if (conf->expires == NGX_HTTP_EXPIRES_ACCESS + } else if (expires == NGX_HTTP_EXPIRES_ACCESS || r->headers_out.last_modified_time == -1) { - expires_time = now + conf->expires_time; - max_age = conf->expires_time; + max_age = expires_time; + expires_time += now; } else { - expires_time = r->headers_out.last_modified_time + conf->expires_time; + expires_time += r->headers_out.last_modified_time; max_age = expires_time - now; } - ngx_http_time(expires->value.data, expires_time); + ngx_http_time(e->value.data, expires_time); if (conf->expires_time < 0 || max_age < 0) { ngx_str_set(&cc->value, "no-cache"); From mdounin at mdounin.ru Thu Dec 11 20:43:02 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 11 Dec 2014 20:43:02 +0000 Subject: [nginx] Headers filter: variables support in expires (ticket #113). Message-ID: details: http://hg.nginx.org/nginx/rev/4983f7d18fe3 branches: changeset: 5942:4983f7d18fe3 user: Maxim Dounin date: Thu Dec 11 23:42:11 2014 +0300 description: Headers filter: variables support in expires (ticket #113). diffstat: src/http/modules/ngx_http_headers_filter_module.c | 180 +++++++++++++++------ 1 files changed, 127 insertions(+), 53 deletions(-) diffs (259 lines): diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -44,14 +44,17 @@ typedef enum { typedef struct { - ngx_http_expires_t expires; - time_t expires_time; - ngx_array_t *headers; + ngx_http_expires_t expires; + time_t expires_time; + ngx_http_complex_value_t *expires_value; + ngx_array_t *headers; } ngx_http_headers_conf_t; static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf); +static ngx_int_t ngx_http_parse_expires(ngx_str_t *value, + ngx_http_expires_t *expires, time_t *expires_time, char **err); static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r, ngx_http_header_val_t *hv, ngx_str_t *value); static ngx_int_t ngx_http_add_header(ngx_http_request_t *r, @@ -209,8 +212,11 @@ ngx_http_headers_filter(ngx_http_request static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) { + char *err; size_t len; time_t now, expires_time, max_age; + ngx_str_t value; + ngx_int_t rc; ngx_uint_t i; ngx_table_elt_t *e, *cc, **ccp; ngx_http_expires_t expires; @@ -218,6 +224,23 @@ ngx_http_set_expires(ngx_http_request_t expires = conf->expires; expires_time = conf->expires_time; + if (conf->expires_value != NULL) { + + if (ngx_http_complex_value(r, conf->expires_value, &value) != NGX_OK) { + return NGX_ERROR; + } + + rc = ngx_http_parse_expires(&value, &expires, &expires_time, &err); + + if (rc != NGX_OK) { + return NGX_OK; + } + + if (expires == NGX_HTTP_EXPIRES_OFF) { + return NGX_OK; + } + } + e = r->headers_out.expires; if (e == NULL) { @@ -332,6 +355,78 @@ ngx_http_set_expires(ngx_http_request_t static ngx_int_t +ngx_http_parse_expires(ngx_str_t *value, ngx_http_expires_t *expires, + time_t *expires_time, char **err) +{ + ngx_uint_t minus; + + if (*expires != NGX_HTTP_EXPIRES_MODIFIED) { + + if (value->len == 5 && ngx_strncmp(value->data, "epoch", 5) == 0) { + *expires = NGX_HTTP_EXPIRES_EPOCH; + return NGX_OK; + } + + if (value->len == 3 && ngx_strncmp(value->data, "max", 3) == 0) { + *expires = NGX_HTTP_EXPIRES_MAX; + return NGX_OK; + } + + if (value->len == 3 && ngx_strncmp(value->data, "off", 3) == 0) { + *expires = NGX_HTTP_EXPIRES_OFF; + return NGX_OK; + } + } + + if (value->data[0] == '@') { + value->data++; + value->len--; + minus = 0; + + if (*expires == NGX_HTTP_EXPIRES_MODIFIED) { + *err = "daily time cannot be used with \"modified\" parameter"; + return NGX_ERROR; + } + + *expires = NGX_HTTP_EXPIRES_DAILY; + + } else if (value->data[0] == '+') { + value->data++; + value->len--; + minus = 0; + + } else if (value->data[0] == '-') { + value->data++; + value->len--; + minus = 1; + + } else { + minus = 0; + } + + *expires_time = ngx_parse_time(value, 1); + + if (*expires_time == (time_t) NGX_ERROR) { + *err = "invalid value"; + return NGX_ERROR; + } + + if (*expires == NGX_HTTP_EXPIRES_DAILY + && *expires_time > 24 * 60 * 60) + { + *err = "daily time value must be less than 24 hours"; + return NGX_ERROR; + } + + if (minus) { + *expires_time = - *expires_time; + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_add_header(ngx_http_request_t *r, ngx_http_header_val_t *hv, ngx_str_t *value) { @@ -461,6 +556,7 @@ ngx_http_headers_create_conf(ngx_conf_t * * conf->headers = NULL; * conf->expires_time = 0; + * conf->expires_value = NULL; */ conf->expires = NGX_HTTP_EXPIRES_UNSET; @@ -478,6 +574,7 @@ ngx_http_headers_merge_conf(ngx_conf_t * if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { conf->expires = prev->expires; conf->expires_time = prev->expires_time; + conf->expires_value = prev->expires_value; if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { conf->expires = NGX_HTTP_EXPIRES_OFF; @@ -507,8 +604,12 @@ ngx_http_headers_expires(ngx_conf_t *cf, { ngx_http_headers_conf_t *hcf = conf; - ngx_uint_t minus, n; - ngx_str_t *value; + char *err; + ngx_str_t *value; + ngx_int_t rc; + ngx_uint_t n; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) { return "is duplicate"; @@ -518,21 +619,6 @@ ngx_http_headers_expires(ngx_conf_t *cf, if (cf->args->nelts == 2) { - if (ngx_strcmp(value[1].data, "epoch") == 0) { - hcf->expires = NGX_HTTP_EXPIRES_EPOCH; - return NGX_CONF_OK; - } - - if (ngx_strcmp(value[1].data, "max") == 0) { - hcf->expires = NGX_HTTP_EXPIRES_MAX; - return NGX_CONF_OK; - } - - if (ngx_strcmp(value[1].data, "off") == 0) { - hcf->expires = NGX_HTTP_EXPIRES_OFF; - return NGX_CONF_OK; - } - hcf->expires = NGX_HTTP_EXPIRES_ACCESS; n = 1; @@ -548,45 +634,33 @@ ngx_http_headers_expires(ngx_conf_t *cf, n = 2; } - if (value[n].data[0] == '@') { - value[n].data++; - value[n].len--; - minus = 0; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - if (hcf->expires == NGX_HTTP_EXPIRES_MODIFIED) { - return "daily time cannot be used with \"modified\" parameter"; + ccv.cf = cf; + ccv.value = &value[n]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + + hcf->expires_value = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + if (hcf->expires_value == NULL) { + return NGX_CONF_ERROR; } - hcf->expires = NGX_HTTP_EXPIRES_DAILY; + *hcf->expires_value = cv; - } else if (value[n].data[0] == '+') { - value[n].data++; - value[n].len--; - minus = 0; - - } else if (value[n].data[0] == '-') { - value[n].data++; - value[n].len--; - minus = 1; - - } else { - minus = 0; + return NGX_CONF_OK; } - hcf->expires_time = ngx_parse_time(&value[n], 1); - - if (hcf->expires_time == (time_t) NGX_ERROR) { - return "invalid value"; - } - - if (hcf->expires == NGX_HTTP_EXPIRES_DAILY - && hcf->expires_time > 24 * 60 * 60) - { - return "daily time value must be less than 24 hours"; - } - - if (minus) { - hcf->expires_time = - hcf->expires_time; + rc = ngx_http_parse_expires(&value[n], &hcf->expires, &hcf->expires_time, + &err); + if (rc != NGX_OK) { + return err; } return NGX_CONF_OK; From vbart at nginx.com Fri Dec 12 17:26:52 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 12 Dec 2014 17:26:52 +0000 Subject: [nginx] Autoindex: rendering code moved to a separate function. Message-ID: details: http://hg.nginx.org/nginx/rev/631dee7bfd4e branches: changeset: 5943:631dee7bfd4e user: Valentin Bartenev date: Fri Dec 12 20:25:28 2014 +0300 description: Autoindex: rendering code moved to a separate function. No functional changes. diffstat: src/http/modules/ngx_http_autoindex_module.c | 168 +++++++++++++++----------- 1 files changed, 96 insertions(+), 72 deletions(-) diffs (253 lines): diff -r 4983f7d18fe3 -r 631dee7bfd4e src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c Thu Dec 11 23:42:11 2014 +0300 +++ b/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:28 2014 +0300 @@ -48,6 +48,8 @@ typedef struct { #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 +static ngx_buf_t *ngx_http_autoindex_html(ngx_http_request_t *r, + ngx_array_t *entries); static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two); static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, @@ -116,47 +118,23 @@ ngx_module_t ngx_http_autoindex_module }; -static u_char title[] = -"" CRLF -"Index of " -; - - -static u_char header[] = -"" CRLF -"" CRLF -"

Index of " -; - -static u_char tail[] = -"" CRLF -"" CRLF -; - - static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { - u_char *last, *filename, scale; - off_t length; - size_t len, char_len, escape_html, allocated, root; - ngx_tm_t tm; + u_char *last, *filename; + size_t len, allocated, root; ngx_err_t err; ngx_buf_t *b; - ngx_int_t rc, size; + ngx_int_t rc; ngx_str_t path; ngx_dir_t dir; - ngx_uint_t i, level, utf8; + ngx_uint_t level; ngx_pool_t *pool; - ngx_time_t *tp; ngx_chain_t out; ngx_array_t entries; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; - static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - if (r->uri.data[r->uri.len - 1] != '/') { return NGX_DECLINED; } @@ -249,16 +227,6 @@ ngx_http_autoindex_handler(ngx_http_requ filename = path.data; filename[path.len] = '/'; - if (r->headers_out.charset.len == 5 - && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) - == 0) - { - utf8 = 1; - - } else { - utf8 = 0; - } - for ( ;; ) { ngx_set_errno(0); @@ -339,18 +307,6 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); - entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, - NGX_ESCAPE_URI_COMPONENT); - - entry->escape_html = ngx_escape_html(NULL, entry->name.data, - entry->name.len); - - if (utf8) { - entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); - } else { - entry->utf_len = len; - } - entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); @@ -361,6 +317,76 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_close_dir_n " \"%V\" failed", &path); } + if (entries.nelts > 1) { + ngx_qsort(entries.elts, (size_t) entries.nelts, + sizeof(ngx_http_autoindex_entry_t), + ngx_http_autoindex_cmp_entries); + } + + b = ngx_http_autoindex_html(r, &entries); + + if (b == NULL) { + return NGX_ERROR; + } + + /* TODO: free temporary pool */ + + if (r == r->main) { + b->last_buf = 1; + } + + b->last_in_chain = 1; + + out.buf = b; + out.next = NULL; + + return ngx_http_output_filter(r, &out); +} + + +static ngx_buf_t * +ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries) +{ + u_char *last, scale; + off_t length; + size_t len, char_len, escape_html; + ngx_tm_t tm; + ngx_buf_t *b; + ngx_int_t size; + ngx_uint_t i, utf8; + ngx_time_t *tp; + ngx_http_autoindex_entry_t *entry; + ngx_http_autoindex_loc_conf_t *alcf; + + static u_char title[] = + "" CRLF + "Index of " + ; + + static u_char header[] = + "" CRLF + "" CRLF + "

Index of " + ; + + static u_char tail[] = + "" CRLF + "" CRLF + ; + + static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + if (r->headers_out.charset.len == 5 + && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) + == 0) + { + utf8 = 1; + + } else { + utf8 = 0; + } + escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); len = sizeof(title) - 1 @@ -372,8 +398,22 @@ ngx_http_autoindex_handler(ngx_http_requ + sizeof("
") - 1 + sizeof(tail) - 1; - entry = entries.elts; - for (i = 0; i < entries.nelts; i++) { + entry = entries->elts; + for (i = 0; i < entries->nelts; i++) { + entry[i].escape = 2 * ngx_escape_uri(NULL, entry[i].name.data, + entry[i].name.len, + NGX_ESCAPE_URI_COMPONENT); + + entry[i].escape_html = ngx_escape_html(NULL, entry[i].name.data, + entry[i].name.len); + + if (utf8) { + entry[i].utf_len = ngx_utf8_length(entry[i].name.data, + entry[i].name.len); + } else { + entry[i].utf_len = entry[i].name.len; + } + len += sizeof("pool, len); if (b == NULL) { - return NGX_ERROR; - } - - if (entries.nelts > 1) { - ngx_qsort(entry, (size_t) entries.nelts, - sizeof(ngx_http_autoindex_entry_t), - ngx_http_autoindex_cmp_entries); + return NULL; } b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); @@ -416,9 +450,10 @@ ngx_http_autoindex_handler(ngx_http_requ b->last = ngx_cpymem(b->last, "
../" CRLF,
                          sizeof("
../" CRLF) - 1);
 
+    alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module);
     tp = ngx_timeofday();
 
-    for (i = 0; i < entries.nelts; i++) {
+    for (i = 0; i < entries->nelts; i++) {
         b->last = ngx_cpymem(b->last, "last++ = LF;
     }
 
-    /* TODO: free temporary pool */
-
     b->last = ngx_cpymem(b->last, "

", sizeof("

") - 1); b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); - if (r == r->main) { - b->last_buf = 1; - } - - b->last_in_chain = 1; - - out.buf = b; - out.next = NULL; - - return ngx_http_output_filter(r, &out); + return b; } From vbart at nginx.com Fri Dec 12 17:26:55 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 12 Dec 2014 17:26:55 +0000 Subject: [nginx] Autoindex: implemented JSON output format. Message-ID: details: http://hg.nginx.org/nginx/rev/33c08d7e2915 branches: changeset: 5944:33c08d7e2915 user: Valentin Bartenev date: Fri Dec 12 20:25:35 2014 +0300 description: Autoindex: implemented JSON output format. diffstat: src/core/ngx_string.c | 52 ++++++ src/core/ngx_string.h | 1 + src/http/modules/ngx_http_autoindex_module.c | 226 ++++++++++++++++++++++++++- 3 files changed, 274 insertions(+), 5 deletions(-) diffs (truncated from 402 to 300 lines): diff -r 631dee7bfd4e -r 33c08d7e2915 src/core/ngx_string.c --- a/src/core/ngx_string.c Fri Dec 12 20:25:28 2014 +0300 +++ b/src/core/ngx_string.c Fri Dec 12 20:25:35 2014 +0300 @@ -1773,6 +1773,58 @@ ngx_escape_html(u_char *dst, u_char *src } +uintptr_t +ngx_escape_json(u_char *dst, u_char *src, size_t size) +{ + u_char ch; + ngx_uint_t len; + + if (dst == NULL) { + len = 0; + + while (size) { + ch = *src++; + + if (ch == '\\' || ch == '"') { + len++; + + } else if (ch <= 0x1f) { + len += sizeof("\\u001F") - 2; + } + + size--; + } + + return (uintptr_t) len; + } + + while (size) { + ch = *src++; + + if (ch > 0x1f) { + + if (ch == '\\' || ch == '"') { + *dst++ = '\\'; + } + + *dst++ = ch; + + } else { + *dst++ = '\\'; *dst++ = 'u'; *dst++ = '0'; *dst++ = '0'; + *dst++ = '0' + (ch >> 4); + + ch &= 0xf; + + *dst++ = (ch < 10) ? ('0' + ch) : ('A' + ch - 10); + } + + size--; + } + + return (uintptr_t) dst; +} + + void ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel) diff -r 631dee7bfd4e -r 33c08d7e2915 src/core/ngx_string.h --- a/src/core/ngx_string.h Fri Dec 12 20:25:28 2014 +0300 +++ b/src/core/ngx_string.h Fri Dec 12 20:25:35 2014 +0300 @@ -207,6 +207,7 @@ uintptr_t ngx_escape_uri(u_char *dst, u_ ngx_uint_t type); void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type); uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size); +uintptr_t ngx_escape_json(u_char *dst, u_char *src, size_t size); typedef struct { diff -r 631dee7bfd4e -r 33c08d7e2915 src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:28 2014 +0300 +++ b/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:35 2014 +0300 @@ -30,6 +30,7 @@ typedef struct { size_t escape_html; unsigned dir:1; + unsigned file:1; time_t mtime; off_t size; @@ -38,11 +39,16 @@ typedef struct { typedef struct { ngx_flag_t enable; + ngx_uint_t format; ngx_flag_t localtime; ngx_flag_t exact_size; } ngx_http_autoindex_loc_conf_t; +#define NGX_HTTP_AUTOINDEX_HTML 0 +#define NGX_HTTP_AUTOINDEX_JSON 1 +#define NGX_HTTP_AUTOINDEX_JSONP 2 + #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 #define NGX_HTTP_AUTOINDEX_NAME_LEN 50 @@ -50,16 +56,30 @@ typedef struct { static ngx_buf_t *ngx_http_autoindex_html(ngx_http_request_t *r, ngx_array_t *entries); +static ngx_buf_t *ngx_http_autoindex_json(ngx_http_request_t *r, + ngx_array_t *entries, ngx_str_t *callback); +static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, + ngx_str_t *callback); + static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two); static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, ngx_str_t *name); + static ngx_int_t ngx_http_autoindex_init(ngx_conf_t *cf); static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static ngx_conf_enum_t ngx_http_autoindex_format[] = { + { ngx_string("html"), NGX_HTTP_AUTOINDEX_HTML }, + { ngx_string("json"), NGX_HTTP_AUTOINDEX_JSON }, + { ngx_string("jsonp"), NGX_HTTP_AUTOINDEX_JSONP }, + { ngx_null_string, 0 } +}; + + static ngx_command_t ngx_http_autoindex_commands[] = { { ngx_string("autoindex"), @@ -69,6 +89,13 @@ static ngx_command_t ngx_http_autoindex offsetof(ngx_http_autoindex_loc_conf_t, enable), NULL }, + { ngx_string("autoindex_format"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_enum_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_autoindex_loc_conf_t, format), + &ngx_http_autoindex_format }, + { ngx_string("autoindex_localtime"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -126,9 +153,9 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_err_t err; ngx_buf_t *b; ngx_int_t rc; - ngx_str_t path; + ngx_str_t path, callback; ngx_dir_t dir; - ngx_uint_t level; + ngx_uint_t level, format; ngx_pool_t *pool; ngx_chain_t out; ngx_array_t entries; @@ -167,6 +194,18 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex: \"%s\"", path.data); + format = alcf->format; + + if (format == NGX_HTTP_AUTOINDEX_JSONP) { + if (ngx_http_autoindex_jsonp_callback(r, &callback) != NGX_OK) { + return NGX_HTTP_BAD_REQUEST; + } + + if (callback.len == 0) { + format = NGX_HTTP_AUTOINDEX_JSON; + } + } + if (ngx_open_dir(&path, &dir) == NGX_ERROR) { err = ngx_errno; @@ -209,8 +248,23 @@ ngx_http_autoindex_handler(ngx_http_requ } r->headers_out.status = NGX_HTTP_OK; - r->headers_out.content_type_len = sizeof("text/html") - 1; - ngx_str_set(&r->headers_out.content_type, "text/html"); + + switch (format) { + + case NGX_HTTP_AUTOINDEX_JSON: + ngx_str_set(&r->headers_out.content_type, "application/json"); + break; + + case NGX_HTTP_AUTOINDEX_JSONP: + ngx_str_set(&r->headers_out.content_type, "application/javascript"); + break; + + default: /* NGX_HTTP_AUTOINDEX_HTML */ + ngx_str_set(&r->headers_out.content_type, "text/html"); + break; + } + + r->headers_out.content_type_len = r->headers_out.content_type.len; r->headers_out.content_type_lowcase = NULL; rc = ngx_http_send_header(r); @@ -308,6 +362,7 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->dir = ngx_de_is_dir(&dir); + entry->file = ngx_de_is_file(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); } @@ -323,7 +378,20 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_http_autoindex_cmp_entries); } - b = ngx_http_autoindex_html(r, &entries); + switch (format) { + + case NGX_HTTP_AUTOINDEX_JSON: + b = ngx_http_autoindex_json(r, &entries, NULL); + break; + + case NGX_HTTP_AUTOINDEX_JSONP: + b = ngx_http_autoindex_json(r, &entries, &callback); + break; + + default: /* NGX_HTTP_AUTOINDEX_HTML */ + b = ngx_http_autoindex_html(r, &entries); + break; + } if (b == NULL) { return NGX_ERROR; @@ -608,6 +676,151 @@ ngx_http_autoindex_html(ngx_http_request } +static ngx_buf_t * +ngx_http_autoindex_json(ngx_http_request_t *r, ngx_array_t *entries, + ngx_str_t *callback) +{ + size_t len; + ngx_buf_t *b; + ngx_uint_t i; + ngx_http_autoindex_entry_t *entry; + + len = sizeof("[" CRLF CRLF "]") - 1; + + if (callback) { + len += sizeof("/* callback */" CRLF "();") - 1 + callback->len; + } + + entry = entries->elts; + + for (i = 0; i < entries->nelts; i++) { + entry[i].escape = ngx_escape_json(NULL, entry[i].name.data, + entry[i].name.len); + + len += sizeof("{ }," CRLF) - 1 + + sizeof("\"name\":\"\"") - 1 + + entry[i].name.len + entry[i].escape + + sizeof(", \"type\":\"directory\"") - 1 + + sizeof(", \"mtime\":\"Wed, 31 Dec 1986 10:00:00 GMT\"") - 1; + + if (entry[i].file) { + len += sizeof(", \"size\":") - 1 + NGX_OFF_T_LEN; + } + } + + b = ngx_create_temp_buf(r->pool, len); + if (b == NULL) { + return NULL; + } + + if (callback) { + b->last = ngx_cpymem(b->last, "/* callback */" CRLF, + sizeof("/* callback */" CRLF) - 1); + + b->last = ngx_cpymem(b->last, callback->data, callback->len); + + *b->last++ = '('; + } + + *b->last++ = '['; + + for (i = 0; i < entries->nelts; i++) { + b->last = ngx_cpymem(b->last, CRLF "{ \"name\":\"", + sizeof(CRLF "{ \"name\":\"") - 1); + + if (entry[i].escape) { + b->last = (u_char *) ngx_escape_json(b->last, entry[i].name.data, + entry[i].name.len); + } else { + b->last = ngx_cpymem(b->last, entry[i].name.data, + entry[i].name.len); + } + + b->last = ngx_cpymem(b->last, "\", \"type\":\"", + sizeof("\", \"type\":\"") - 1); + From vbart at nginx.com Fri Dec 12 17:26:58 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 12 Dec 2014 17:26:58 +0000 Subject: [nginx] Autoindex: implemented XML output format. Message-ID: details: http://hg.nginx.org/nginx/rev/99751fe3bc3b branches: changeset: 5945:99751fe3bc3b user: Valentin Bartenev date: Fri Dec 12 20:25:42 2014 +0300 description: Autoindex: implemented XML output format. diffstat: src/http/modules/ngx_http_autoindex_module.c | 105 +++++++++++++++++++++++++++ 1 files changed, 105 insertions(+), 0 deletions(-) diffs (150 lines): diff -r 33c08d7e2915 -r 99751fe3bc3b src/http/modules/ngx_http_autoindex_module.c --- a/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:35 2014 +0300 +++ b/src/http/modules/ngx_http_autoindex_module.c Fri Dec 12 20:25:42 2014 +0300 @@ -48,6 +48,7 @@ typedef struct { #define NGX_HTTP_AUTOINDEX_HTML 0 #define NGX_HTTP_AUTOINDEX_JSON 1 #define NGX_HTTP_AUTOINDEX_JSONP 2 +#define NGX_HTTP_AUTOINDEX_XML 3 #define NGX_HTTP_AUTOINDEX_PREALLOCATE 50 @@ -60,6 +61,8 @@ static ngx_buf_t *ngx_http_autoindex_jso ngx_array_t *entries, ngx_str_t *callback); static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, ngx_str_t *callback); +static ngx_buf_t *ngx_http_autoindex_xml(ngx_http_request_t *r, + ngx_array_t *entries); static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two); @@ -76,6 +79,7 @@ static ngx_conf_enum_t ngx_http_autoind { ngx_string("html"), NGX_HTTP_AUTOINDEX_HTML }, { ngx_string("json"), NGX_HTTP_AUTOINDEX_JSON }, { ngx_string("jsonp"), NGX_HTTP_AUTOINDEX_JSONP }, + { ngx_string("xml"), NGX_HTTP_AUTOINDEX_XML }, { ngx_null_string, 0 } }; @@ -259,6 +263,11 @@ ngx_http_autoindex_handler(ngx_http_requ ngx_str_set(&r->headers_out.content_type, "application/javascript"); break; + case NGX_HTTP_AUTOINDEX_XML: + ngx_str_set(&r->headers_out.content_type, "text/xml"); + ngx_str_set(&r->headers_out.charset, "utf-8"); + break; + default: /* NGX_HTTP_AUTOINDEX_HTML */ ngx_str_set(&r->headers_out.content_type, "text/html"); break; @@ -388,6 +397,10 @@ ngx_http_autoindex_handler(ngx_http_requ b = ngx_http_autoindex_json(r, &entries, &callback); break; + case NGX_HTTP_AUTOINDEX_XML: + b = ngx_http_autoindex_xml(r, &entries); + break; + default: /* NGX_HTTP_AUTOINDEX_HTML */ b = ngx_http_autoindex_html(r, &entries); break; @@ -821,6 +834,98 @@ ngx_http_autoindex_jsonp_callback(ngx_ht } +static ngx_buf_t * +ngx_http_autoindex_xml(ngx_http_request_t *r, ngx_array_t *entries) +{ + size_t len; + ngx_tm_t tm; + ngx_buf_t *b; + ngx_str_t type; + ngx_uint_t i; + ngx_http_autoindex_entry_t *entry; + + static u_char head[] = "" CRLF "" CRLF; + static u_char tail[] = "" CRLF; + + len = sizeof(head) - 1 + sizeof(tail) - 1; + + entry = entries->elts; + + for (i = 0; i < entries->nelts; i++) { + entry[i].escape = ngx_escape_html(NULL, entry[i].name.data, + entry[i].name.len); + + len += sizeof("" CRLF) - 1 + + entry[i].name.len + entry[i].escape + + sizeof(" mtime=\"1986-12-31T10:00:00Z\"") - 1; + + if (entry[i].file) { + len += sizeof(" size=\"\"") - 1 + NGX_OFF_T_LEN; + } + } + + b = ngx_create_temp_buf(r->pool, len); + if (b == NULL) { + return NULL; + } + + b->last = ngx_cpymem(b->last, head, sizeof(head) - 1); + + for (i = 0; i < entries->nelts; i++) { + *b->last++ = '<'; + + if (entry[i].dir) { + ngx_str_set(&type, "directory"); + + } else if (entry[i].file) { + ngx_str_set(&type, "file"); + + } else { + ngx_str_set(&type, "other"); + } + + b->last = ngx_cpymem(b->last, type.data, type.len); + + b->last = ngx_cpymem(b->last, " mtime=\"", sizeof(" mtime=\"") - 1); + + ngx_gmtime(entry[i].mtime, &tm); + + b->last = ngx_sprintf(b->last, "%4d-%02d-%02dT%02d:%02d:%02dZ", + tm.ngx_tm_year, tm.ngx_tm_mon, + tm.ngx_tm_mday, tm.ngx_tm_hour, + tm.ngx_tm_min, tm.ngx_tm_sec); + + if (entry[i].file) { + b->last = ngx_cpymem(b->last, "\" size=\"", + sizeof("\" size=\"") - 1); + b->last = ngx_sprintf(b->last, "%O", entry[i].size); + } + + *b->last++ = '"'; *b->last++ = '>'; + + if (entry[i].escape) { + b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, + entry[i].name.len); + } else { + b->last = ngx_cpymem(b->last, entry[i].name.data, + entry[i].name.len); + } + + *b->last++ = '<'; *b->last++ = '/'; + + b->last = ngx_cpymem(b->last, type.data, type.len); + + *b->last++ = '>'; + + *b->last++ = CR; *b->last++ = LF; + } + + b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); + + return b; +} + + static int ngx_libc_cdecl ngx_http_autoindex_cmp_entries(const void *one, const void *two) { From dani at telecom.pt Tue Dec 16 14:21:59 2014 From: dani at telecom.pt (Dani Bento) Date: Tue, 16 Dec 2014 14:21:59 +0000 Subject: nginx + DSCP (Differentied services) Message-ID: <20141216142159.3201aa59@alma> Hello, We are using nginx-1.6 in a production environment for caching data from multiple remote origins. To improve our data distribution over the network we thought that using IP DiffServ/ToS to traffic shape by backend would be useful. We developed a small patch for the nginx core to mark packets. Because the nginx workers don't seem to have CAP_NET_ADMIN privileges we are using the TOS field instead of socket marks. This patch only marks client packets and not upstream/backend packets. Besides that, we added an X-Accel-ClassID header so that the upstream/backend itself can choose the class id to use. Do you find this an interesting feature to add to the nginx core? How can we proceed and submit a patch? Thanks, Dani -- Dani Bento Dire??o de Internet e Tecnologia DTS/DVS tlm: +351 91 429 72 81 dani at telecom.pt From mdounin at mdounin.ru Tue Dec 16 15:46:36 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Dec 2014 18:46:36 +0300 Subject: nginx + DSCP (Differentied services) In-Reply-To: <20141216142159.3201aa59@alma> References: <20141216142159.3201aa59@alma> Message-ID: <20141216154636.GL45960@mdounin.ru> Hello! On Tue, Dec 16, 2014 at 02:21:59PM +0000, Dani Bento wrote: > Hello, > > We are using nginx-1.6 in a production environment for caching data > from multiple remote origins. > > To improve our data distribution over the network we thought that using > IP DiffServ/ToS to traffic shape by backend would be useful. > > We developed a small patch for the nginx core to mark packets. Because > the nginx workers don't seem to have CAP_NET_ADMIN privileges we are > using the TOS field instead of socket marks. This patch only marks > client packets and not upstream/backend packets. I had a module to set IP ToS for serveral years now, see here: http://mdounin.ru/hg/ngx_http_ip_tos_filter_module/ It doesn't seem to be used much though, and hence we don't import it (or an equivalent code) into nginx, at least yet. > Besides that, we added an X-Accel-ClassID header so that the > upstream/backend itself can choose the class id to use. This doesn't looks like a good solution for me. If you want allow backends to control ToS set, it may be a better idea to support variables in the directive in question. > Do you find this an interesting feature to add to the nginx core? How > can we proceed and submit a patch? See above. Just in case, some general guidelines on submitting patches can be found here: http://nginx.org/en/docs/contributing_changes.html -- Maxim Dounin http://nginx.org/ From dani at telecom.pt Tue Dec 16 17:24:42 2014 From: dani at telecom.pt (Dani Bento) Date: Tue, 16 Dec 2014 17:24:42 +0000 Subject: nginx + DSCP (Differentied services) In-Reply-To: <20141216154636.GL45960@mdounin.ru> References: <20141216142159.3201aa59@alma> <20141216154636.GL45960@mdounin.ru> Message-ID: <20141216172442.3ba2d9d8@alma> Thanks for the reply. We looked at your module and found it interesting that you avoided to change the core. Our code marks each buffer flush individually. We can control the ToS for each request even when using keep-alive (using the X-Accel-ClassID header). After the response has been sent the ToS is reset back to the default (location configuration). In your module you mark only at the beginning of the response (at the header filter stage). Don't you have problems with different requests using the same connection? You can only have one ToS mark for each location if you relying on a static configuration. Can it be set by variable "tos $class_id" ? It may be interesting to merge our patch with your module... Dani On Tue, 16 Dec 2014 15:46:36 +0000 Maxim Dounin wrote: > Hello! > > On Tue, Dec 16, 2014 at 02:21:59PM +0000, Dani Bento wrote: > > > Hello, > > > > We are using nginx-1.6 in a production environment for caching data > > from multiple remote origins. > > > > To improve our data distribution over the network we thought that > > using IP DiffServ/ToS to traffic shape by backend would be useful. > > > > We developed a small patch for the nginx core to mark packets. > > Because the nginx workers don't seem to have CAP_NET_ADMIN > > privileges we are using the TOS field instead of socket marks. This > > patch only marks client packets and not upstream/backend packets. > > I had a module to set IP ToS for serveral years now, see here: > > http://mdounin.ru/hg/ngx_http_ip_tos_filter_module/ > > It doesn't seem to be used much though, and hence we don't import > it (or an equivalent code) into nginx, at least yet. > > > Besides that, we added an X-Accel-ClassID header so that the > > upstream/backend itself can choose the class id to use. > > This doesn't looks like a good solution for me. If you want > allow backends to control ToS set, it may be a better idea to > support variables in the directive in question. > > > Do you find this an interesting feature to add to the nginx core? > > How can we proceed and submit a patch? > > See above. Just in case, some general guidelines on submitting > patches can be found here: > > http://nginx.org/en/docs/contributing_changes.html > -- Dani Bento Dire??o de Internet e Tecnologia DTS/DVS tlm: +351 91 429 72 81 dani at telecom.pt From mdounin at mdounin.ru Tue Dec 16 18:48:28 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 16 Dec 2014 21:48:28 +0300 Subject: nginx + DSCP (Differentied services) In-Reply-To: <20141216172442.3ba2d9d8@alma> References: <20141216142159.3201aa59@alma> <20141216154636.GL45960@mdounin.ru> <20141216172442.3ba2d9d8@alma> Message-ID: <20141216184828.GO45960@mdounin.ru> Hello! On Tue, Dec 16, 2014 at 05:24:42PM +0000, Dani Bento wrote: > Thanks for the reply. > > We looked at your module and found it interesting that you > avoided to change the core. > > Our code marks each buffer flush individually. We can control the ToS > for each request even when using keep-alive (using the X-Accel-ClassID > header). After the response has been sent the ToS is reset back to the > default (location configuration). > > In your module you mark only at the beginning of the response (at the > header filter stage). Don't you have problems with different > requests using the same connection? If you want ToS to be reset, you can use "ip_tos 0x00;" by default, see example here: http://mdounin.ru/hg/ngx_http_ip_tos_filter_module/file/tip/README > You can only have one ToS mark for > each location if you relying on a static configuration. Can it be > set by variable "tos $class_id" ? Not now, but this can be added if needed - like it was recently added to the "expires" directive, see http://hg.nginx.org/nginx/rev/4983f7d18fe3. -- Maxim Dounin http://nginx.org/ From piotr at cloudflare.com Wed Dec 17 01:21:52 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Tue, 16 Dec 2014 17:21:52 -0800 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: <20141204181150.GE62402@mdounin.ru> References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> Message-ID: Hey Maxim, > I don't really understand the logic you suggest. > > Previous behaviour is as follows: > > - We don't check if the response is cacheable or not, but rather > rely on the fact that it's already in the cache (hence it, at > least was, cacheable). > > This kind of agree with what nginx normally does for cache items - > cacheability is determined when we are placing a response into the > cache, and not changed after this even if settings are changed. Which is strange, because the 304 response is used to signal validity and cacheability of the original (cached) response, so ignoring that feels wrong. Also, right now, validity, but not cacheability of the 304 response takes priority over cached response, which means that in most cases, the decision is based partially on the 304 and partially on the cached response. One of the reasons for this change is to avoid requests with Authorization header and/or responses with Set-Cookie header revalidating cached responses for anonymous users. Another, more technical reason, is that this is the only place in the code where r->cache->valid_sec isn't guarded by u->cacheable, which is protection assumed by rest of the code that doesn't clear this value on errors, just sets u->cacheable to 0, so ignoring it can result in odd validity values that wouldn't be applied originally on cache miss. > With the suggested change, you do the following: > > - If the 304 response is cacheable and there is a validity known in > advance (from Expires, Cache-Control or X-Accel-Expires), the > response will be cached. > > - If the 304 response is cacheable and the cached response is > cacheable according to current settings, the response will be > cached. Correct, so the only difference between existing and proposed behavior is that in case 304 response (which, according to RFC7232, must include all cache-controlling headers, other than the specific to nginx X-Accel-Expires) isn't cacheable, nginx won't update the validity of the cached item. I don't see anything wrong with this logic. > This doesn't look consistent. In particular, > > - If the cached response is not cacheable according to current > settings, it's still can be cached if the 304 response can be > cached and have a validity explicitly set. > > Doesn't look like a good change to me. I don't see how this is different from the current behavior, which is less strict than the proposed one. Maybe look at the diff ignoring white spaces? This patch just adds requirement for 304 to be cacheable, that's it. >> + time_t now; > > Please do not put declarations inside blocks, with the exception > of dedicated conditionally compiled blocks. I only wrote it like that to be consistent with rest of the code, where "now" and/or "valid" are defined inside u->cacheable conditional blocks. See: ngx_http_upstream.c lines 2553 and 3763. Best regards, Piotr Sikora From piotr at cloudflare.com Wed Dec 17 01:31:25 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Tue, 16 Dec 2014 17:31:25 -0800 Subject: [PATCH 2 of 2] Cache: test proxy_no_cache predicates before updating cache In-Reply-To: <20141204181349.GF62402@mdounin.ru> References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181349.GF62402@mdounin.ru> Message-ID: Hey Maxim, > Again, not sure it's a good change. In particular, suggested code > checks proxy_no_cache against a 304 response, not against a > response which will be cached (or, rather, already cached), and > this looks very questionable. Rather, it checks whether it can extend the validity of the cached response based on the 304 response, which is used exactly for that purpose. While I agree that this isn't perfect, because 304 response doesn't contain all headers that proxy_no_cache might want to check, I think it's much better than totally ignoring that directive, which is the case now... At the very least, it checks client headers, which are perfect candidates for proxy_bypass and proxy_no_cache. Would checking proxy_no_cache against both 304 and cached response work for you or are you totally against this idea? Best regards, Piotr Sikora From dani at telecom.pt Wed Dec 17 11:27:29 2014 From: dani at telecom.pt (Dani Bento) Date: Wed, 17 Dec 2014 11:27:29 +0000 Subject: nginx + DSCP (Differentied services) In-Reply-To: <20141216184828.GO45960@mdounin.ru> References: <20141216142159.3201aa59@alma> <20141216154636.GL45960@mdounin.ru> <20141216172442.3ba2d9d8@alma> <20141216184828.GO45960@mdounin.ru> Message-ID: <20141217112729.55ca175c@alma> Hello, In attachment is our patch to the nginx core. You can take a look. We found that your module isn't IPv6 compatible too, but it may be simple to implement that. Thanks. On Tue, 16 Dec 2014 18:48:28 +0000 Maxim Dounin wrote: > Hello! > > On Tue, Dec 16, 2014 at 05:24:42PM +0000, Dani Bento wrote: > > > Thanks for the reply. > > > > We looked at your module and found it interesting that you > > avoided to change the core. > > > > Our code marks each buffer flush individually. We can control the > > ToS for each request even when using keep-alive (using the > > X-Accel-ClassID header). After the response has been sent the ToS > > is reset back to the default (location configuration). > > > > In your module you mark only at the beginning of the response (at > > the header filter stage). Don't you have problems with different > > requests using the same connection? > > If you want ToS to be reset, you can use "ip_tos 0x00;" by > default, see example here: > > http://mdounin.ru/hg/ngx_http_ip_tos_filter_module/file/tip/README > > > You can only have one ToS mark for > > each location if you relying on a static configuration. Can it be > > set by variable "tos $class_id" ? > > Not now, but this can be added if needed - like it was recently > added to the "expires" directive, see > http://hg.nginx.org/nginx/rev/4983f7d18fe3. > -- Dani Bento Dire??o de Internet e Tecnologia DTS/DVS tlm: +351 91 429 72 81 dani at telecom.pt -------------- next part -------------- A non-text attachment was scrubbed... Name: ngx-traffic-xaccel-classid-1.6.2.patch Type: text/x-patch Size: 26222 bytes Desc: ngx-traffic-xaccel-classid-1.6.2.patch URL: From luky-37 at hotmail.com Wed Dec 17 14:20:37 2014 From: luky-37 at hotmail.com (Lukas Tribus) Date: Wed, 17 Dec 2014 15:20:37 +0100 Subject: SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS Message-ID: # HG changeset patch # User Lukas Tribus # Date 1418825570 -3600 # Wed Dec 17 15:12:50 2014 +0100 # Node ID 923f5d7061b6df59fb1d28c70379da8b9daf1c8c # Parent a23c35496c2fc0ba9a34d968c2ca6d1f9374f8a8 SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS OpenSSL or its forks may remove this flag (BoringSSL did), as the renegotiation issue was fixed in OpenSSL. diff -r a23c35496c2f -r 923f5d7061b6 src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c Mon Mar 24 17:55:10 2014 +0400 +++ b/src/event/ngx_event_openssl.c Wed Dec 17 15:12:50 2014 +0100 @@ -851,9 +851,11 @@ c->send_chain = ngx_ssl_send_chain; /* initial handshake done, disable renegotiation (CVE-2009-3555) */ +#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS if (c->ssl->connection->s3) { c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } +#endif return NGX_OK; } From piotr at cloudflare.com Wed Dec 17 23:01:28 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 17 Dec 2014 15:01:28 -0800 Subject: SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS In-Reply-To: References: Message-ID: Hey Lukas, > /* initial handshake done, disable renegotiation (CVE-2009-3555) */ > +#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS > if (c->ssl->connection->s3) { > c->ssl->connection->s3->flags |= > SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; > } > +#endif #ifdef should be above the comment. I also think that this change needs a bit more work, since renegotiation changes are all over the place in nginx. I've started looking into this earlier this month, but got busy with other stuff. Best regards, Piotr Sikora From piotr at cloudflare.com Thu Dec 18 02:48:37 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Wed, 17 Dec 2014 18:48:37 -0800 Subject: [PATCH] Add strict Host validation Message-ID: # HG changeset patch # User Piotr Sikora # Date 1418870862 28800 # Wed Dec 17 18:47:42 2014 -0800 # Node ID ab0442e232ce098438943a77422d8a04cc5b6790 # Parent 99751fe3bc3b285801b434f7f707d87fa42b093e Add strict Host validation. According to RFC3986, Host is a sequence of printable ASCII characters, with the exception of: space, ", #, /, <, >, ?, @, \, ^, `, {, | and }. Signed-off-by: Piotr Sikora diff -r 99751fe3bc3b -r ab0442e232ce src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c Fri Dec 12 20:25:42 2014 +0300 +++ b/src/http/ngx_http_request.c Wed Dec 17 18:47:42 2014 -0800 @@ -1955,12 +1955,25 @@ ngx_http_validate_host(ngx_str_t *host, } break; - case '\0': + case ' ': + case '"': + case '#': + case '/': + case '<': + case '>': + case '?': + case '@': + case '\\': + case '^': + case '`': + case '{': + case '|': + case '}': return NGX_DECLINED; default: - if (ngx_path_separator(ch)) { + if (ch < 0x20 || ch > 0x7e) { return NGX_DECLINED; } From wangxiaochen0 at gmail.com Thu Dec 18 04:05:01 2014 From: wangxiaochen0 at gmail.com (Xiaochen Wang) Date: Thu, 18 Dec 2014 12:05:01 +0800 Subject: Core: added signal name to "signal process started" logging Message-ID: <20141218040501.GB16247@gmail.com> It is useful to know which signal was sent to nginx master when we analyzed error.log. If error_log level is warn/error/crit/alert/emerg, we could not know this information from nginx master/worker error log. The error log with this patch is changed as following: 2014/12/18 11:47:42 [notice] 17320#0: signal process started (reopen) 2014/12/18 11:47:44 [notice] 17346#0: signal process started (reload) # HG changeset patch # User Xiaochen Wang # Date 1418872566 -28800 # Node ID 179a8ce4f68f96c316e4daec3fa677cd7d4e0126 # Parent 99751fe3bc3b285801b434f7f707d87fa42b093e Core: added signal name to "signal process started" logging diff -r 99751fe3bc3b -r 179a8ce4f68f src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c Fri Dec 12 20:25:42 2014 +0300 +++ b/src/core/ngx_cycle.c Thu Dec 18 11:16:06 2014 +0800 @@ -969,7 +969,8 @@ ngx_signal_process(ngx_cycle_t *cycle, c ngx_core_conf_t *ccf; u_char buf[NGX_INT64_LEN + 2]; - ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "signal process started"); + ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, + "signal process started (%s)", sig); ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); From luky-37 at hotmail.com Thu Dec 18 08:34:43 2014 From: luky-37 at hotmail.com (Lukas Tribus) Date: Thu, 18 Dec 2014 09:34:43 +0100 Subject: SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS In-Reply-To: References: , Message-ID: Hi Piotr, > Hey Lukas, > >> /* initial handshake done, disable renegotiation (CVE-2009-3555) */ >> +#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS >> if (c->ssl->connection->s3) { >> c->ssl->connection->s3->flags |= >> SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; >> } >> +#endif > > #ifdef should be above the comment. > > I also think that this change needs a bit more work, since > renegotiation changes are all over the place in nginx. I've started > looking into this earlier this month, but got busy with other stuff. Ok, I will leave it to you then. This was just a fast fix to allow the build with boringssl again, but if more work is required then I better let you handle it, as I'm not not familiar with the code. Thanks, Lukas From kindy61 at gmail.com Thu Dec 18 15:23:51 2014 From: kindy61 at gmail.com (Kindy Lin) Date: Thu, 18 Dec 2014 23:23:51 +0800 Subject: Directive "map" not working with regex key and value that like "$1" Message-ID: <1C929111-0744-44F7-A81B-09B347C86E9F@gmail.com> Hi, I have some configuration like: map $host $sub { default www; ~^(\w+)\.abc\.com$ $1; } And it not works. I first find it in 1.1.19 and seems the latest version still have this issue. Thanks. From mdounin at mdounin.ru Thu Dec 18 16:07:58 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Dec 2014 19:07:58 +0300 Subject: SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS In-Reply-To: References: Message-ID: <20141218160758.GF79300@mdounin.ru> Hello! On Wed, Dec 17, 2014 at 03:01:28PM -0800, Piotr Sikora wrote: > Hey Lukas, > > > /* initial handshake done, disable renegotiation (CVE-2009-3555) */ > > +#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS > > if (c->ssl->connection->s3) { > > c->ssl->connection->s3->flags |= > > SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; > > } > > +#endif > > #ifdef should be above the comment. > > I also think that this change needs a bit more work, since > renegotiation changes are all over the place in nginx. I've started > looking into this earlier this month, but got busy with other stuff. There isn't that many renegotiation changes: nginx disables renegotiation, nothing more. Unfortunately, even after a number of renegotiation-related vulnerabilities OpenSSL (and derivatives) doesn't provide an easy way to do this. So we do the following: 1. Detect a renegotiation via info callback, and drop the connection later if it was detected. 2. After a handshake, we the SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag is set to disable renegotiation within OpenSSL. Initial commit is at http://hg.nginx.org/nginx/rev/5a08dfb8d763 (and some more details can be found in Russian mailing list, http://nginx.org/pipermail/nginx-ru/2009-November/029439.html). As far as I can see, BoringSSL removed SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS without introducing any replacement. That's a bit sad as this opens a door for various attacks, but probably we can live with it, at least when compiled with BoringSSL. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 18 16:11:55 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Dec 2014 19:11:55 +0300 Subject: Directive "map" not working with regex key and value that like "$1" In-Reply-To: <1C929111-0744-44F7-A81B-09B347C86E9F@gmail.com> References: <1C929111-0744-44F7-A81B-09B347C86E9F@gmail.com> Message-ID: <20141218161155.GG79300@mdounin.ru> Hello! On Thu, Dec 18, 2014 at 11:23:51PM +0800, Kindy Lin wrote: > Hi, > > I have some configuration like: > > map $host $sub { > default www; > ~^(\w+)\.abc\.com$ $1; > } > > And it not works. > I first find it in 1.1.19 and seems the latest version still have this issue. This doesn't looks like a development-related question. Please use nginx@ mailing list for such questions. Thank you. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 18 17:09:44 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Dec 2014 17:09:44 +0000 Subject: [nginx] SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS. Message-ID: details: http://hg.nginx.org/nginx/rev/ee941e49bd88 branches: changeset: 5946:ee941e49bd88 user: Lukas Tribus date: Wed Dec 17 15:12:50 2014 +0100 description: SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS. The flag was recently removed by BoringSSL. diffstat: src/event/ngx_event_openssl.c | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diffs (19 lines): diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1146,11 +1146,15 @@ ngx_ssl_handshake(ngx_connection_t *c) c->recv_chain = ngx_ssl_recv_chain; c->send_chain = ngx_ssl_send_chain; +#ifdef SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS + /* initial handshake done, disable renegotiation (CVE-2009-3555) */ if (c->ssl->connection->s3) { c->ssl->connection->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; } +#endif + return NGX_OK; } From mdounin at mdounin.ru Thu Dec 18 17:10:17 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Dec 2014 20:10:17 +0300 Subject: SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS In-Reply-To: References: Message-ID: <20141218171016.GI79300@mdounin.ru> Hello! On Wed, Dec 17, 2014 at 03:20:37PM +0100, Lukas Tribus wrote: > # HG changeset patch > # User Lukas Tribus > # Date 1418825570 -3600 > # Wed Dec 17 15:12:50 2014 +0100 > # Node ID 923f5d7061b6df59fb1d28c70379da8b9daf1c8c > # Parent a23c35496c2fc0ba9a34d968c2ca6d1f9374f8a8 > SSL: safeguard use of SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS > > OpenSSL or its forks may remove this flag (BoringSSL did), as the > renegotiation issue was fixed in OpenSSL. I've committed the patch with some minor changes, thanks. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Thu Dec 18 19:29:46 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Thu, 18 Dec 2014 22:29:46 +0300 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> Message-ID: <20141218192946.GJ79300@mdounin.ru> Hello! On Tue, Dec 16, 2014 at 05:21:52PM -0800, Piotr Sikora wrote: > Hey Maxim, > > > I don't really understand the logic you suggest. > > > > Previous behaviour is as follows: > > > > - We don't check if the response is cacheable or not, but rather > > rely on the fact that it's already in the cache (hence it, at > > least was, cacheable). > > > > This kind of agree with what nginx normally does for cache items - > > cacheability is determined when we are placing a response into the > > cache, and not changed after this even if settings are changed. > > Which is strange, because the 304 response is used to signal validity > and cacheability of the original (cached) response, so ignoring that > feels wrong. The cacheability of the response was already signalled previously. And a 304 response can't really change it. Consider, for example, that there were no validation request at all - and it happens some time later. So the only thing that really changes is validity. > Also, right now, validity, but not cacheability of the 304 response > takes priority over cached response, which means that in most cases, > the decision is based partially on the 304 and partially on the cached > response. That's in line with the RFC2616: it allows 304 to supply new Cache-Control and Expires headers if they are different from what was previously sent. So we use validity from the 304 response, then from the cached response, then from proxy_cache_valid. What is probably missing here is not using valid_sec if u->cacheable is set. > One of the reasons for this change is to avoid requests with > Authorization header and/or responses with Set-Cookie header > revalidating cached responses for anonymous users. > > Another, more technical reason, is that this is the only place in the > code where r->cache->valid_sec isn't guarded by u->cacheable, which is > protection assumed by rest of the code that doesn't clear this value > on errors, just sets u->cacheable to 0, so ignoring it can result in > odd validity values that wouldn't be applied originally on cache miss. I agree, see above. > > With the suggested change, you do the following: > > > > - If the 304 response is cacheable and there is a validity known in > > advance (from Expires, Cache-Control or X-Accel-Expires), the > > response will be cached. > > > > - If the 304 response is cacheable and the cached response is > > cacheable according to current settings, the response will be > > cached. > > Correct, so the only difference between existing and proposed behavior > is that in case 304 response (which, according to RFC7232, must > include all cache-controlling headers, other than the specific to > nginx X-Accel-Expires) isn't cacheable, nginx won't update the > validity of the cached item. I don't see anything wrong with this > logic. > > > This doesn't look consistent. In particular, > > > > - If the cached response is not cacheable according to current > > settings, it's still can be cached if the 304 response can be > > cached and have a validity explicitly set. > > > > Doesn't look like a good change to me. > > I don't see how this is different from the current behavior, which is > less strict than the proposed one. > > Maybe look at the diff ignoring white spaces? This patch just adds > requirement for 304 to be cacheable, that's it. The problem is consistency of the behaviour in equivalent cases. E.g., consider the following: - A response with Set-Cookie cached with "proxy_ignore_headers Set-Cookie" in the configuration. The response contains "Cache-Control: max-age=100". - Now proxy_ignore_headers is removed from the configuration. We do a request with If-Modified-Since, 304 is returned: (a) If the 304 contains "Cache-Control: max-age=100", the response will be cached for 100 more seconds. (b) If the 304 does not contain "Cache-Control: max-age=100", the response won't be updated. On the other hand, (a) and (b) are equivalent per RFC2616. > >> + time_t now; > > > > Please do not put declarations inside blocks, with the exception > > of dedicated conditionally compiled blocks. > > I only wrote it like that to be consistent with rest of the code, > where "now" and/or "valid" are defined inside u->cacheable conditional > blocks. See: ngx_http_upstream.c lines 2553 and 3763. Understood, but please don't. These two cases are more or less dedicated conditionally compiled blocks (the only if() in the conditionally complied code in 2553, the inner and the only block with local variables in 3763). Adding more than one place with local variables inside an #if is certainly a bad idea. -- Maxim Dounin http://nginx.org/ From kindy61 at gmail.com Thu Dec 18 23:23:14 2014 From: kindy61 at gmail.com (Kindy Lin) Date: Fri, 19 Dec 2014 07:23:14 +0800 Subject: Directive "map" not working with regex key and value that like "$1" In-Reply-To: <20141218161155.GG79300@mdounin.ru> References: <1C929111-0744-44F7-A81B-09B347C86E9F@gmail.com> <20141218161155.GG79300@mdounin.ru> Message-ID: <77413CDD-2A43-40D5-8C2D-2F0A09C63711@gmail.com> Yep, it's a bug but not a question. Thanks. > On 2014?12?19?, at 00:11, Maxim Dounin wrote: > > Hello! > >> On Thu, Dec 18, 2014 at 11:23:51PM +0800, Kindy Lin wrote: >> >> Hi, >> >> I have some configuration like: >> >> map $host $sub { >> default www; >> ~^(\w+)\.abc\.com$ $1; >> } >> >> And it not works. >> I first find it in 1.1.19 and seems the latest version still have this issue. > > This doesn't looks like a development-related question. Please > use nginx@ mailing list for such questions. Thank you. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From toshikuni-fukaya at cybozu.co.jp Fri Dec 19 06:52:55 2014 From: toshikuni-fukaya at cybozu.co.jp (Toshikuni Fukaya) Date: Fri, 19 Dec 2014 15:52:55 +0900 Subject: Questions for X-Accel-Redirect Message-ID: <5493CB47.7060708@cybozu.co.jp> Hi, I have some questions for X-Accel-Redirect. Background: I use X-Accel-Redirect to send blob data from a second server (:8001 in below). I want to send headers from not only the second but also the first (:8000). Current nginx implementation, however, sends only headers from the second except some headers from the first, such as Content-Type. Question 1: Can I change this behavior to send headers from the first server together with ones from the second to a client? Question 2: If Q1 is acceptable, I hope to hide some headers by proxy_hide_header directive. Is this design ok for you? ### here is my example conf. ### server { listen 80 default_server; location / { proxy_pass http://localhost:8000/; } location /reproxy/ { proxy_pass http://localhost:8001/; } } server { listen 8000; location / { add_header x-accel-redirect /reproxy/; add_header foo 1; return 200; } } server { listen 8001; location / { add_header bar 1; return 200; } } Thanks, Toshikuni Fukaya From mdounin at mdounin.ru Fri Dec 19 11:59:52 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Dec 2014 14:59:52 +0300 Subject: Directive "map" not working with regex key and value that like "$1" In-Reply-To: <77413CDD-2A43-40D5-8C2D-2F0A09C63711@gmail.com> References: <1C929111-0744-44F7-A81B-09B347C86E9F@gmail.com> <20141218161155.GG79300@mdounin.ru> <77413CDD-2A43-40D5-8C2D-2F0A09C63711@gmail.com> Message-ID: <20141219115952.GO79300@mdounin.ru> Hello! On Fri, Dec 19, 2014 at 07:23:14AM +0800, Kindy Lin wrote: > Yep, it's a bug but not a question. Even if you think it's a bug (I don't, rather a feature request), it's still doesn't belong to the development list unless you are providing a patch or asking where to start hacking. Thank you. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Fri Dec 19 12:10:19 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Dec 2014 15:10:19 +0300 Subject: Questions for X-Accel-Redirect In-Reply-To: <5493CB47.7060708@cybozu.co.jp> References: <5493CB47.7060708@cybozu.co.jp> Message-ID: <20141219121019.GP79300@mdounin.ru> Hello! On Fri, Dec 19, 2014 at 03:52:55PM +0900, Toshikuni Fukaya wrote: > Hi, > > I have some questions for X-Accel-Redirect. > > Background: I use X-Accel-Redirect to send blob data from a second > server (:8001 in below). I want to send headers from not only the second > but also the first (:8000). > Current nginx implementation, however, sends only headers from the > second except some headers from the first, such as Content-Type. > > Question 1: > Can I change this behavior to send headers from the first server > together with ones from the second to a client? You can save headers from the first server response from $upstream_http_* variables and then use add_header to add them to the final response: location / { proxy_pass http://upstream1; } location /second/ { set $x_foo_bar $upstream_http_x_foo_bar; add_header X-Foo-Bar $x_foo_bar; proxy_pass http://upstream2; } I don't really think we need additional functionality here. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Fri Dec 19 16:37:05 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Dec 2014 19:37:05 +0300 Subject: [PATCH] Add strict Host validation In-Reply-To: References: Message-ID: <20141219163705.GU79300@mdounin.ru> Hello! On Wed, Dec 17, 2014 at 06:48:37PM -0800, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1418870862 28800 > # Wed Dec 17 18:47:42 2014 -0800 > # Node ID ab0442e232ce098438943a77422d8a04cc5b6790 > # Parent 99751fe3bc3b285801b434f7f707d87fa42b093e > Add strict Host validation. > > According to RFC3986, Host is a sequence of printable ASCII characters, > with the exception of: space, ", #, /, <, >, ?, @, \, ^, `, {, | and }. > > Signed-off-by: Piotr Sikora > > diff -r 99751fe3bc3b -r ab0442e232ce src/http/ngx_http_request.c > --- a/src/http/ngx_http_request.c Fri Dec 12 20:25:42 2014 +0300 > +++ b/src/http/ngx_http_request.c Wed Dec 17 18:47:42 2014 -0800 > @@ -1955,12 +1955,25 @@ ngx_http_validate_host(ngx_str_t *host, > } > break; > > - case '\0': > + case ' ': > + case '"': > + case '#': > + case '/': > + case '<': > + case '>': > + case '?': > + case '@': > + case '\\': > + case '^': > + case '`': > + case '{': > + case '|': > + case '}': > return NGX_DECLINED; > > default: > > - if (ngx_path_separator(ch)) { > + if (ch < 0x20 || ch > 0x7e) { > return NGX_DECLINED; > } I don't think we should further restrict allowed hostnames solely based on what current edition of standard says. We are more or less liberal here, allowing various experiments - and I don't think this should be changed without a good reason. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Fri Dec 19 17:27:28 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Fri, 19 Dec 2014 20:27:28 +0300 Subject: Core: added signal name to "signal process started" logging In-Reply-To: <20141218040501.GB16247@gmail.com> References: <20141218040501.GB16247@gmail.com> Message-ID: <20141219172728.GW79300@mdounin.ru> Hello! On Thu, Dec 18, 2014 at 12:05:01PM +0800, Xiaochen Wang wrote: > It is useful to know which signal was sent to nginx master when we analyzed > error.log. If error_log level is warn/error/crit/alert/emerg, we could not > know this information from nginx master/worker error log. Adding more logging into signal process won't help, as signal process is not the only way to send signals to nginx. The main purpose of signal process is to allow sending signals on Windows, where there is no "kill" to do this. -- Maxim Dounin http://nginx.org/ From piotr at cloudflare.com Fri Dec 19 21:08:52 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Fri, 19 Dec 2014 13:08:52 -0800 Subject: [PATCH] Add strict Host validation In-Reply-To: <20141219163705.GU79300@mdounin.ru> References: <20141219163705.GU79300@mdounin.ru> Message-ID: Hey Maxim, > I don't think we should further restrict allowed hostnames solely > based on what current edition of standard says. We are more or > less liberal here, allowing various experiments - and I don't > think this should be changed without a good reason. While I agree that there is no real reason for forbidding some of those characters, I think that Host still should be restricted to at least printable ASCII characters (minus space and path separators). I can't think of any reason why would you intentionally allow control characters in there. Best regards, Piotr Sikora From amdeich at gmail.com Sat Dec 20 16:59:11 2014 From: amdeich at gmail.com (Andrey Kulikov) Date: Sat, 20 Dec 2014 19:59:11 +0300 Subject: [PATCH] Add strict Host validation In-Reply-To: References: <20141219163705.GU79300@mdounin.ru> Message-ID: On 20 December 2014 at 00:08, Piotr Sikora wrote: > I think that Host still should be restricted to at > least printable ASCII > In what part of ASCII table? What about host names in national alphabets? -------------- next part -------------- An HTML attachment was scrubbed... URL: From luky-37 at hotmail.com Sat Dec 20 18:49:42 2014 From: luky-37 at hotmail.com (Lukas Tribus) Date: Sat, 20 Dec 2014 19:49:42 +0100 Subject: [PATCH] Add strict Host validation In-Reply-To: References: , <20141219163705.GU79300@mdounin.ru>, , Message-ID: > I can't think of any reason why would you intentionally allow > control characters in there. I fully agree. > What about host names in national alphabets? Its not in the standard, to what end exactly would we allow such characters? It will just encourage users to use non-standard hostname which will break in a lot of browser, forward and reverse proxies. IDN is the proper way to do special characters in domain names and it works with the entire Unicode spectrum in a standardized way. I don't see any reason to allow a Hostname that cannot even be published via DNS in the first place. Lukas From piotr at cloudflare.com Sat Dec 20 21:32:33 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Sat, 20 Dec 2014 13:32:33 -0800 Subject: [PATCH] Add strict Host validation In-Reply-To: References: <20141219163705.GU79300@mdounin.ru> Message-ID: Hey Andrey, > In what part of ASCII table? US-ASCII, i.e. printable characters are 0x20-0x7E. > What about host names in national alphabets? They are not transmitted as such, see RFC3492 (Punycode) and RFC5891 (IDNA). Best regards, Piotr Sikora From piotr at cloudflare.com Sun Dec 21 00:05:13 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Sat, 20 Dec 2014 16:05:13 -0800 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: <20141218192946.GJ79300@mdounin.ru> References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> <20141218192946.GJ79300@mdounin.ru> Message-ID: Hey Maxim, > The cacheability of the response was already signalled previously. > And a 304 response can't really change it. Fine, if you want to get technical, then yes, cacheability of the response was signaled previously, however the 304 response can still signal that the validity shouldn't be extended (i.e. that the cache shouldn't be updated), which is what we're really talking about here. > Consider, for example, > that there were no validation request at all - and it happens some > time later. So the only thing that really changes is validity. I don't follow your logic here, what exactly are you trying to say? > That's in line with the RFC2616: it allows 304 to supply new > Cache-Control and Expires headers if they are different from what > was previously sent. So we use validity from the 304 response, > then from the cached response, then from proxy_cache_valid. > > What is probably missing here is not using valid_sec if > u->cacheable is set. > > (...) > > I agree, see above. Which is basically what my patch adds, isn't it? > The problem is consistency of the behaviour in equivalent cases. > > E.g., consider the following: > > - A response with Set-Cookie cached with > "proxy_ignore_headers Set-Cookie" in the configuration. The > response contains "Cache-Control: max-age=100". > > - Now proxy_ignore_headers is removed from the configuration. We > do a request with If-Modified-Since, 304 is returned: > > (a) If the 304 contains "Cache-Control: max-age=100", the > response will be cached for 100 more seconds. > > (b) If the 304 does not contain "Cache-Control: max-age=100", > the response won't be updated. > > On the other hand, (a) and (b) are equivalent per RFC2616. However, according to RFC7232, (a) and (b) are different: The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 (OK) response to the same request: Cache-Control, Content-Location, Date, ETag, Expires, and Vary. Since the goal of a 304 response is to minimize information transfer when the recipient already has one or more cached representations, a sender SHOULD NOT generate representation metadata other than the above listed fields unless said metadata exists for the purpose of guiding cache updates (e.g., Last-Modified might be useful if the response does not have an ETag field). Best regards, Piotr Sikora From piotr at cloudflare.com Sun Dec 21 00:22:57 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Sat, 20 Dec 2014 16:22:57 -0800 Subject: [PATCH] Cache: check if ETag and Vary didn't change before updating header Message-ID: <7e7f823e87fc02c55d46.1419121377@piotrs-macbook-pro.local> # HG changeset patch # User Piotr Sikora # Date 1419121345 28800 # Sat Dec 20 16:22:25 2014 -0800 # Node ID 7e7f823e87fc02c55d46d74a65b336752afe17ee # Parent ee941e49bd8899d2beb3da9ec36acf3b56c5ce9e Cache: check if ETag and Vary didn't change before updating header. Signed-off-by: Piotr Sikora diff -r ee941e49bd88 -r 7e7f823e87fc src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c Wed Dec 17 15:12:50 2014 +0100 +++ b/src/http/ngx_http_file_cache.c Sat Dec 20 16:22:25 2014 -0800 @@ -1362,6 +1362,10 @@ ngx_http_file_cache_update_header(ngx_ht if (h.version != NGX_HTTP_CACHE_VERSION || h.last_modified != c->last_modified + || h.etag_len != c->etag.len + || ngx_memcmp(h.etag, c->etag.data, c->etag.len) != 0 + || h.vary_len != c->vary.len + || ngx_memcmp(h.vary, c->vary.data, c->vary.len) != 0 || h.crc32 != c->crc32 || h.header_start != c->header_start || h.body_start != c->body_start) From kindy61 at gmail.com Sun Dec 21 03:03:24 2014 From: kindy61 at gmail.com (kindy) Date: Sun, 21 Dec 2014 11:03:24 +0800 Subject: [Patch] Re: Directive "map" not working with regex key and value that like "$1" Message-ID: The root cause there are both. var_values & value_hashs. when used with regex key, we should not use var_values, because numbered capture are not registered as nginx variable. so directive like "~(.+) $1;" will add $1 into var_values by mistake, but latter regex will not add this variable.. ---start of patch--- --- nginx-1.1.19-orig/src/http/modules/ngx_http_map_module.c 2012-01-18 23:07:43.000000000 +0800 +++ nginx-1.1.19-fixe/src/http/modules/ngx_http_map_module.c 2014-12-20 10:42:01.000000000 +0800 @@ -403,6 +403,10 @@ return ngx_conf_parse(cf, &file); } +#if (NGX_PCRE) + if (!value[0].len || value[0].data[0] != '~') { +#endif + if (value[1].data[0] == '$') { name = value[1]; name.len--; @@ -442,6 +446,10 @@ goto found; } +#if (NGX_PCRE) + } +#endif + key = 0; for (i = 0; i < value[1].len; i++) { ---end of patch--- On Fri, Dec 19, 2014 at 7:59 PM, Maxim Dounin wrote: > Hello! > > On Fri, Dec 19, 2014 at 07:23:14AM +0800, Kindy Lin wrote: > > > Yep, it's a bug but not a question. > > Even if you think it's a bug (I don't, rather a feature request), > it's still doesn't belong to the development list unless you are > providing a patch or asking where to start hacking. > > Thank you. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -- - - - - - - - - - - - - ??(Kindy Lin) -------------- next part -------------- An HTML attachment was scrubbed... URL: From jhs at mojatatu.com Sun Dec 21 19:40:56 2014 From: jhs at mojatatu.com (Jamal Hadi Salim) Date: Sun, 21 Dec 2014 14:40:56 -0500 Subject: netdev 01 Message-ID: <54972248.60305@mojatatu.com> Sorry for the spam but i wasnt sure who else to contact. I'd like to invite people from nginx community to submit proposals to netdev01. https://www.netdev01.org/participate Tutorials on both developer level and/or user level will be welcome. But also this could be an opportunity to write papers on new ideas or general ideas that have not been documented before on nginx. Sorry for the solicitation again - we want to make the conference not too kernel centric and i have heard good things about nginx. so please submit proposals. please CC me if you want to respond as i am not subscribed. cheers, jamal From toshikuni-fukaya at cybozu.co.jp Mon Dec 22 00:58:43 2014 From: toshikuni-fukaya at cybozu.co.jp (Toshikuni Fukaya) Date: Mon, 22 Dec 2014 09:58:43 +0900 Subject: Questions for X-Accel-Redirect In-Reply-To: <20141219121019.GP79300@mdounin.ru> References: <5493CB47.7060708@cybozu.co.jp> <20141219121019.GP79300@mdounin.ru> Message-ID: <54976CC3.4000503@cybozu.co.jp> Hi, On 2014/12/19 21:10, Maxim Dounin wrote: > Hello! > > On Fri, Dec 19, 2014 at 03:52:55PM +0900, Toshikuni Fukaya wrote: > >> Hi, >> >> I have some questions for X-Accel-Redirect. >> >> Background: I use X-Accel-Redirect to send blob data from a second >> server (:8001 in below). I want to send headers from not only the second >> but also the first (:8000). >> Current nginx implementation, however, sends only headers from the >> second except some headers from the first, such as Content-Type. >> >> Question 1: >> Can I change this behavior to send headers from the first server >> together with ones from the second to a client? > > You can save headers from the first server response from > $upstream_http_* variables and then use add_header to add them to > the final response: > > location / { > proxy_pass http://upstream1; > } > > location /second/ { > set $x_foo_bar $upstream_http_x_foo_bar; > add_header X-Foo-Bar $x_foo_bar; > proxy_pass http://upstream2; > } > > I don't really think we need additional functionality here. > It is hard for me because I want to redirect almost all headers from the first server to a client. Following your suggestion, I need too many set and add_header directives. Thanks, Toshikuni Fukaya From steven.hartland at multiplay.co.uk Mon Dec 22 01:01:35 2014 From: steven.hartland at multiplay.co.uk (Steven Hartland) Date: Mon, 22 Dec 2014 01:01:35 +0000 Subject: Questions for X-Accel-Redirect In-Reply-To: <5493CB47.7060708@cybozu.co.jp> References: <5493CB47.7060708@cybozu.co.jp> Message-ID: <54976D6F.2030707@multiplay.co.uk> If you want to just pass the header through and not process it you can use proxy_pass_header. We do just this to pass X-Accel-Redirect though from server1 -> server2 where its then processed. e.g. proxy_pass_header X-Accel-Redirect Hope this helps. Regards Steve On 19/12/2014 06:52, Toshikuni Fukaya wrote: > Hi, > > I have some questions for X-Accel-Redirect. > > Background: I use X-Accel-Redirect to send blob data from a second > server (:8001 in below). I want to send headers from not only the second > but also the first (:8000). > Current nginx implementation, however, sends only headers from the > second except some headers from the first, such as Content-Type. > > Question 1: > Can I change this behavior to send headers from the first server > together with ones from the second to a client? > > Question 2: > If Q1 is acceptable, I hope to hide some headers by proxy_hide_header > directive. Is this design ok for you? > > ### here is my example conf. ### > server { > listen 80 default_server; > location / { > proxy_pass http://localhost:8000/; > } > location /reproxy/ { > proxy_pass http://localhost:8001/; > } > } > > server { > listen 8000; > location / { > add_header x-accel-redirect /reproxy/; > add_header foo 1; > return 200; > } > } > > server { > listen 8001; > location / { > add_header bar 1; > return 200; > } > } > > Thanks, > Toshikuni Fukaya > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Mon Dec 22 01:19:45 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 22 Dec 2014 04:19:45 +0300 Subject: [Patch] Re: Directive "map" not working with regex key and value that like "$1" In-Reply-To: References: Message-ID: <20141222011945.GA79300@mdounin.ru> Hello! On Sun, Dec 21, 2014 at 11:03:24AM +0800, kindy wrote: > The root cause there are both. var_values & value_hashs. > when used with regex key, we should not use var_values, > because numbered capture are not registered as nginx variable. > > so directive like "~(.+) $1;" will add $1 into var_values by mistake, but > latter regex will not add this variable.. No. The root cause is that $1 variables are special and can't be handled using the ngx_http_get_variable_index() function. As map{} uses the ngx_http_get_variable_index(), it doesn't understand $1..$9 variables. If you want to access captures in resulting values in a map, you can use named captures instead: map $foo $bar { ~(.*) $temp; } > ---start of patch--- > > --- nginx-1.1.19-orig/src/http/modules/ngx_http_map_module.c 2012-01-18 > 23:07:43.000000000 +0800 > +++ nginx-1.1.19-fixe/src/http/modules/ngx_http_map_module.c 2014-12-20 > 10:42:01.000000000 +0800 > @@ -403,6 +403,10 @@ > return ngx_conf_parse(cf, &file); > } > > +#if (NGX_PCRE) > + if (!value[0].len || value[0].data[0] != '~') { > +#endif > + > if (value[1].data[0] == '$') { > name = value[1]; > name.len--; This patch is wrong, it will prevent variable expansion in resulting values if a source value is specified using a regular expression. [...] -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Mon Dec 22 02:10:48 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 22 Dec 2014 05:10:48 +0300 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> <20141218192946.GJ79300@mdounin.ru> Message-ID: <20141222021048.GB79300@mdounin.ru> Hello! On Sat, Dec 20, 2014 at 04:05:13PM -0800, Piotr Sikora wrote: > Hey Maxim, > > > The cacheability of the response was already signalled previously. > > And a 304 response can't really change it. > > Fine, if you want to get technical, then yes, cacheability of the > response was signaled previously, however the 304 response can still > signal that the validity shouldn't be extended (i.e. that the cache > shouldn't be updated), which is what we're really talking about here. > > > Consider, for example, > > that there were no validation request at all - and it happens some > > time later. So the only thing that really changes is validity. > > I don't follow your logic here, what exactly are you trying to say? I'm trying to explain the current behaviour - which, as you said, "is strange". > > That's in line with the RFC2616: it allows 304 to supply new > > Cache-Control and Expires headers if they are different from what > > was previously sent. So we use validity from the 304 response, > > then from the cached response, then from proxy_cache_valid. > > > > What is probably missing here is not using valid_sec if > > u->cacheable is set. > > > > (...) > > > > I agree, see above. > > Which is basically what my patch adds, isn't it? Maybe, but the result looks wrong to me. > > The problem is consistency of the behaviour in equivalent cases. > > > > E.g., consider the following: > > > > - A response with Set-Cookie cached with > > "proxy_ignore_headers Set-Cookie" in the configuration. The > > response contains "Cache-Control: max-age=100". > > > > - Now proxy_ignore_headers is removed from the configuration. We > > do a request with If-Modified-Since, 304 is returned: > > > > (a) If the 304 contains "Cache-Control: max-age=100", the > > response will be cached for 100 more seconds. > > > > (b) If the 304 does not contain "Cache-Control: max-age=100", > > the response won't be updated. > > > > On the other hand, (a) and (b) are equivalent per RFC2616. > > However, according to RFC7232, (a) and (b) are different: > > The server generating a 304 response MUST generate any of the > following header fields that would have been sent in a 200 (OK) > response to the same request: Cache-Control, Content-Location, Date, > ETag, Expires, and Vary. As you can see, RFC7232 doesn't really say they are different - instead, it requires servers to always add relevant headers. On the other hand, if you'll look at the RFC7234 4.3.4 as linked from the paragraph you quoted, you'll find that after merging headers these two cases are still equivalent. But even if you assume they are not equivalent (that is, (b) final response shouldn't have "Cache-Control: max-age=100") in case of (b) validity should be extended as if there are no Cache-Control headers in the response, i.e., per proxy_cache_valid. This is not what happens with your patch, so the problem is here anyway. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Mon Dec 22 10:00:18 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 22 Dec 2014 10:00:18 +0000 Subject: [nginx] Upstream: simplified proxy_store and friends configurati... Message-ID: details: http://hg.nginx.org/nginx/rev/d9025ea1f5a5 branches: changeset: 5947:d9025ea1f5a5 user: Valentin Bartenev date: Mon Dec 22 12:58:56 2014 +0300 description: Upstream: simplified proxy_store and friends configuration code. This changes internal API related to handling of the "store" flag in ngx_http_upstream_conf_t. Previously, a non-null value of "store_lengths" was enough to enable store functionality with custom path. Now, the "store" flag is also required to be set. No functional changes. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 15 ++++++--------- src/http/modules/ngx_http_proxy_module.c | 15 ++++++--------- src/http/modules/ngx_http_scgi_module.c | 13 ++++++------- src/http/modules/ngx_http_uwsgi_module.c | 14 ++++++-------- src/http/ngx_http_upstream.c | 2 +- 5 files changed, 25 insertions(+), 34 deletions(-) diffs (197 lines): diff -r ee941e49bd88 -r d9025ea1f5a5 src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Wed Dec 17 15:12:50 2014 +0100 +++ b/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:58:56 2014 +0300 @@ -2436,10 +2436,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); - if (conf->upstream.store_lengths == NULL) { - conf->upstream.store_lengths = prev->upstream.store_lengths; - conf->upstream.store_values = prev->upstream.store_values; - } + conf->upstream.store_lengths = prev->upstream.store_lengths; + conf->upstream.store_values = prev->upstream.store_values; } ngx_conf_merge_uint_value(conf->upstream.store_access, @@ -3206,9 +3204,7 @@ ngx_http_fastcgi_store(ngx_conf_t *cf, n ngx_str_t *value; ngx_http_script_compile_t sc; - if (flcf->upstream.store != NGX_CONF_UNSET - || flcf->upstream.store_lengths) - { + if (flcf->upstream.store != NGX_CONF_UNSET) { return "is duplicate"; } @@ -3229,8 +3225,9 @@ ngx_http_fastcgi_store(ngx_conf_t *cf, n #endif + flcf->upstream.store = 1; + if (ngx_strcmp(value[1].data, "on") == 0) { - flcf->upstream.store = 1; return NGX_CONF_OK; } @@ -3275,7 +3272,7 @@ ngx_http_fastcgi_cache(ngx_conf_t *cf, n return NGX_CONF_OK; } - if (flcf->upstream.store > 0 || flcf->upstream.store_lengths) { + if (flcf->upstream.store > 0) { return "is incompatible with \"fastcgi_store\""; } diff -r ee941e49bd88 -r d9025ea1f5a5 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Wed Dec 17 15:12:50 2014 +0100 +++ b/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:58:56 2014 +0300 @@ -2628,10 +2628,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); - if (conf->upstream.store_lengths == NULL) { - conf->upstream.store_lengths = prev->upstream.store_lengths; - conf->upstream.store_values = prev->upstream.store_values; - } + conf->upstream.store_lengths = prev->upstream.store_lengths; + conf->upstream.store_values = prev->upstream.store_values; } ngx_conf_merge_uint_value(conf->upstream.store_access, @@ -3794,9 +3792,7 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx ngx_str_t *value; ngx_http_script_compile_t sc; - if (plcf->upstream.store != NGX_CONF_UNSET - || plcf->upstream.store_lengths) - { + if (plcf->upstream.store != NGX_CONF_UNSET) { return "is duplicate"; } @@ -3817,8 +3813,9 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx #endif + plcf->upstream.store = 1; + if (ngx_strcmp(value[1].data, "on") == 0) { - plcf->upstream.store = 1; return NGX_CONF_OK; } @@ -3863,7 +3860,7 @@ ngx_http_proxy_cache(ngx_conf_t *cf, ngx return NGX_CONF_OK; } - if (plcf->upstream.store > 0 || plcf->upstream.store_lengths) { + if (plcf->upstream.store > 0) { return "is incompatible with \"proxy_store\""; } diff -r ee941e49bd88 -r d9025ea1f5a5 src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c Wed Dec 17 15:12:50 2014 +0100 +++ b/src/http/modules/ngx_http_scgi_module.c Mon Dec 22 12:58:56 2014 +0300 @@ -1189,10 +1189,8 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); - if (conf->upstream.store_lengths == NULL) { - conf->upstream.store_lengths = prev->upstream.store_lengths; - conf->upstream.store_values = prev->upstream.store_values; - } + conf->upstream.store_lengths = prev->upstream.store_lengths; + conf->upstream.store_values = prev->upstream.store_values; } ngx_conf_merge_uint_value(conf->upstream.store_access, @@ -1760,7 +1758,7 @@ ngx_http_scgi_store(ngx_conf_t *cf, ngx_ ngx_str_t *value; ngx_http_script_compile_t sc; - if (scf->upstream.store != NGX_CONF_UNSET || scf->upstream.store_lengths) { + if (scf->upstream.store != NGX_CONF_UNSET) { return "is duplicate"; } @@ -1781,8 +1779,9 @@ ngx_http_scgi_store(ngx_conf_t *cf, ngx_ #endif + scf->upstream.store = 1; + if (ngx_strcmp(value[1].data, "on") == 0) { - scf->upstream.store = 1; return NGX_CONF_OK; } @@ -1827,7 +1826,7 @@ ngx_http_scgi_cache(ngx_conf_t *cf, ngx_ return NGX_CONF_OK; } - if (scf->upstream.store > 0 || scf->upstream.store_lengths) { + if (scf->upstream.store > 0) { return "is incompatible with \"scgi_store\""; } diff -r ee941e49bd88 -r d9025ea1f5a5 src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Wed Dec 17 15:12:50 2014 +0100 +++ b/src/http/modules/ngx_http_uwsgi_module.c Mon Dec 22 12:58:56 2014 +0300 @@ -1403,10 +1403,8 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); - if (conf->upstream.store_lengths == NULL) { - conf->upstream.store_lengths = prev->upstream.store_lengths; - conf->upstream.store_values = prev->upstream.store_values; - } + conf->upstream.store_lengths = prev->upstream.store_lengths; + conf->upstream.store_values = prev->upstream.store_values; } ngx_conf_merge_uint_value(conf->upstream.store_access, @@ -2047,8 +2045,7 @@ ngx_http_uwsgi_store(ngx_conf_t *cf, ngx ngx_str_t *value; ngx_http_script_compile_t sc; - if (uwcf->upstream.store != NGX_CONF_UNSET || uwcf->upstream.store_lengths) - { + if (uwcf->upstream.store != NGX_CONF_UNSET) { return "is duplicate"; } @@ -2069,8 +2066,9 @@ ngx_http_uwsgi_store(ngx_conf_t *cf, ngx #endif + uwcf->upstream.store = 1; + if (ngx_strcmp(value[1].data, "on") == 0) { - uwcf->upstream.store = 1; return NGX_CONF_OK; } @@ -2115,7 +2113,7 @@ ngx_http_uwsgi_cache(ngx_conf_t *cf, ngx return NGX_CONF_OK; } - if (uwcf->upstream.store > 0 || uwcf->upstream.store_lengths) { + if (uwcf->upstream.store > 0) { return "is incompatible with \"uwsgi_store\""; } diff -r ee941e49bd88 -r d9025ea1f5a5 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Wed Dec 17 15:12:50 2014 +0100 +++ b/src/http/ngx_http_upstream.c Mon Dec 22 12:58:56 2014 +0300 @@ -540,7 +540,7 @@ ngx_http_upstream_init_request(ngx_http_ #endif - u->store = (u->conf->store || u->conf->store_lengths); + u->store = u->conf->store; if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { r->read_event_handler = ngx_http_upstream_rd_check_broken_connection; From vbart at nginx.com Mon Dec 22 10:00:21 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 22 Dec 2014 10:00:21 +0000 Subject: [nginx] Upstream: mutually exclusive inheritance of "cache" and ... Message-ID: details: http://hg.nginx.org/nginx/rev/f2ff0aa89126 branches: changeset: 5948:f2ff0aa89126 user: Valentin Bartenev date: Mon Dec 22 12:58:59 2014 +0300 description: Upstream: mutually exclusive inheritance of "cache" and "store". Currently, storing and caching mechanisms cannot work together, and a configuration error is thrown when the proxy_store and proxy_cache directives (as well as their friends) are configured on the same level. But configurations like in the example below were allowed and could result in critical errors in the error log: proxy_store on; location / { proxy_cache one; } Only proxy_store worked in this case. For more predictable and errorless behavior these directives now prevent each other from being inherited from the previous level. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 14 ++++++++++++++ src/http/modules/ngx_http_proxy_module.c | 14 ++++++++++++++ src/http/modules/ngx_http_scgi_module.c | 14 ++++++++++++++ src/http/modules/ngx_http_uwsgi_module.c | 14 ++++++++++++++ 4 files changed, 56 insertions(+), 0 deletions(-) diffs (96 lines): diff -r d9025ea1f5a5 -r f2ff0aa89126 src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:58:56 2014 +0300 +++ b/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:58:59 2014 +0300 @@ -2432,6 +2432,20 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; +#if (NGX_HTTP_CACHE) + + if (conf->upstream.store > 0) { + conf->upstream.cache = NULL; + } + + if (conf->upstream.cache != NGX_CONF_UNSET_PTR + && conf->upstream.cache != NULL) + { + conf->upstream.store = 0; + } + +#endif + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); diff -r d9025ea1f5a5 -r f2ff0aa89126 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:58:56 2014 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:58:59 2014 +0300 @@ -2624,6 +2624,20 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_http_proxy_rewrite_t *pr; ngx_http_script_compile_t sc; +#if (NGX_HTTP_CACHE) + + if (conf->upstream.store > 0) { + conf->upstream.cache = NULL; + } + + if (conf->upstream.cache != NGX_CONF_UNSET_PTR + && conf->upstream.cache != NULL) + { + conf->upstream.store = 0; + } + +#endif + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); diff -r d9025ea1f5a5 -r f2ff0aa89126 src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c Mon Dec 22 12:58:56 2014 +0300 +++ b/src/http/modules/ngx_http_scgi_module.c Mon Dec 22 12:58:59 2014 +0300 @@ -1186,6 +1186,20 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; +#if (NGX_HTTP_CACHE) + + if (conf->upstream.store > 0) { + conf->upstream.cache = NULL; + } + + if (conf->upstream.cache != NGX_CONF_UNSET_PTR + && conf->upstream.cache != NULL) + { + conf->upstream.store = 0; + } + +#endif + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); diff -r d9025ea1f5a5 -r f2ff0aa89126 src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c Mon Dec 22 12:58:56 2014 +0300 +++ b/src/http/modules/ngx_http_uwsgi_module.c Mon Dec 22 12:58:59 2014 +0300 @@ -1400,6 +1400,20 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_hash_init_t hash; ngx_http_core_loc_conf_t *clcf; +#if (NGX_HTTP_CACHE) + + if (conf->upstream.store > 0) { + conf->upstream.cache = NULL; + } + + if (conf->upstream.cache != NGX_CONF_UNSET_PTR + && conf->upstream.cache != NULL) + { + conf->upstream.store = 0; + } + +#endif + if (conf->upstream.store == NGX_CONF_UNSET) { ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0); From vbart at nginx.com Mon Dec 22 10:00:24 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 22 Dec 2014 10:00:24 +0000 Subject: [nginx] Upstream: refactored proxy_cache and friends. Message-ID: details: http://hg.nginx.org/nginx/rev/634da79665d3 branches: changeset: 5949:634da79665d3 user: Valentin Bartenev date: Mon Dec 22 12:59:02 2014 +0300 description: Upstream: refactored proxy_cache and friends. The configuration handling code has changed to look similar to the proxy_store directive and friends. This simplifies adding variable support in the following patch. No functional changes. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 41 +++++++++++++++-------------- src/http/modules/ngx_http_proxy_module.c | 41 +++++++++++++++-------------- src/http/modules/ngx_http_scgi_module.c | 38 +++++++++++++------------- src/http/modules/ngx_http_uwsgi_module.c | 38 ++++++++++++++------------- src/http/ngx_http_upstream.c | 6 ++-- src/http/ngx_http_upstream.h | 5 ++- 6 files changed, 88 insertions(+), 81 deletions(-) diffs (truncated from 443 to 300 lines): diff -r f2ff0aa89126 -r 634da79665d3 src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:58:59 2014 +0300 +++ b/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:59:02 2014 +0300 @@ -2352,6 +2352,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con * conf->upstream.bufs.num = 0; * conf->upstream.ignore_headers = 0; * conf->upstream.next_upstream = 0; + * conf->upstream.cache_zone = NULL; * conf->upstream.cache_use_stale = 0; * conf->upstream.cache_methods = 0; * conf->upstream.temp_path = NULL; @@ -2390,7 +2391,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.pass_request_body = NGX_CONF_UNSET; #if (NGX_HTTP_CACHE) - conf->upstream.cache = NGX_CONF_UNSET_PTR; + conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; @@ -2435,12 +2436,10 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf #if (NGX_HTTP_CACHE) if (conf->upstream.store > 0) { - conf->upstream.cache = NULL; + conf->upstream.cache = 0; } - if (conf->upstream.cache != NGX_CONF_UNSET_PTR - && conf->upstream.cache != NULL) - { + if (conf->upstream.cache > 0) { conf->upstream.store = 0; } @@ -2613,13 +2612,17 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf #if (NGX_HTTP_CACHE) - ngx_conf_merge_ptr_value(conf->upstream.cache, - prev->upstream.cache, NULL); - - if (conf->upstream.cache && conf->upstream.cache->data == NULL) { + if (conf->upstream.cache == NGX_CONF_UNSET) { + ngx_conf_merge_value(conf->upstream.cache, + prev->upstream.cache, 0); + + conf->upstream.cache_zone = prev->upstream.cache_zone; + } + + if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) { ngx_shm_zone_t *shm_zone; - shm_zone = conf->upstream.cache; + shm_zone = conf->upstream.cache_zone; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"fastcgi_cache\" zone \"%V\" is unknown", @@ -3230,13 +3233,9 @@ ngx_http_fastcgi_store(ngx_conf_t *cf, n } #if (NGX_HTTP_CACHE) - - if (flcf->upstream.cache != NGX_CONF_UNSET_PTR - && flcf->upstream.cache != NULL) - { + if (flcf->upstream.cache > 0) { return "is incompatible with \"fastcgi_cache\""; } - #endif flcf->upstream.store = 1; @@ -3277,12 +3276,12 @@ ngx_http_fastcgi_cache(ngx_conf_t *cf, n value = cf->args->elts; - if (flcf->upstream.cache != NGX_CONF_UNSET_PTR) { + if (flcf->upstream.cache != NGX_CONF_UNSET) { return "is duplicate"; } if (ngx_strcmp(value[1].data, "off") == 0) { - flcf->upstream.cache = NULL; + flcf->upstream.cache = 0; return NGX_CONF_OK; } @@ -3290,9 +3289,11 @@ ngx_http_fastcgi_cache(ngx_conf_t *cf, n return "is incompatible with \"fastcgi_store\""; } - flcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, - &ngx_http_fastcgi_module); - if (flcf->upstream.cache == NULL) { + flcf->upstream.cache = 1; + + flcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0, + &ngx_http_fastcgi_module); + if (flcf->upstream.cache_zone == NULL) { return NGX_CONF_ERROR; } diff -r f2ff0aa89126 -r 634da79665d3 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:58:59 2014 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:59:02 2014 +0300 @@ -2509,6 +2509,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ * conf->upstream.bufs.num = 0; * conf->upstream.ignore_headers = 0; * conf->upstream.next_upstream = 0; + * conf->upstream.cache_zone = NULL; * conf->upstream.cache_use_stale = 0; * conf->upstream.cache_methods = 0; * conf->upstream.temp_path = NULL; @@ -2566,7 +2567,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.pass_request_body = NGX_CONF_UNSET; #if (NGX_HTTP_CACHE) - conf->upstream.cache = NGX_CONF_UNSET_PTR; + conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; @@ -2627,12 +2628,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_CACHE) if (conf->upstream.store > 0) { - conf->upstream.cache = NULL; + conf->upstream.cache = 0; } - if (conf->upstream.cache != NGX_CONF_UNSET_PTR - && conf->upstream.cache != NULL) - { + if (conf->upstream.cache > 0) { conf->upstream.store = 0; } @@ -2804,13 +2803,17 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_CACHE) - ngx_conf_merge_ptr_value(conf->upstream.cache, - prev->upstream.cache, NULL); - - if (conf->upstream.cache && conf->upstream.cache->data == NULL) { + if (conf->upstream.cache == NGX_CONF_UNSET) { + ngx_conf_merge_value(conf->upstream.cache, + prev->upstream.cache, 0); + + conf->upstream.cache_zone = prev->upstream.cache_zone; + } + + if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) { ngx_shm_zone_t *shm_zone; - shm_zone = conf->upstream.cache; + shm_zone = conf->upstream.cache_zone; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"proxy_cache\" zone \"%V\" is unknown", @@ -3818,13 +3821,9 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx } #if (NGX_HTTP_CACHE) - - if (plcf->upstream.cache != NGX_CONF_UNSET_PTR - && plcf->upstream.cache != NULL) - { + if (plcf->upstream.cache > 0) { return "is incompatible with \"proxy_cache\""; } - #endif plcf->upstream.store = 1; @@ -3865,12 +3864,12 @@ ngx_http_proxy_cache(ngx_conf_t *cf, ngx value = cf->args->elts; - if (plcf->upstream.cache != NGX_CONF_UNSET_PTR) { + if (plcf->upstream.cache != NGX_CONF_UNSET) { return "is duplicate"; } if (ngx_strcmp(value[1].data, "off") == 0) { - plcf->upstream.cache = NULL; + plcf->upstream.cache = 0; return NGX_CONF_OK; } @@ -3878,9 +3877,11 @@ ngx_http_proxy_cache(ngx_conf_t *cf, ngx return "is incompatible with \"proxy_store\""; } - plcf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, - &ngx_http_proxy_module); - if (plcf->upstream.cache == NULL) { + plcf->upstream.cache = 1; + + plcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0, + &ngx_http_proxy_module); + if (plcf->upstream.cache_zone == NULL) { return NGX_CONF_ERROR; } diff -r f2ff0aa89126 -r 634da79665d3 src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c Mon Dec 22 12:58:59 2014 +0300 +++ b/src/http/modules/ngx_http_scgi_module.c Mon Dec 22 12:59:02 2014 +0300 @@ -1148,7 +1148,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t conf->upstream.pass_request_body = NGX_CONF_UNSET; #if (NGX_HTTP_CACHE) - conf->upstream.cache = NGX_CONF_UNSET_PTR; + conf->upstream.cache = NGX_CONF_UNSET; conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT; conf->upstream.cache_bypass = NGX_CONF_UNSET_PTR; conf->upstream.no_cache = NGX_CONF_UNSET_PTR; @@ -1189,12 +1189,10 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_CACHE) if (conf->upstream.store > 0) { - conf->upstream.cache = NULL; + conf->upstream.cache = 0; } - if (conf->upstream.cache != NGX_CONF_UNSET_PTR - && conf->upstream.cache != NULL) - { + if (conf->upstream.cache > 0) { conf->upstream.store = 0; } @@ -1366,13 +1364,17 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t #if (NGX_HTTP_CACHE) - ngx_conf_merge_ptr_value(conf->upstream.cache, - prev->upstream.cache, NULL); + if (conf->upstream.cache == NGX_CONF_UNSET) { + ngx_conf_merge_value(conf->upstream.cache, + prev->upstream.cache, 0); - if (conf->upstream.cache && conf->upstream.cache->data == NULL) { + conf->upstream.cache_zone = prev->upstream.cache_zone; + } + + if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) { ngx_shm_zone_t *shm_zone; - shm_zone = conf->upstream.cache; + shm_zone = conf->upstream.cache_zone; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "\"scgi_cache\" zone \"%V\" is unknown", @@ -1784,13 +1786,9 @@ ngx_http_scgi_store(ngx_conf_t *cf, ngx_ } #if (NGX_HTTP_CACHE) - - if (scf->upstream.cache != NGX_CONF_UNSET_PTR - && scf->upstream.cache != NULL) - { + if (scf->upstream.cache > 0) { return "is incompatible with \"scgi_cache\""; } - #endif scf->upstream.store = 1; @@ -1831,12 +1829,12 @@ ngx_http_scgi_cache(ngx_conf_t *cf, ngx_ value = cf->args->elts; - if (scf->upstream.cache != NGX_CONF_UNSET_PTR) { + if (scf->upstream.cache != NGX_CONF_UNSET) { return "is duplicate"; } if (ngx_strcmp(value[1].data, "off") == 0) { - scf->upstream.cache = NULL; + scf->upstream.cache = 0; return NGX_CONF_OK; } @@ -1844,9 +1842,11 @@ ngx_http_scgi_cache(ngx_conf_t *cf, ngx_ return "is incompatible with \"scgi_store\""; } - scf->upstream.cache = ngx_shared_memory_add(cf, &value[1], 0, - &ngx_http_scgi_module); - if (scf->upstream.cache == NULL) { + scf->upstream.cache = 1; + + scf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0, + &ngx_http_scgi_module); + if (scf->upstream.cache_zone == NULL) { return NGX_CONF_ERROR; } From vbart at nginx.com Mon Dec 22 10:00:26 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 22 Dec 2014 10:00:26 +0000 Subject: [nginx] Upstream: preset some cache configuration when bypassing. Message-ID: details: http://hg.nginx.org/nginx/rev/eaeecf00d5d7 branches: changeset: 5950:eaeecf00d5d7 user: Valentin Bartenev date: Mon Dec 22 12:59:06 2014 +0300 description: Upstream: preset some cache configuration when bypassing. No functional changes. diffstat: src/http/ngx_http_upstream.c | 16 +++++++--------- 1 files changed, 7 insertions(+), 9 deletions(-) diffs (40 lines): diff -r 634da79665d3 -r eaeecf00d5d7 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Mon Dec 22 12:59:02 2014 +0300 +++ b/src/http/ngx_http_upstream.c Mon Dec 22 12:59:06 2014 +0300 @@ -763,6 +763,12 @@ ngx_http_upstream_cache(ngx_http_request u->cacheable = 1; + c = r->cache; + + c->body_start = u->conf->buffer_size; + c->min_uses = u->conf->cache_min_uses; + c->file_cache = u->conf->cache_zone->data; + switch (ngx_http_test_predicates(r, u->conf->cache_bypass)) { case NGX_ERROR: @@ -776,12 +782,6 @@ ngx_http_upstream_cache(ngx_http_request break; } - c = r->cache; - - c->min_uses = u->conf->cache_min_uses; - c->body_start = u->conf->buffer_size; - c->file_cache = u->conf->cache_zone->data; - c->lock = u->conf->cache_lock; c->lock_timeout = u->conf->cache_lock_timeout; c->lock_age = u->conf->cache_lock_age; @@ -2536,9 +2536,7 @@ ngx_http_upstream_send_response(ngx_http if (u->cache_status == NGX_HTTP_CACHE_BYPASS) { - r->cache->min_uses = u->conf->cache_min_uses; - r->cache->body_start = u->conf->buffer_size; - r->cache->file_cache = u->conf->cache_zone->data; + /* create cache if previously bypassed */ if (ngx_http_file_cache_create(r) != NGX_OK) { ngx_http_upstream_finalize_request(r, u, NGX_ERROR); From vbart at nginx.com Mon Dec 22 10:00:29 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Mon, 22 Dec 2014 10:00:29 +0000 Subject: [nginx] Upstream: added variables support to proxy_cache and fri... Message-ID: details: http://hg.nginx.org/nginx/rev/610832763648 branches: changeset: 5951:610832763648 user: Valentin Bartenev date: Mon Dec 22 12:59:09 2014 +0300 description: Upstream: added variables support to proxy_cache and friends. diffstat: src/http/modules/ngx_http_fastcgi_module.c | 78 ++++++++++++++++++++++++++--- src/http/modules/ngx_http_proxy_module.c | 78 ++++++++++++++++++++++++++--- src/http/modules/ngx_http_scgi_module.c | 78 ++++++++++++++++++++++++++--- src/http/modules/ngx_http_uwsgi_module.c | 78 ++++++++++++++++++++++++++--- src/http/ngx_http_file_cache.c | 14 +++++- src/http/ngx_http_upstream.c | 58 +++++++++++++++++++++- src/http/ngx_http_upstream.h | 4 + 7 files changed, 352 insertions(+), 36 deletions(-) diffs (truncated from 767 to 300 lines): diff -r eaeecf00d5d7 -r 610832763648 src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:59:06 2014 +0300 +++ b/src/http/modules/ngx_http_fastcgi_module.c Mon Dec 22 12:59:09 2014 +0300 @@ -11,6 +11,11 @@ typedef struct { + ngx_array_t caches; /* ngx_http_file_cache_t * */ +} ngx_http_fastcgi_main_conf_t; + + +typedef struct { ngx_array_t *flushes; ngx_array_t *lengths; ngx_array_t *values; @@ -155,6 +160,7 @@ static void ngx_http_fastcgi_finalize_re ngx_int_t rc); static ngx_int_t ngx_http_fastcgi_add_variables(ngx_conf_t *cf); +static void *ngx_http_fastcgi_create_main_conf(ngx_conf_t *cf); static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); @@ -368,8 +374,8 @@ static ngx_command_t ngx_http_fastcgi_c { ngx_string("fastcgi_cache_path"), NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE, ngx_http_file_cache_set_slot, - 0, - 0, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_fastcgi_main_conf_t, caches), &ngx_http_fastcgi_module }, { ngx_string("fastcgi_cache_bypass"), @@ -536,7 +542,7 @@ static ngx_http_module_t ngx_http_fastc ngx_http_fastcgi_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ - NULL, /* create main configuration */ + ngx_http_fastcgi_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ @@ -635,10 +641,13 @@ static ngx_path_init_t ngx_http_fastcgi static ngx_int_t ngx_http_fastcgi_handler(ngx_http_request_t *r) { - ngx_int_t rc; - ngx_http_upstream_t *u; - ngx_http_fastcgi_ctx_t *f; - ngx_http_fastcgi_loc_conf_t *flcf; + ngx_int_t rc; + ngx_http_upstream_t *u; + ngx_http_fastcgi_ctx_t *f; + ngx_http_fastcgi_loc_conf_t *flcf; +#if (NGX_HTTP_CACHE) + ngx_http_fastcgi_main_conf_t *fmcf; +#endif if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -667,8 +676,12 @@ ngx_http_fastcgi_handler(ngx_http_reques u->conf = &flcf->upstream; #if (NGX_HTTP_CACHE) + fmcf = ngx_http_get_module_main_conf(r, ngx_http_fastcgi_module); + + u->caches = &fmcf->caches; u->create_key = ngx_http_fastcgi_create_key; #endif + u->create_request = ngx_http_fastcgi_create_request; u->reinit_request = ngx_http_fastcgi_reinit_request; u->process_header = ngx_http_fastcgi_process_header; @@ -2337,6 +2350,29 @@ ngx_http_fastcgi_add_variables(ngx_conf_ static void * +ngx_http_fastcgi_create_main_conf(ngx_conf_t *cf) +{ + ngx_http_fastcgi_main_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fastcgi_main_conf_t)); + if (conf == NULL) { + return NULL; + } + +#if (NGX_HTTP_CACHE) + if (ngx_array_init(&conf->caches, cf->pool, 4, + sizeof(ngx_http_file_cache_t *)) + != NGX_OK) + { + return NULL; + } +#endif + + return conf; +} + + +static void * ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) { ngx_http_fastcgi_loc_conf_t *conf; @@ -2617,6 +2653,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf prev->upstream.cache, 0); conf->upstream.cache_zone = prev->upstream.cache_zone; + conf->upstream.cache_value = prev->upstream.cache_value; } if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) { @@ -3272,7 +3309,9 @@ ngx_http_fastcgi_cache(ngx_conf_t *cf, n { ngx_http_fastcgi_loc_conf_t *flcf = conf; - ngx_str_t *value; + ngx_str_t *value; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; value = cf->args->elts; @@ -3291,6 +3330,29 @@ ngx_http_fastcgi_cache(ngx_conf_t *cf, n flcf->upstream.cache = 1; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + + flcf->upstream.cache_value = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + if (flcf->upstream.cache_value == NULL) { + return NGX_CONF_ERROR; + } + + *flcf->upstream.cache_value = cv; + + return NGX_CONF_OK; + } + flcf->upstream.cache_zone = ngx_shared_memory_add(cf, &value[1], 0, &ngx_http_fastcgi_module); if (flcf->upstream.cache_zone == NULL) { diff -r eaeecf00d5d7 -r 610832763648 src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:59:06 2014 +0300 +++ b/src/http/modules/ngx_http_proxy_module.c Mon Dec 22 12:59:09 2014 +0300 @@ -10,6 +10,11 @@ #include +typedef struct { + ngx_array_t caches; /* ngx_http_file_cache_t * */ +} ngx_http_proxy_main_conf_t; + + typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t; typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r, @@ -151,6 +156,7 @@ static ngx_int_t ngx_http_proxy_rewrite( ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement); static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf); +static void *ngx_http_proxy_create_main_conf(ngx_conf_t *cf); static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); @@ -438,8 +444,8 @@ static ngx_command_t ngx_http_proxy_com { ngx_string("proxy_cache_path"), NGX_HTTP_MAIN_CONF|NGX_CONF_2MORE, ngx_http_file_cache_set_slot, - 0, - 0, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_proxy_main_conf_t, caches), &ngx_http_proxy_module }, { ngx_string("proxy_cache_bypass"), @@ -680,7 +686,7 @@ static ngx_http_module_t ngx_http_proxy ngx_http_proxy_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ - NULL, /* create main configuration */ + ngx_http_proxy_create_main_conf, /* create main configuration */ NULL, /* init main configuration */ NULL, /* create server configuration */ @@ -792,10 +798,13 @@ static ngx_path_init_t ngx_http_proxy_t static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r) { - ngx_int_t rc; - ngx_http_upstream_t *u; - ngx_http_proxy_ctx_t *ctx; - ngx_http_proxy_loc_conf_t *plcf; + ngx_int_t rc; + ngx_http_upstream_t *u; + ngx_http_proxy_ctx_t *ctx; + ngx_http_proxy_loc_conf_t *plcf; +#if (NGX_HTTP_CACHE) + ngx_http_proxy_main_conf_t *pmcf; +#endif if (ngx_http_upstream_create(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; @@ -830,8 +839,12 @@ ngx_http_proxy_handler(ngx_http_request_ u->conf = &plcf->upstream; #if (NGX_HTTP_CACHE) + pmcf = ngx_http_get_module_main_conf(r, ngx_http_proxy_module); + + u->caches = &pmcf->caches; u->create_key = ngx_http_proxy_create_key; #endif + u->create_request = ngx_http_proxy_create_request; u->reinit_request = ngx_http_proxy_reinit_request; u->process_header = ngx_http_proxy_process_status_line; @@ -2494,6 +2507,29 @@ ngx_http_proxy_add_variables(ngx_conf_t static void * +ngx_http_proxy_create_main_conf(ngx_conf_t *cf) +{ + ngx_http_proxy_main_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_main_conf_t)); + if (conf == NULL) { + return NULL; + } + +#if (NGX_HTTP_CACHE) + if (ngx_array_init(&conf->caches, cf->pool, 4, + sizeof(ngx_http_file_cache_t *)) + != NGX_OK) + { + return NULL; + } +#endif + + return conf; +} + + +static void * ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) { ngx_http_proxy_loc_conf_t *conf; @@ -2808,6 +2844,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t prev->upstream.cache, 0); conf->upstream.cache_zone = prev->upstream.cache_zone; + conf->upstream.cache_value = prev->upstream.cache_value; } if (conf->upstream.cache_zone && conf->upstream.cache_zone->data == NULL) { @@ -3860,7 +3897,9 @@ ngx_http_proxy_cache(ngx_conf_t *cf, ngx { ngx_http_proxy_loc_conf_t *plcf = conf; - ngx_str_t *value; + ngx_str_t *value; + ngx_http_complex_value_t cv; + ngx_http_compile_complex_value_t ccv; value = cf->args->elts; @@ -3879,6 +3918,29 @@ ngx_http_proxy_cache(ngx_conf_t *cf, ngx plcf->upstream.cache = 1; + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &cv; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + if (cv.lengths != NULL) { + + plcf->upstream.cache_value = ngx_palloc(cf->pool, + sizeof(ngx_http_complex_value_t)); + if (plcf->upstream.cache_value == NULL) { + return NGX_CONF_ERROR; + } + + *plcf->upstream.cache_value = cv; + From mdounin at mdounin.ru Mon Dec 22 13:05:30 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Mon, 22 Dec 2014 16:05:30 +0300 Subject: [PATCH] Cache: check if ETag and Vary didn't change before updating header In-Reply-To: <7e7f823e87fc02c55d46.1419121377@piotrs-macbook-pro.local> References: <7e7f823e87fc02c55d46.1419121377@piotrs-macbook-pro.local> Message-ID: <20141222130530.GF79300@mdounin.ru> Hello! On Sat, Dec 20, 2014 at 04:22:57PM -0800, Piotr Sikora wrote: > # HG changeset patch > # User Piotr Sikora > # Date 1419121345 28800 > # Sat Dec 20 16:22:25 2014 -0800 > # Node ID 7e7f823e87fc02c55d46d74a65b336752afe17ee > # Parent ee941e49bd8899d2beb3da9ec36acf3b56c5ce9e > Cache: check if ETag and Vary didn't change before updating header. > > Signed-off-by: Piotr Sikora > > diff -r ee941e49bd88 -r 7e7f823e87fc src/http/ngx_http_file_cache.c > --- a/src/http/ngx_http_file_cache.c Wed Dec 17 15:12:50 2014 +0100 > +++ b/src/http/ngx_http_file_cache.c Sat Dec 20 16:22:25 2014 -0800 > @@ -1362,6 +1362,10 @@ ngx_http_file_cache_update_header(ngx_ht > > if (h.version != NGX_HTTP_CACHE_VERSION > || h.last_modified != c->last_modified > + || h.etag_len != c->etag.len > + || ngx_memcmp(h.etag, c->etag.data, c->etag.len) != 0 > + || h.vary_len != c->vary.len > + || ngx_memcmp(h.vary, c->vary.data, c->vary.len) != 0 > || h.crc32 != c->crc32 > || h.header_start != c->header_start > || h.body_start != c->body_start) The check in question is mostly a safeguard to ensure that ngx_file_uniq() check above did it's work properly. Any specific reason to assume it needs to be extended? -- Maxim Dounin http://nginx.org/ From piotr at cloudflare.com Mon Dec 22 22:34:45 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 22 Dec 2014 14:34:45 -0800 Subject: [nginx] Upstream: added variables support to proxy_cache and fri... In-Reply-To: References: Message-ID: Hey Valentin, > details: http://hg.nginx.org/nginx/rev/610832763648 > branches: > changeset: 5951:610832763648 > user: Valentin Bartenev > date: Mon Dec 22 12:59:09 2014 +0300 > description: > Upstream: added variables support to proxy_cache and friends. Is there any reason why ngx_http_upstream_cache_get() isn't exported? Best regards, Piotr Sikora From piotr at cloudflare.com Mon Dec 22 22:58:43 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 22 Dec 2014 14:58:43 -0800 Subject: [PATCH] Cache: check if ETag and Vary didn't change before updating header In-Reply-To: <20141222130530.GF79300@mdounin.ru> References: <7e7f823e87fc02c55d46.1419121377@piotrs-macbook-pro.local> <20141222130530.GF79300@mdounin.ru> Message-ID: Hey Maxim, > The check in question is mostly a safeguard to ensure that > ngx_file_uniq() check above did it's work properly. I'm aware of that. > Any specific reason to assume it needs to be extended? It just seems inconsistent to check only some of the fields that aren't supposed to change (i.e. version, last modified, etc.), but not the others (i.e. etag and vary). Best regards, Piotr Sikora From piotr at cloudflare.com Tue Dec 23 01:02:32 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 22 Dec 2014 17:02:32 -0800 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: <20141222021048.GB79300@mdounin.ru> References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> <20141218192946.GJ79300@mdounin.ru> <20141222021048.GB79300@mdounin.ru> Message-ID: Hey Maxim, > As you can see, RFC7232 doesn't really say they are different - > instead, it requires servers to always add relevant headers. On > the other hand, if you'll look at the RFC7234 4.3.4 as linked from the > paragraph you quoted, you'll find that after merging headers these > two cases are still equivalent. Agreed. On the other hand, it requires 304 responses to include all cache-related headers. > But even if you assume they are not equivalent (that is, (b) final > response shouldn't have "Cache-Control: max-age=100") in case of (b) > validity should be extended as if there are no Cache-Control > headers in the response, i.e., per proxy_cache_valid. This is not what > happens with your patch, so the problem is here anyway. Ironically, with the patch I sent, the cache will be updated according to headers from cached response if there is nothing in 304 response that sets the validity, which makes (a) and (b) equivalent... And as far as I can tell, this matches the current behavior, so I'm not really sure what's the problem you're talking about. Best regards, Piotr Sikora From mdounin at mdounin.ru Tue Dec 23 01:16:25 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 23 Dec 2014 04:16:25 +0300 Subject: [PATCH] Cache: check if ETag and Vary didn't change before updating header In-Reply-To: References: <7e7f823e87fc02c55d46.1419121377@piotrs-macbook-pro.local> <20141222130530.GF79300@mdounin.ru> Message-ID: <20141223011625.GP79300@mdounin.ru> Hello! On Mon, Dec 22, 2014 at 02:58:43PM -0800, Piotr Sikora wrote: > Hey Maxim, > > > The check in question is mostly a safeguard to ensure that > > ngx_file_uniq() check above did it's work properly. > > I'm aware of that. > > > Any specific reason to assume it needs to be extended? > > It just seems inconsistent to check only some of the fields that > aren't supposed to change (i.e. version, last modified, etc.), but not > the others (i.e. etag and vary). Ok, understood. I don't think this check needs to be extended - as of now it checks basic fixed-width fields, and I think these checks should be sufficient. -- Maxim Dounin http://nginx.org/ From mdounin at mdounin.ru Tue Dec 23 01:28:40 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 23 Dec 2014 04:28:40 +0300 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> <20141218192946.GJ79300@mdounin.ru> <20141222021048.GB79300@mdounin.ru> Message-ID: <20141223012840.GQ79300@mdounin.ru> Hello! On Mon, Dec 22, 2014 at 05:02:32PM -0800, Piotr Sikora wrote: > > But even if you assume they are not equivalent (that is, (b) final > > response shouldn't have "Cache-Control: max-age=100") in case of (b) > > validity should be extended as if there are no Cache-Control > > headers in the response, i.e., per proxy_cache_valid. This is not what > > happens with your patch, so the problem is here anyway. > > Ironically, with the patch I sent, the cache will be updated according > to headers from cached response if there is nothing in 304 response > that sets the validity, which makes (a) and (b) equivalent... And as > far as I can tell, this matches the current behavior, so I'm not > really sure what's the problem you're talking about. With the patch you've sent the response will not be updated in case (b), but will be updated in case (a). And this difference is the problem. -- Maxim Dounin http://nginx.org/ From piotr at cloudflare.com Tue Dec 23 01:46:53 2014 From: piotr at cloudflare.com (Piotr Sikora) Date: Mon, 22 Dec 2014 17:46:53 -0800 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: <20141223012840.GQ79300@mdounin.ru> References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> <20141218192946.GJ79300@mdounin.ru> <20141222021048.GB79300@mdounin.ru> <20141223012840.GQ79300@mdounin.ru> Message-ID: Hey Maxim, > With the patch you've sent the response will not be updated in > case (b), but will be updated in case (a). And this difference is > the problem. It will be updated in both cases: - in (a) it will use the "Cache-Control" from 304 response, - in (b) it will use the "Cache-Control" from cached response. How are you testing this? Best regards, Piotr Sikora From mdounin at mdounin.ru Tue Dec 23 03:03:16 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 23 Dec 2014 06:03:16 +0300 Subject: [PATCH 1 of 2] Cache: don't update cache if revalidated response is not cacheable In-Reply-To: References: <01f07fc7932b64f261c9.1416886073@piotrs-macbook-pro.local> <20141204181150.GE62402@mdounin.ru> <20141218192946.GJ79300@mdounin.ru> <20141222021048.GB79300@mdounin.ru> <20141223012840.GQ79300@mdounin.ru> Message-ID: <20141223030316.GR79300@mdounin.ru> Hello! On Mon, Dec 22, 2014 at 05:46:53PM -0800, Piotr Sikora wrote: > Hey Maxim, > > > With the patch you've sent the response will not be updated in > > case (b), but will be updated in case (a). And this difference is > > the problem. > > It will be updated in both cases: > - in (a) it will use the "Cache-Control" from 304 response, > - in (b) it will use the "Cache-Control" from cached response. It won't, as in case (b) the condition "(u->cacheable || valid)" in your patch evaluates to false. Note that the cached response is not cacheable now due to Set-Cookie. -- Maxim Dounin http://nginx.org/ From vbart at nginx.com Tue Dec 23 11:26:51 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Tue, 23 Dec 2014 14:26:51 +0300 Subject: [nginx] Upstream: added variables support to proxy_cache and fri... In-Reply-To: References: Message-ID: <1757238.jlnPW6gI7R@vbart-workstation> On Monday 22 December 2014 14:34:45 Piotr Sikora wrote: > Hey Valentin, > > > details: http://hg.nginx.org/nginx/rev/610832763648 > > branches: > > changeset: 5951:610832763648 > > user: Valentin Bartenev > > date: Mon Dec 22 12:59:09 2014 +0300 > > description: > > Upstream: added variables support to proxy_cache and friends. > > Is there any reason why ngx_http_upstream_cache_get() isn't exported? > The reason is that it used only internally in the ngx_http_upstream_cache() function, which is static too. In fact, in my original version of patch the whole code was in ngx_http_upstream_cache() but Maxim insisted on moving it into a separate function just because the ngx_http_upstream_cache() is already bloated. wbr, Valentin V. Bartenev From mdounin at mdounin.ru Tue Dec 23 15:30:45 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 23 Dec 2014 15:30:45 +0000 Subject: [nginx] nginx-1.7.9-RELEASE Message-ID: details: http://hg.nginx.org/nginx/rev/34b201c1abd1 branches: changeset: 5952:34b201c1abd1 user: Maxim Dounin date: Tue Dec 23 18:28:37 2014 +0300 description: nginx-1.7.9-RELEASE diffstat: docs/xml/nginx/changes.xml | 104 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 104 insertions(+), 0 deletions(-) diffs (114 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -5,6 +5,110 @@ + + + + +????????? proxy_cache, fastcgi_cache, scgi_cache ? uwsgi_cache +???????????? ??????????. + + +variables support in the "proxy_cache", "fastcgi_cache", "scgi_cache", +and "uwsgi_cache" directives. + + + + + +????????? expires ???????????? ??????????. + + +variables support in the "expires" directive. + + + + + +??????????? ???????? ????????? ?????? ? ?????????? ????????? +? ??????? OpenSSL engines.
+??????? ??????? ????????. +
+ +loading of secret keys from hardware tokens +with OpenSSL engines.
+Thanks to Dmitrii Pichulin. +
+
+ + + +????????? autoindex_format. + + +the "autoindex_format" directive. + + + + + +??????????? ????????? ???? ?????? ???????????? ?????? ??? ??????? +? ?????? 200 ? 206.
+??????? Piotr Sikora. +
+ +cache revalidation is now only used for responses +with 200 and 206 status codes.
+Thanks to Piotr Sikora. +
+
+ + + +?????? "TE" ????????? ??????? ??????? ???????????? ?? ?????? ??? ?????????????. + + +the "TE" client request header line was passed to backends while proxying. + + + + + +????????? proxy_pass, fastcgi_pass, scgi_pass ? uwsgi_pass +????? ??????????? ???????? ?????? ?????? if ? limit_except. + + +the "proxy_pass", "fastcgi_pass", "scgi_pass", and "uwsgi_pass" directives +might not work correctly inside the "if" and "limit_except" blocks. + + + + + +????????? proxy_store ? ?????????? "on" ??????????????, +???? ?? ?????????? ?????? ?????????????? ????????? proxy_store +? ???? ???????? ????? ? ??????. + + +the "proxy_store" directive with the "on" parameter was ignored +if the "proxy_store" directive with an explicitly specified file path +was used on a previous level. + + + + + +nginx ?? ????????? ? BoringSSL.
+??????? Lukas Tribus. +
+ +nginx could not be built with BoringSSL.
+Thanks to Lukas Tribus. +
+
+ +
+ + From mdounin at mdounin.ru Tue Dec 23 15:30:48 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Tue, 23 Dec 2014 15:30:48 +0000 Subject: [nginx] release-1.7.9 tag Message-ID: details: http://hg.nginx.org/nginx/rev/1ce49d4e3883 branches: changeset: 5953:1ce49d4e3883 user: Maxim Dounin date: Tue Dec 23 18:28:38 2014 +0300 description: release-1.7.9 tag diffstat: .hgtags | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -378,3 +378,4 @@ fe129aa02db9001d220f1db7c3c056f79482c111 a8d111bb68847f61d682a3c8792fecb2e52efa2c release-1.7.6 6d2fbc30f8a7f70136cf08f32d5ff3179d524873 release-1.7.7 d5ea659b8bab2d6402a2266efa691f705e84001e release-1.7.8 +34b201c1abd1e2d4faeae4650a21574771a03c0e release-1.7.9 From wangxiaochen0 at gmail.com Wed Dec 24 02:10:48 2014 From: wangxiaochen0 at gmail.com (Xiaochen Wang) Date: Wed, 24 Dec 2014 10:10:48 +0800 Subject: Core: added signal name to "signal process started" logging In-Reply-To: <20141219172728.GW79300@mdounin.ru> References: <20141218040501.GB16247@gmail.com> <20141219172728.GW79300@mdounin.ru> Message-ID: On Sat, Dec 20, 2014 at 1:27 AM, Maxim Dounin wrote: > Hello! > > On Thu, Dec 18, 2014 at 12:05:01PM +0800, Xiaochen Wang wrote: > >> It is useful to know which signal was sent to nginx master when we analyzed >> error.log. If error_log level is warn/error/crit/alert/emerg, we could not >> know this information from nginx master/worker error log. > > Adding more logging into signal process won't help, as signal > process is not the only way to send signals to nginx. The main > purpose of signal process is to allow sending signals on Windows, > where there is no "kill" to do this. Yes, you're right. This patch can only get message in signal process. The signals sent from other process cannot be logged. > > -- > Maxim Dounin > http://nginx.org/ > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel From mdounin at mdounin.ru Wed Dec 24 16:03:59 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 24 Dec 2014 16:03:59 +0000 Subject: [nginx] Version bump. Message-ID: details: http://hg.nginx.org/nginx/rev/53499b86242e branches: changeset: 5954:53499b86242e user: Maxim Dounin date: Wed Dec 24 18:53:38 2014 +0300 description: Version bump. diffstat: src/core/nginx.h | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diffs (14 lines): diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1007009 -#define NGINX_VERSION "1.7.9" +#define nginx_version 1007010 +#define NGINX_VERSION "1.7.10" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD From mdounin at mdounin.ru Wed Dec 24 16:04:02 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 24 Dec 2014 16:04:02 +0000 Subject: [nginx] Fixed building with musl libc (ticket #685). Message-ID: details: http://hg.nginx.org/nginx/rev/fd6fd02f6a4d branches: changeset: 5955:fd6fd02f6a4d user: Maxim Dounin date: Wed Dec 24 19:01:22 2014 +0300 description: Fixed building with musl libc (ticket #685). diffstat: src/os/unix/ngx_user.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diffs (14 lines): diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c --- a/src/os/unix/ngx_user.c +++ b/src/os/unix/ngx_user.c @@ -31,8 +31,10 @@ ngx_libc_crypt(ngx_pool_t *pool, u_char struct crypt_data cd; cd.initialized = 0; +#ifdef __GLIBC__ /* work around the glibc bug */ cd.current_salt[0] = ~salt[0]; +#endif value = crypt_r((char *) key, (char *) salt, &cd); From mdounin at mdounin.ru Wed Dec 24 16:04:04 2014 From: mdounin at mdounin.ru (Maxim Dounin) Date: Wed, 24 Dec 2014 16:04:04 +0000 Subject: [nginx] Trailing space fix. Message-ID: details: http://hg.nginx.org/nginx/rev/4045818c726a branches: changeset: 5956:4045818c726a user: Maxim Dounin date: Wed Dec 24 19:02:58 2014 +0300 description: Trailing space fix. diffstat: docs/xml/nginx/changes.xml | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff --git a/docs/xml/nginx/changes.xml b/docs/xml/nginx/changes.xml --- a/docs/xml/nginx/changes.xml +++ b/docs/xml/nginx/changes.xml @@ -84,7 +84,7 @@ might not work correctly inside the "if" -????????? proxy_store ? ?????????? "on" ??????????????, +????????? proxy_store ? ?????????? "on" ??????????????, ???? ?? ?????????? ?????? ?????????????? ????????? proxy_store ? ???? ???????? ????? ? ??????. From sballal at instartlogic.com Thu Dec 25 04:04:16 2014 From: sballal at instartlogic.com (Shrirang Ballal) Date: Thu, 25 Dec 2014 09:34:16 +0530 Subject: [PATCH-REQUEST] : SPDY handling for 304 response Message-ID: 304 handling for non-spdy requests is exactly same as that of 204 handling (Reference : ngx_http_header_filter_module.c::ngx_http_header_filter()). SPDY requests too should be handled same way. Handle 204/304 response for SPDY requests in same way as the same way that are handled for non-SPDY requests --- .../src/http/ngx_http_spdy_filter_module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/service/proxy/nginx-1.6.2/src/http/ngx_http_spdy_filter_module.c b/service/proxy/nginx-1.6.2/src/http/ngx_http_spdy_filter_module.c index a31ad1f..8f975f5 100644 --- a/service/proxy/nginx-1.6.2/src/http/ngx_http_spdy_filter_module.c +++ b/service/proxy/nginx-1.6.2/src/http/ngx_http_spdy_filter_module.c @@ -147,10 +147,10 @@ ngx_http_spdy_header_filter(ngx_http_request_t *r) break; case NGX_HTTP_NOT_MODIFIED: - r->header_only = 1; - break; - case NGX_HTTP_NO_CONTENT: + /* take same action for "NGX_HTTP_NOT_MODIFIED" as that for + "NGX_HTTP_NO_CONTENT" */ r->header_only = 1; ngx_str_null(&r->headers_out.content_type); -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Thu Dec 25 14:34:13 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Thu, 25 Dec 2014 17:34:13 +0300 Subject: [PATCH-REQUEST] : SPDY handling for 304 response In-Reply-To: References: Message-ID: <101396952.BKIpRkdHMp@vbart-workstation> On Thursday 25 December 2014 09:34:16 Shrirang Ballal wrote: > 304 handling for non-spdy requests is exactly same as that of 204 handling > (Reference : ngx_http_header_filter_module.c::ngx_http_header_filter()). > SPDY requests too should be handled same way. [..] Well, they are not handled the same way. A quote from the function you mentioned: if (status >= NGX_HTTP_OK && status < NGX_HTTP_LAST_2XX) { /* 2XX */ if (status == NGX_HTTP_NO_CONTENT) { r->header_only = 1; ngx_str_null(&r->headers_out.content_type); r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; } status -= NGX_HTTP_OK; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_MOVED_PERMANENTLY && status < NGX_HTTP_LAST_3XX) { /* 3XX */ if (status == NGX_HTTP_NOT_MODIFIED) { r->header_only = 1; } status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } wbr, Valentin V. Bartenev From sballal at instartlogic.com Thu Dec 25 15:18:41 2014 From: sballal at instartlogic.com (Shrirang Ballal) Date: Thu, 25 Dec 2014 20:48:41 +0530 Subject: [PATCH-REQUEST] : SPDY handling for 304 response In-Reply-To: <101396952.BKIpRkdHMp@vbart-workstation> References: <101396952.BKIpRkdHMp@vbart-workstation> Message-ID: Hello Valentin, I understand that the "*complete*" handling of the 204 & 304 response is not same, but it is same for below mentioned response headers received by downstream client Quote for handling of "Content-Type", "Content-Length", "Last-Modified" header from ngx_http_header_filter_module.c::ngx_http_header_filter() /* clear out CL/CT header for header only 204/304 response earlier it was done only for 204/304 generated by nginx making it common for both paths - when nginx is serving the response and when the response is generated from the upstream */ if (r->headers_out.status == NGX_HTTP_NO_CONTENT || r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { r->header_only = 1; ngx_str_null(&r->headers_out.content_type); r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; } --- After this "*common*" handling for 204 & 304 responses, specific handling of 204/304 come in effect. I wanted to achieve this "*common*" handling through the patch I submitted. I think the patch is correct and should be incorporated. Without the patch, SPDY 304 responses will have "Content-Length", "Content-Type" header (which is not present in non-SPDY 304 response). Let me know if I am not being clear here. On Thu, Dec 25, 2014 at 8:04 PM, Valentin V. Bartenev wrote: > On Thursday 25 December 2014 09:34:16 Shrirang Ballal wrote: > > 304 handling for non-spdy requests is exactly same as that of 204 > handling > > (Reference : ngx_http_header_filter_module.c::ngx_http_header_filter()). > > SPDY requests too should be handled same way. > [..] > > Well, they are not handled the same way. > > A quote from the function you mentioned: > > if (status >= NGX_HTTP_OK > && status < NGX_HTTP_LAST_2XX) > { > /* 2XX */ > > if (status == NGX_HTTP_NO_CONTENT) { > r->header_only = 1; > ngx_str_null(&r->headers_out.content_type); > r->headers_out.last_modified_time = -1; > r->headers_out.last_modified = NULL; > r->headers_out.content_length = NULL; > r->headers_out.content_length_n = -1; > } > > status -= NGX_HTTP_OK; > status_line = &ngx_http_status_lines[status]; > len += ngx_http_status_lines[status].len; > > } else if (status >= NGX_HTTP_MOVED_PERMANENTLY > && status < NGX_HTTP_LAST_3XX) > { > /* 3XX */ > > if (status == NGX_HTTP_NOT_MODIFIED) { > r->header_only = 1; > } > > status = status - NGX_HTTP_MOVED_PERMANENTLY + > NGX_HTTP_OFF_3XX; > status_line = &ngx_http_status_lines[status]; > len += ngx_http_status_lines[status].len; > > } > > > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Thu Dec 25 15:30:02 2014 From: vbart at nginx.com (Valentin V. Bartenev) Date: Thu, 25 Dec 2014 18:30:02 +0300 Subject: [PATCH-REQUEST] : SPDY handling for 304 response In-Reply-To: References: <101396952.BKIpRkdHMp@vbart-workstation> Message-ID: <1657259.utDCMvviW4@vbart-workstation> On Thursday 25 December 2014 20:48:41 Shrirang Ballal wrote: > Hello Valentin, > > I understand that the "*complete*" handling of the 204 & 304 response is > not same, but it is same for below mentioned response headers received by > downstream client > > Quote for handling of "Content-Type", "Content-Length", "Last-Modified" > header from ngx_http_header_filter_module.c::ngx_http_header_filter() > /* clear out CL/CT header for header only 204/304 response > earlier it was done only for 204/304 generated by nginx > making it common for both paths - when nginx is serving the response > and when the response is generated from the upstream */ > if (r->headers_out.status == NGX_HTTP_NO_CONTENT > || r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { > r->header_only = 1; > ngx_str_null(&r->headers_out.content_type); > r->headers_out.last_modified_time = -1; > r->headers_out.last_modified = NULL; > r->headers_out.content_length = NULL; > r->headers_out.content_length_n = -1; > } > > --- Where have you found this code? It's not part of nginx. wbr, Valentin V. Bartenev From sballal at instartlogic.com Fri Dec 26 08:28:07 2014 From: sballal at instartlogic.com (Shrirang Ballal) Date: Fri, 26 Dec 2014 13:58:07 +0530 Subject: [PATCH-REQUEST] : SPDY handling for 304 response In-Reply-To: <1657259.utDCMvviW4@vbart-workstation> References: <101396952.BKIpRkdHMp@vbart-workstation> <1657259.utDCMvviW4@vbart-workstation> Message-ID: I am very sorry for bringing this up. This was a private change done in the private nginx that I was working on and I mistakenly thought that this piece of code was in standard nginx. I'll be more diligent next time onwards. On Thu, Dec 25, 2014 at 9:00 PM, Valentin V. Bartenev wrote: > On Thursday 25 December 2014 20:48:41 Shrirang Ballal wrote: > > Hello Valentin, > > > > I understand that the "*complete*" handling of the 204 & 304 response is > > not same, but it is same for below mentioned response headers received by > > downstream client > > > > Quote for handling of "Content-Type", "Content-Length", "Last-Modified" > > header from ngx_http_header_filter_module.c::ngx_http_header_filter() > > /* clear out CL/CT header for header only 204/304 response > > earlier it was done only for 204/304 generated by nginx > > making it common for both paths - when nginx is serving the > response > > and when the response is generated from the upstream */ > > if (r->headers_out.status == NGX_HTTP_NO_CONTENT > > || r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { > > r->header_only = 1; > > ngx_str_null(&r->headers_out.content_type); > > r->headers_out.last_modified_time = -1; > > r->headers_out.last_modified = NULL; > > r->headers_out.content_length = NULL; > > r->headers_out.content_length_n = -1; > > } > > > > --- > > Where have you found this code? It's not part of nginx. > > wbr, Valentin V. Bartenev > > _______________________________________________ > nginx-devel mailing list > nginx-devel at nginx.org > http://mailman.nginx.org/mailman/listinfo/nginx-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From vbart at nginx.com Fri Dec 26 13:23:53 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 26 Dec 2014 13:23:53 +0000 Subject: [nginx] Unified handling of ngx_create_temp_file() return value. Message-ID: details: http://hg.nginx.org/nginx/rev/570677a06dce branches: changeset: 5957:570677a06dce user: Valentin Bartenev date: Fri Dec 26 16:22:50 2014 +0300 description: Unified handling of ngx_create_temp_file() return value. The original check for NGX_AGAIN was surplus, since the function returns only NGX_OK or NGX_ERROR. Now it looks similar to other places. No functional changes. diffstat: src/core/ngx_file.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diffs (12 lines): diff -r 4045818c726a -r 570677a06dce src/core/ngx_file.c --- a/src/core/ngx_file.c Wed Dec 24 19:02:58 2014 +0300 +++ b/src/core/ngx_file.c Fri Dec 26 16:22:50 2014 +0300 @@ -114,7 +114,7 @@ ngx_write_chain_to_temp_file(ngx_temp_fi rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access); - if (rc == NGX_ERROR || rc == NGX_AGAIN) { + if (rc != NGX_OK) { return rc; } From vbart at nginx.com Fri Dec 26 13:23:56 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 26 Dec 2014 13:23:56 +0000 Subject: [nginx] Core: added prefix-based temporary files. Message-ID: details: http://hg.nginx.org/nginx/rev/a9138c35120d branches: changeset: 5958:a9138c35120d user: Valentin Bartenev date: Fri Dec 26 16:22:54 2014 +0300 description: Core: added prefix-based temporary files. Now, if the "path" parameter is NULL, ngx_create_temp_file() will use file->name as a predefined file path prefix. diffstat: src/core/ngx_file.c | 28 ++++++++++++++++++++-------- src/core/ngx_file.h | 1 + 2 files changed, 21 insertions(+), 8 deletions(-) diffs (83 lines): diff -r 570677a06dce -r a9138c35120d src/core/ngx_file.c --- a/src/core/ngx_file.c Fri Dec 26 16:22:50 2014 +0300 +++ b/src/core/ngx_file.c Fri Dec 26 16:22:54 2014 +0300 @@ -111,8 +111,9 @@ ngx_write_chain_to_temp_file(ngx_temp_fi ngx_int_t rc; if (tf->file.fd == NGX_INVALID_FILE) { - rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool, - tf->persistent, tf->clean, tf->access); + rc = ngx_create_temp_file(&tf->file, tf->prefix ? NULL : tf->path, + tf->pool, tf->persistent, tf->clean, + tf->access); if (rc != NGX_OK) { return rc; @@ -132,12 +133,15 @@ ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean, ngx_uint_t access) { + u_char *p; uint32_t n; ngx_err_t err; + ngx_str_t prefix; ngx_pool_cleanup_t *cln; ngx_pool_cleanup_file_t *clnf; - file->name.len = path->name.len + 1 + path->len + 10; + prefix = path ? path->name : file->name; + file->name.len = prefix.len + 1 + (path ? path->len : 0) + 10; file->name.data = ngx_pnalloc(pool, file->name.len + 1); if (file->name.data == NULL) { @@ -150,7 +154,14 @@ ngx_create_temp_file(ngx_file_t *file, n } #endif - ngx_memcpy(file->name.data, path->name.data, path->name.len); + p = ngx_cpymem(file->name.data, prefix.data, prefix.len); + + if (path) { + p += 1 + path->len; + + } else { + *p++ = '.'; + } n = (uint32_t) ngx_next_temp_number(0); @@ -160,10 +171,11 @@ ngx_create_temp_file(ngx_file_t *file, n } for ( ;; ) { - (void) ngx_sprintf(file->name.data + path->name.len + 1 + path->len, - "%010uD%Z", n); + (void) ngx_sprintf(p, "%010uD%Z", n); - ngx_create_hashed_filename(path, file->name.data, file->name.len); + if (path) { + ngx_create_hashed_filename(path, file->name.data, file->name.len); + } ngx_log_debug1(NGX_LOG_DEBUG_CORE, file->log, 0, "hashed path: %s", file->name.data); @@ -192,7 +204,7 @@ ngx_create_temp_file(ngx_file_t *file, n continue; } - if ((path->level[0] == 0) || (err != NGX_ENOPATH)) { + if ((path == NULL) || (path->level[0] == 0) || (err != NGX_ENOPATH)) { ngx_log_error(NGX_LOG_CRIT, file->log, err, ngx_open_tempfile_n " \"%s\" failed", file->name.data); diff -r 570677a06dce -r a9138c35120d src/core/ngx_file.h --- a/src/core/ngx_file.h Fri Dec 26 16:22:50 2014 +0300 +++ b/src/core/ngx_file.h Fri Dec 26 16:22:54 2014 +0300 @@ -71,6 +71,7 @@ typedef struct { unsigned log_level:8; unsigned persistent:1; unsigned clean:1; + unsigned prefix:1; } ngx_temp_file_t; From vbart at nginx.com Fri Dec 26 13:23:59 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 26 Dec 2014 13:23:59 +0000 Subject: [nginx] Cache: update variant while setting header. Message-ID: details: http://hg.nginx.org/nginx/rev/f7584d7c0ccb branches: changeset: 5959:f7584d7c0ccb user: Valentin Bartenev date: Fri Dec 26 16:22:56 2014 +0300 description: Cache: update variant while setting header. Some parts of code related to handling variants of a resource moved into a separate function that is called earlier. This allows to use cache file name as a prefix for temporary file in the following patch. diffstat: src/http/ngx_http_cache.h | 2 +- src/http/ngx_http_file_cache.c | 94 +++++++++++++++++++++++++---------------- src/http/ngx_http_upstream.c | 5 +- 3 files changed, 63 insertions(+), 38 deletions(-) diffs (159 lines): diff -r a9138c35120d -r f7584d7c0ccb src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h Fri Dec 26 16:22:54 2014 +0300 +++ b/src/http/ngx_http_cache.h Fri Dec 26 16:22:56 2014 +0300 @@ -162,7 +162,7 @@ ngx_int_t ngx_http_file_cache_new(ngx_ht ngx_int_t ngx_http_file_cache_create(ngx_http_request_t *r); void ngx_http_file_cache_create_key(ngx_http_request_t *r); ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r); -void ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf); +ngx_int_t ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf); void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf); void ngx_http_file_cache_update_header(ngx_http_request_t *r); ngx_int_t ngx_http_cache_send(ngx_http_request_t *); diff -r a9138c35120d -r f7584d7c0ccb src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c Fri Dec 26 16:22:54 2014 +0300 +++ b/src/http/ngx_http_file_cache.c Fri Dec 26 16:22:56 2014 +0300 @@ -37,6 +37,8 @@ static void ngx_http_file_cache_vary_hea ngx_md5_t *md5, ngx_str_t *name); static ngx_int_t ngx_http_file_cache_reopen(ngx_http_request_t *r, ngx_http_cache_t *c); +static ngx_int_t ngx_http_file_cache_update_variant(ngx_http_request_t *r, + ngx_http_cache_t *c); static void ngx_http_file_cache_cleanup(void *data); static time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache); static time_t ngx_http_file_cache_expire(ngx_http_file_cache_t *cache); @@ -1122,7 +1124,7 @@ ngx_http_file_cache_reopen(ngx_http_requ } -void +ngx_int_t ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) { ngx_http_file_cache_header_t *h = (ngx_http_file_cache_header_t *) buf; @@ -1164,9 +1166,10 @@ ngx_http_file_cache_set_header(ngx_http_ ngx_http_file_cache_vary(r, c->vary.data, c->vary.len, c->variant); ngx_memcpy(h->variant, c->variant, NGX_HTTP_CACHE_KEY_LEN); - - } else { - ngx_memzero(c->variant, NGX_HTTP_CACHE_KEY_LEN); + } + + if (ngx_http_file_cache_update_variant(r, c) != NGX_OK) { + return NGX_ERROR; } p = buf + sizeof(ngx_http_file_cache_header_t); @@ -1179,6 +1182,57 @@ ngx_http_file_cache_set_header(ngx_http_ } *p = LF; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_file_cache_update_variant(ngx_http_request_t *r, ngx_http_cache_t *c) +{ + ngx_http_file_cache_t *cache; + + if (!c->secondary) { + return NGX_OK; + } + + if (c->vary.len + && ngx_memcmp(c->variant, c->key, NGX_HTTP_CACHE_KEY_LEN) == 0) + { + return NGX_OK; + } + + /* + * if the variant hash doesn't match one we used as a secondary + * cache key, switch back to the original key + */ + + cache = c->file_cache; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache main key"); + + ngx_shmtx_lock(&cache->shpool->mutex); + + c->node->count--; + c->node->updating = 0; + c->node = NULL; + + ngx_shmtx_unlock(&cache->shpool->mutex); + + c->file.name.len = 0; + + ngx_memcpy(c->key, c->main, NGX_HTTP_CACHE_KEY_LEN); + + if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; } @@ -1204,38 +1258,6 @@ ngx_http_file_cache_update(ngx_http_requ cache = c->file_cache; - if (c->secondary - && ngx_memcmp(c->variant, c->key, NGX_HTTP_CACHE_KEY_LEN) != 0) - { - /* - * if the variant hash doesn't match one we used as a secondary - * cache key, switch back to the original key - */ - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http file cache main key"); - - ngx_shmtx_lock(&cache->shpool->mutex); - - c->node->count--; - c->node->updating = 0; - c->node = NULL; - - ngx_shmtx_unlock(&cache->shpool->mutex); - - c->file.name.len = 0; - - ngx_memcpy(c->key, c->main, NGX_HTTP_CACHE_KEY_LEN); - - if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) { - return; - } - - if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) { - return; - } - } - c->updated = 1; c->updating = 0; diff -r a9138c35120d -r f7584d7c0ccb src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Fri Dec 26 16:22:54 2014 +0300 +++ b/src/http/ngx_http_upstream.c Fri Dec 26 16:22:56 2014 +0300 @@ -2628,7 +2628,10 @@ ngx_http_upstream_send_response(ngx_http } } - ngx_http_file_cache_set_header(r, u->buffer.start); + if (ngx_http_file_cache_set_header(r, u->buffer.start) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } } else { u->cacheable = 0; From vbart at nginx.com Fri Dec 26 13:24:01 2014 From: vbart at nginx.com (Valentin Bartenev) Date: Fri, 26 Dec 2014 13:24:01 +0000 Subject: [nginx] Upstream: use_temp_path parameter of proxy_cache_path an... Message-ID: details: http://hg.nginx.org/nginx/rev/e9effef98874 branches: changeset: 5960:e9effef98874 user: Valentin Bartenev date: Fri Dec 26 16:22:59 2014 +0300 description: Upstream: use_temp_path parameter of proxy_cache_path and friends. When set to "off", temporary files for cacheable responses will be stored inside cache directory. diffstat: src/http/ngx_http_cache.h | 3 +++ src/http/ngx_http_file_cache.c | 36 +++++++++++++++++++++++++++++++++++- src/http/ngx_http_upstream.c | 8 ++++++++ 3 files changed, 46 insertions(+), 1 deletions(-) diffs (105 lines): diff -r f7584d7c0ccb -r e9effef98874 src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h Fri Dec 26 16:22:56 2014 +0300 +++ b/src/http/ngx_http_cache.h Fri Dec 26 16:22:59 2014 +0300 @@ -155,6 +155,9 @@ struct ngx_http_file_cache_s { ngx_msec_t loader_threshold; ngx_shm_zone_t *shm_zone; + + ngx_uint_t use_temp_path; + /* unsigned use_temp_path:1 */ }; diff -r f7584d7c0ccb -r e9effef98874 src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c Fri Dec 26 16:22:56 2014 +0300 +++ b/src/http/ngx_http_file_cache.c Fri Dec 26 16:22:59 2014 +0300 @@ -1935,6 +1935,17 @@ ngx_http_file_cache_add_file(ngx_tree_ct return NGX_ERROR; } + /* + * Temporary files in cache have a suffix consisting of a dot + * followed by 10 digits. + */ + + if (name->len >= 2 * NGX_HTTP_CACHE_KEY_LEN + 1 + 10 + && name->data[name->len - 10 - 1] == '.') + { + return NGX_OK; + } + if (ctx->size < (off_t) sizeof(ngx_http_file_cache_header_t)) { ngx_log_error(NGX_LOG_CRIT, ctx->log, 0, "cache file \"%s\" is too small", name->data); @@ -2063,7 +2074,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t ngx_str_t s, name, *value; ngx_int_t loader_files; ngx_msec_t loader_sleep, loader_threshold; - ngx_uint_t i, n; + ngx_uint_t i, n, use_temp_path; ngx_array_t *caches; ngx_http_file_cache_t *cache, **ce; @@ -2077,6 +2088,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t return NGX_CONF_ERROR; } + use_temp_path = 1; + inactive = 600; loader_files = 100; loader_sleep = 50; @@ -2137,6 +2150,25 @@ ngx_http_file_cache_set_slot(ngx_conf_t return NGX_CONF_ERROR; } + if (ngx_strncmp(value[i].data, "use_temp_path=", 14) == 0) { + + if (ngx_strcmp(&value[i].data[14], "on") == 0) { + use_temp_path = 1; + + } else if (ngx_strcmp(&value[i].data[14], "off") == 0) { + use_temp_path = 0; + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid use_temp_path value \"%V\", " + "it must be \"on\" or \"off\"", + &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strncmp(value[i].data, "keys_zone=", 10) == 0) { name.data = value[i].data + 10; @@ -2274,6 +2306,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t cache->shm_zone->init = ngx_http_file_cache_init; cache->shm_zone->data = cache; + cache->use_temp_path = use_temp_path; + cache->inactive = inactive; cache->max_size = max_size; diff -r f7584d7c0ccb -r e9effef98874 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c Fri Dec 26 16:22:56 2014 +0300 +++ b/src/http/ngx_http_upstream.c Fri Dec 26 16:22:59 2014 +0300 @@ -2677,6 +2677,14 @@ ngx_http_upstream_send_response(ngx_http if (p->cacheable) { p->temp_file->persistent = 1; +#if (NGX_HTTP_CACHE) + if (r->cache && !r->cache->file_cache->use_temp_path) { + p->temp_file->file.name = r->cache->file.name; + p->temp_file->path = r->cache->file_cache->path; + p->temp_file->prefix = 1; + } +#endif + } else { p->temp_file->log_level = NGX_LOG_WARN; p->temp_file->warn = "an upstream response is buffered "