[PATCH 13 of 14] Proxy: add "proxy_pass_trailers" directive
Piotr Sikora
piotrsikora at google.com
Thu Jun 22 20:33:17 UTC 2017
# HG changeset patch
# User Piotr Sikora <piotrsikora at 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 <piotrsikora at 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;
More information about the nginx-devel
mailing list