# HG changeset patch # User Piotr Sikora <piotrsik...@google.com> # Date 1490351854 25200 # Fri Mar 24 03:37:34 2017 -0700 # Node ID cde1f42da7b26b7d2b788f916685e736b919138e # Parent 7eb807b056da7abe9c679b59e94595d59a1406e6 Proxy: add "proxy_pass_trailers" directive.
Signed-off-by: Piotr Sikora <piotrsik...@google.com> diff -r 7eb807b056da -r cde1f42da7b2 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 @@ -2788,10 +2788,10 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.intercept_errors = NGX_CONF_UNSET; - /* "fastcgi_cyclic_temp_file" is disabled */ + /* the hardcoded values */ conf->upstream.cyclic_temp_file = 0; - conf->upstream.change_buffering = 1; + conf->upstream.pass_trailers = 0; conf->catch_stderr = NGX_CONF_UNSET_PTR; diff -r 7eb807b056da -r cde1f42da7b2 src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -619,6 +619,7 @@ ngx_http_memcached_create_loc_conf(ngx_c conf->upstream.pass_request_headers = 0; conf->upstream.pass_request_body = 0; conf->upstream.force_ranges = 1; + conf->upstream.pass_trailers = 0; conf->index = NGX_CONF_UNSET; conf->gzip_flag = NGX_CONF_UNSET_UINT; diff -r 7eb807b056da -r cde1f42da7b2 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 @@ -630,6 +630,13 @@ static ngx_command_t ngx_http_proxy_com offsetof(ngx_http_proxy_loc_conf_t, upstream.ignore_headers), &ngx_http_upstream_ignore_headers_masks }, + { ngx_string("proxy_pass_trailers"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.pass_trailers), + NULL }, + { ngx_string("proxy_http_version"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_enum_slot, @@ -3483,6 +3490,8 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.hide_headers = NGX_CONF_UNSET_PTR; conf->upstream.pass_headers = NGX_CONF_UNSET_PTR; + conf->upstream.pass_trailers = NGX_CONF_UNSET; + conf->upstream.intercept_errors = NGX_CONF_UNSET; #if (NGX_HTTP_SSL) @@ -3494,11 +3503,11 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->ssl_passwords = NGX_CONF_UNSET_PTR; #endif - /* "proxy_cyclic_temp_file" is disabled */ + /* the hardcoded values */ conf->upstream.cyclic_temp_file = 0; + conf->upstream.change_buffering = 1; conf->redirect = NGX_CONF_UNSET; - conf->upstream.change_buffering = 1; conf->cookie_domains = NGX_CONF_UNSET_PTR; conf->cookie_paths = NGX_CONF_UNSET_PTR; @@ -3798,6 +3807,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_value(conf->upstream.pass_request_body, prev->upstream.pass_request_body, 1); + ngx_conf_merge_value(conf->upstream.pass_trailers, + prev->upstream.pass_trailers, 0); + ngx_conf_merge_value(conf->upstream.intercept_errors, prev->upstream.intercept_errors, 0); @@ -4018,6 +4030,28 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t #endif } + if (conf->upstream.pass_trailers) { + + if (conf->http_version != NGX_HTTP_VERSION_20) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_pass_trailers\" requires " + "\"proxy_http_version 2.0\""); + return NGX_CONF_ERROR; + } + +#if (NGX_HTTP_CACHE) + + if (conf->upstream.cache) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_pass_trailers\" doesn't work with " + "\"proxy_cache\""); + return NGX_CONF_ERROR; + } + +#endif + + } + return NGX_CONF_OK; } diff -r 7eb807b056da -r cde1f42da7b2 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 @@ -1236,10 +1236,10 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t conf->upstream.intercept_errors = NGX_CONF_UNSET; - /* "scgi_cyclic_temp_file" is disabled */ + /* the hardcoded values */ conf->upstream.cyclic_temp_file = 0; - conf->upstream.change_buffering = 1; + conf->upstream.pass_trailers = 0; ngx_str_set(&conf->upstream.module, "scgi"); diff -r 7eb807b056da -r cde1f42da7b2 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 @@ -1451,10 +1451,10 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->ssl_passwords = NGX_CONF_UNSET_PTR; #endif - /* "uwsgi_cyclic_temp_file" is disabled */ + /* the hardcoded values */ conf->upstream.cyclic_temp_file = 0; - conf->upstream.change_buffering = 1; + conf->upstream.pass_trailers = 0; ngx_str_set(&conf->upstream.module, "uwsgi"); diff -r 7eb807b056da -r cde1f42da7b2 src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -56,6 +56,8 @@ static ngx_int_t ngx_http_upstream_test_ ngx_connection_t *c); static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r, ngx_http_upstream_t *u); +static ngx_int_t ngx_http_upstream_process_trailers(ngx_http_request_t *r, + ngx_http_upstream_t *u); static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, ngx_http_upstream_t *u); static void ngx_http_upstream_send_response(ngx_http_request_t *r, @@ -150,6 +152,8 @@ static ngx_int_t ngx_http_upstream_rewri ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_upstream_copy_trailer(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); #if (NGX_HTTP_GZIP) static ngx_int_t ngx_http_upstream_copy_content_encoding(ngx_http_request_t *r, @@ -167,6 +171,8 @@ static ngx_int_t ngx_http_upstream_respo ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_upstream_trailer_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -313,6 +319,10 @@ static ngx_http_upstream_header_t ngx_h ngx_http_upstream_process_charset, 0, ngx_http_upstream_copy_header_line, 0, 0 }, + { ngx_string("Trailer"), + ngx_http_upstream_ignore_header_line, 0, + ngx_http_upstream_copy_trailer, 0, 0 }, + { ngx_string("Transfer-Encoding"), ngx_http_upstream_process_transfer_encoding, 0, ngx_http_upstream_ignore_header_line, 0, 0 }, @@ -428,6 +438,9 @@ static ngx_http_variable_t ngx_http_ups { ngx_string("upstream_http_"), NULL, ngx_http_upstream_header_variable, 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, + { ngx_string("upstream_trailer_"), NULL, ngx_http_upstream_trailer_variable, + 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, + { ngx_string("upstream_cookie_"), NULL, ngx_http_upstream_cookie_variable, 0, NGX_HTTP_VAR_NOCACHEABLE|NGX_HTTP_VAR_PREFIX, 0 }, @@ -1048,6 +1061,13 @@ ngx_http_upstream_cache_send(ngx_http_re return NGX_ERROR; } + if (ngx_list_init(&u->headers_in.trailers, r->pool, 2, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + return NGX_ERROR; + } + rc = u->process_header(r); if (rc == NGX_OK) { @@ -1942,6 +1962,13 @@ ngx_http_upstream_reinit(ngx_http_reques return NGX_ERROR; } + if (ngx_list_init(&u->headers_in.trailers, r->pool, 2, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + return NGX_ERROR; + } + /* reinit the request chain */ file_pos = 0; @@ -2329,6 +2356,15 @@ ngx_http_upstream_process_header(ngx_htt return; } + if (ngx_list_init(&u->headers_in.trailers, r->pool, 2, + sizeof(ngx_table_elt_t)) + != NGX_OK) + { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + #if (NGX_HTTP_CACHE) if (r->cache) { @@ -2880,6 +2916,45 @@ ngx_http_upstream_process_headers(ngx_ht } +static ngx_int_t +ngx_http_upstream_process_trailers(ngx_http_request_t *r, + ngx_http_upstream_t *u) +{ + ngx_uint_t i; + ngx_list_part_t *part; + ngx_table_elt_t *h, *ho; + + if (!r->expect_trailers || !u->conf->pass_trailers) { + return NGX_OK; + } + + part = &u->headers_in.trailers.part; + h = part->elts; + + for (i = 0; /* void */; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + + part = part->next; + h = part->elts; + i = 0; + } + + ho = ngx_list_push(&r->headers_out.trailers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = h[i]; + } + + return NGX_OK; +} + + static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r, ngx_http_upstream_t *u) @@ -4491,6 +4566,13 @@ ngx_http_upstream_finalize_request(ngx_h } if (rc == 0) { + if (ngx_http_upstream_process_trailers(r, u) != NGX_OK) { + rc = NGX_ERROR; + flush = 1; + } + } + + if (rc == 0) { rc = ngx_http_send_special(r, NGX_HTTP_LAST); } else if (flush) { @@ -5277,6 +5359,27 @@ ngx_http_upstream_copy_allow_ranges(ngx_ } +static ngx_int_t +ngx_http_upstream_copy_trailer(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset) +{ + ngx_table_elt_t *ho; + + if (!r->expect_trailers || !r->upstream->conf->pass_trailers) { + return NGX_OK; + } + + ho = ngx_list_push(&r->headers_out.headers); + if (ho == NULL) { + return NGX_ERROR; + } + + *ho = *h; + + return NGX_OK; +} + + #if (NGX_HTTP_GZIP) static ngx_int_t @@ -5615,6 +5718,21 @@ ngx_http_upstream_header_variable(ngx_ht static ngx_int_t +ngx_http_upstream_trailer_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->upstream == NULL) { + v->not_found = 1; + return NGX_OK; + } + + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->upstream->headers_in.trailers.part, + sizeof("upstream_trailer_") - 1); +} + + +static ngx_int_t ngx_http_upstream_cookie_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { diff -r 7eb807b056da -r cde1f42da7b2 src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -174,6 +174,7 @@ typedef struct { ngx_flag_t request_buffering; ngx_flag_t pass_request_headers; ngx_flag_t pass_request_body; + ngx_flag_t pass_trailers; ngx_flag_t ignore_client_abort; ngx_flag_t intercept_errors; @@ -251,6 +252,7 @@ typedef struct { typedef struct { ngx_list_t headers; + ngx_list_t trailers; ngx_uint_t status_n; ngx_str_t status_line; _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel