Merge upstream version of HTTP trailers.
Commits upstream:
- http://hg.nginx.org/nginx/rev/1b068a4e82d8
- http://hg.nginx.org/nginx/rev/4e784e095a97
- http://hg.nginx.org/nginx/rev/8666da1ecf33
Notable difference between this and previously committed patches
is lack of the requirement for "TE: trailers" header in requests.
Change-Id: Ib0a2a4b53966bc012373442d933c960e27f3d7fb
Signed-off-by: Piotr Sikora <piotrsikora@google.com>
Reviewed-on: https://nginx-review.googlesource.com/3040
Reviewed-by: Lizan Zhou <zlizan@google.com>
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index ffa1dd2..4d6fd3e 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -17,7 +17,8 @@
static ngx_int_t ngx_http_chunked_filter_init(ngx_conf_t *cf);
-static ngx_chain_t *ngx_http_chunked_get_trailers(ngx_http_request_t *r);
+static ngx_chain_t *ngx_http_chunked_create_trailers(ngx_http_request_t *r,
+ ngx_http_chunked_filter_ctx_t *ctx);
static ngx_http_module_t ngx_http_chunked_filter_module_ctx = {
@@ -70,35 +71,32 @@
return ngx_http_next_header_filter(r);
}
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (clcf->chunked_transfer_encoding
- && r->allow_trailers && r->expect_trailers)
+ if (r->headers_out.content_length_n == -1
+ || r->expect_trailers)
{
- ngx_http_clear_content_length(r);
- r->chunked = 1;
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
- } else if (r->headers_out.content_length_n == -1) {
- if (r->http_version < NGX_HTTP_VERSION_11) {
- r->keepalive = 0;
+ if (r->http_version >= NGX_HTTP_VERSION_11
+ && clcf->chunked_transfer_encoding)
+ {
+ if (r->expect_trailers) {
+ ngx_http_clear_content_length(r);
+ }
- } else if (clcf->chunked_transfer_encoding) {
r->chunked = 1;
- } else {
+ ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_filter_ctx_t));
+ if (ctx == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module);
+
+ } else if (r->headers_out.content_length_n == -1) {
r->keepalive = 0;
}
}
- if (r->chunked) {
- ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_filter_ctx_t));
- if (ctx == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_set_ctx(r, ctx, ngx_http_chunked_filter_module);
- }
-
return ngx_http_next_header_filter(r);
}
@@ -185,35 +183,17 @@
}
if (cl->buf->last_buf) {
- tl = ngx_chain_get_free_buf(r->pool, &ctx->free);
+ tl = ngx_http_chunked_create_trailers(r, ctx);
if (tl == NULL) {
return NGX_ERROR;
}
- b = tl->buf;
-
- b->tag = (ngx_buf_tag_t) &ngx_http_chunked_filter_module;
- b->temporary = 0;
- b->memory = 1;
- b->last_buf = 1;
- b->pos = (u_char *) CRLF "0" CRLF CRLF;
- b->last = b->pos + 7;
-
cl->buf->last_buf = 0;
*ll = tl;
if (size == 0) {
- b->pos += 2;
- }
-
- if (r->allow_trailers && r->expect_trailers) {
- tl->next = ngx_http_chunked_get_trailers(r);
-
- if (tl->next != NULL) {
- b->last -= 2;
- b->last_buf = 0;
- }
+ tl->buf->pos += 2;
}
} else if (size > 0) {
@@ -246,19 +226,15 @@
static ngx_chain_t *
-ngx_http_chunked_get_trailers(ngx_http_request_t *r)
+ngx_http_chunked_create_trailers(ngx_http_request_t *r,
+ ngx_http_chunked_filter_ctx_t *ctx)
{
- size_t len;
- ngx_buf_t *b;
- ngx_uint_t i;
- ngx_chain_t *cl;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_chunked_filter_ctx_t *ctx;
-
- if (ngx_http_eval_trailers(r) != NGX_OK) {
- return NULL;
- }
+ size_t len;
+ ngx_buf_t *b;
+ ngx_uint_t i;
+ ngx_chain_t *cl;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *header;
len = 0;
@@ -281,18 +257,10 @@
continue;
}
- len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len
- + sizeof(CRLF) - 1;
+ len += header[i].key.len + sizeof(": ") - 1
+ + header[i].value.len + sizeof(CRLF) - 1;
}
- if (len == 0) {
- return NULL;
- }
-
- len += sizeof(CRLF) - 1;
-
- ctx = ngx_http_get_module_ctx(r, ngx_http_chunked_filter_module);
-
cl = ngx_chain_get_free_buf(r->pool, &ctx->free);
if (cl == NULL) {
return NULL;
@@ -305,14 +273,24 @@
b->memory = 1;
b->last_buf = 1;
- b->start = ngx_palloc(r->pool, len);
- if (b->start == NULL) {
+ if (len == 0) {
+ b->pos = (u_char *) CRLF "0" CRLF CRLF;
+ b->last = b->pos + sizeof(CRLF "0" CRLF CRLF) - 1;
+ return cl;
+ }
+
+ len += sizeof(CRLF "0" CRLF CRLF) - 1;
+
+ b->pos = ngx_palloc(r->pool, len);
+ if (b->pos == NULL) {
return NULL;
}
- b->end = b->last + len;
- b->pos = b->start;
- b->last = b->start;
+ b->last = b->pos;
+
+ *b->last++ = CR; *b->last++ = LF;
+ *b->last++ = '0';
+ *b->last++ = CR; *b->last++ = LF;
part = &r->headers_out.trailers.part;
header = part->elts;
@@ -344,7 +322,6 @@
*b->last++ = CR; *b->last++ = LF;
}
- /* the end of HTTP trailer */
*b->last++ = CR; *b->last++ = LF;
return cl;
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 47ce779..29e2787 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -73,8 +73,6 @@
void *conf);
static char *ngx_http_headers_add(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
-static char *ngx_http_headers_add_trailer(ngx_conf_t *cf, ngx_command_t *cmd,
- void *conf);
static ngx_http_set_header_t ngx_http_set_headers[] = {
@@ -108,16 +106,16 @@
|NGX_CONF_TAKE23,
ngx_http_headers_add,
NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL},
+ offsetof(ngx_http_headers_conf_t, headers),
+ NULL },
{ ngx_string("add_trailer"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
|NGX_CONF_TAKE23,
- ngx_http_headers_add_trailer,
+ ngx_http_headers_add,
NGX_HTTP_LOC_CONF_OFFSET,
- 0,
- NULL},
+ offsetof(ngx_http_headers_conf_t, trailers),
+ NULL },
ngx_null_command
};
@@ -155,19 +153,16 @@
static ngx_http_output_header_filter_pt ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static ngx_int_t
ngx_http_headers_filter(ngx_http_request_t *r)
{
- u_char *p, *data;
- size_t len;
- ngx_str_t value;
- ngx_uint_t i, safe_status;
- ngx_table_elt_t *t;
- ngx_http_header_val_t *h;
- ngx_http_headers_conf_t *conf;
- ngx_http_core_loc_conf_t *clcf;
+ ngx_str_t value;
+ ngx_uint_t i, safe_status;
+ ngx_http_header_val_t *h;
+ ngx_http_headers_conf_t *conf;
if (r != r->main) {
return ngx_http_next_header_filter(r);
@@ -176,8 +171,8 @@
conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
if (conf->expires == NGX_HTTP_EXPIRES_OFF
- && conf->headers == NULL
- && conf->trailers == NULL)
+ && conf->headers == NULL
+ && conf->trailers == NULL)
{
return ngx_http_next_header_filter(r);
}
@@ -226,27 +221,7 @@
}
}
- if (conf->trailers && r->allow_trailers) {
-
- if (r->http_version < NGX_HTTP_VERSION_20) {
- if (r->header_only
- || r->headers_out.status == NGX_HTTP_NOT_MODIFIED
- || r->headers_out.status == NGX_HTTP_NO_CONTENT
- || r->headers_out.status < NGX_HTTP_OK
- || r->method == NGX_HTTP_HEAD)
- {
- return ngx_http_next_header_filter(r);
- }
-
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
- if (!clcf->chunked_transfer_encoding) {
- return ngx_http_next_header_filter(r);
- }
- }
-
- len = 0;
-
+ if (conf->trailers) {
h = conf->trailers->elts;
for (i = 0; i < conf->trailers->nelts; i++) {
@@ -254,54 +229,9 @@
continue;
}
- if (h[i].value.value.len) {
- len += h[i].key.len + sizeof(", ") - 1;
- }
+ r->expect_trailers = 1;
+ break;
}
-
- if (len == 0) {
- return ngx_http_next_header_filter(r);
- }
-
- len -= sizeof(", ") - 1;
-
- t = ngx_list_push(&r->headers_out.headers);
- if (t == NULL) {
- return NGX_ERROR;
- }
-
- data = ngx_pnalloc(r->pool, len);
- if (data == NULL) {
- return NGX_ERROR;
- }
-
- p = data;
-
- h = conf->trailers->elts;
- for (i = 0; i < conf->trailers->nelts; i++) {
-
- if (!safe_status && !h[i].always) {
- continue;
- }
-
- if (h[i].value.value.len) {
- p = ngx_copy(p, h[i].key.data, h[i].key.len);
-
- if (p == data + len) {
- break;
- }
-
- *p++ = ','; *p++ = ' ';
- }
- }
-
- ngx_str_set(&t->key, "Trailer");
- t->value.data = data;
- t->value.len = len;
- t->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(
- ngx_hash('t', 'r'), 'a'), 'i'), 'l'), 'e'), 'r');
-
- r->expect_trailers = 1;
}
return ngx_http_next_header_filter(r);
@@ -309,6 +239,83 @@
static ngx_int_t
+ngx_http_trailers_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+ ngx_str_t value;
+ ngx_uint_t i, safe_status;
+ ngx_chain_t *cl;
+ ngx_table_elt_t *t;
+ ngx_http_header_val_t *h;
+ ngx_http_headers_conf_t *conf;
+
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
+
+ if (in == NULL
+ || conf->trailers == NULL
+ || !r->expect_trailers
+ || r->header_only)
+ {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ for (cl = in; cl; cl = cl->next) {
+ if (cl->buf->last_buf) {
+ break;
+ }
+ }
+
+ if (cl == NULL) {
+ return ngx_http_next_body_filter(r, in);
+ }
+
+ switch (r->headers_out.status) {
+
+ case NGX_HTTP_OK:
+ case NGX_HTTP_CREATED:
+ case NGX_HTTP_NO_CONTENT:
+ case NGX_HTTP_PARTIAL_CONTENT:
+ case NGX_HTTP_MOVED_PERMANENTLY:
+ case NGX_HTTP_MOVED_TEMPORARILY:
+ case NGX_HTTP_SEE_OTHER:
+ case NGX_HTTP_NOT_MODIFIED:
+ case NGX_HTTP_TEMPORARY_REDIRECT:
+ case NGX_HTTP_PERMANENT_REDIRECT:
+ safe_status = 1;
+ break;
+
+ default:
+ safe_status = 0;
+ break;
+ }
+
+ h = conf->trailers->elts;
+ for (i = 0; i < conf->trailers->nelts; i++) {
+
+ if (!safe_status && !h[i].always) {
+ continue;
+ }
+
+ if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (value.len) {
+ t = ngx_list_push(&r->headers_out.trailers);
+ if (t == NULL) {
+ return NGX_ERROR;
+ }
+
+ t->key = h[i].key;
+ t->value = value;
+ t->hash = 1;
+ }
+ }
+
+ return ngx_http_next_body_filter(r, in);
+}
+
+
+static ngx_int_t
ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf)
{
char *err;
@@ -641,67 +648,6 @@
}
-ngx_int_t
-ngx_http_eval_trailers(ngx_http_request_t *r)
-{
- ngx_str_t value;
- ngx_uint_t i, safe_status;
- ngx_table_elt_t *t;
- ngx_http_header_val_t *h;
- ngx_http_headers_conf_t *conf;
-
- conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
-
- if (conf->trailers == NULL) {
- return NGX_OK;
- }
-
- switch (r->headers_out.status) {
-
- case NGX_HTTP_OK:
- case NGX_HTTP_CREATED:
- case NGX_HTTP_NO_CONTENT:
- case NGX_HTTP_PARTIAL_CONTENT:
- case NGX_HTTP_MOVED_PERMANENTLY:
- case NGX_HTTP_MOVED_TEMPORARILY:
- case NGX_HTTP_SEE_OTHER:
- case NGX_HTTP_NOT_MODIFIED:
- case NGX_HTTP_TEMPORARY_REDIRECT:
- safe_status = 1;
- break;
-
- default:
- safe_status = 0;
- break;
- }
-
- h = conf->trailers->elts;
- for (i = 0; i < conf->trailers->nelts; i++) {
-
- if (!safe_status && !h[i].always) {
- continue;
- }
-
- if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (value.len) {
- t = ngx_list_push(&r->headers_out.trailers);
- if (t == NULL) {
- return NGX_ERROR;
- }
-
- t->key = h[i].key;
- t->value = value;
- t->hash = 1;
- }
- }
-
- return NGX_OK;
-}
-
-
static void *
ngx_http_headers_create_conf(ngx_conf_t *cf)
{
@@ -761,6 +707,9 @@
ngx_http_next_header_filter = ngx_http_top_header_filter;
ngx_http_top_header_filter = ngx_http_headers_filter;
+ ngx_http_next_body_filter = ngx_http_top_body_filter;
+ ngx_http_top_body_filter = ngx_http_trailers_filter;
+
return NGX_OK;
}
@@ -838,95 +787,26 @@
{
ngx_http_headers_conf_t *hcf = conf;
- ngx_str_t *value;
- ngx_uint_t i;
- ngx_http_header_val_t *hv;
- ngx_http_set_header_t *set;
- ngx_http_compile_complex_value_t ccv;
+ ngx_str_t *value;
+ ngx_uint_t i;
+ ngx_array_t **headers;
+ ngx_http_header_val_t *hv;
+ ngx_http_set_header_t *set;
+ ngx_http_compile_complex_value_t ccv;
value = cf->args->elts;
- if (hcf->headers == NULL) {
- hcf->headers = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_header_val_t));
- if (hcf->headers == NULL) {
+ headers = (ngx_array_t **) ((char *) hcf + cmd->offset);
+
+ if (*headers == NULL) {
+ *headers = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_header_val_t));
+ if (*headers == NULL) {
return NGX_CONF_ERROR;
}
}
- hv = ngx_array_push(hcf->headers);
- if (hv == NULL) {
- return NGX_CONF_ERROR;
- }
-
- hv->key = value[1];
- hv->handler = ngx_http_add_header;
- hv->offset = 0;
- hv->always = 0;
-
- set = ngx_http_set_headers;
- for (i = 0; set[i].name.len; i++) {
- if (ngx_strcasecmp(value[1].data, set[i].name.data) != 0) {
- continue;
- }
-
- hv->offset = set[i].offset;
- hv->handler = set[i].handler;
-
- break;
- }
-
- if (value[2].len == 0) {
- ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t));
-
- } else {
- ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
-
- ccv.cf = cf;
- ccv.value = &value[2];
- ccv.complex_value = &hv->value;
-
- if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
- return NGX_CONF_ERROR;
- }
- }
-
- if (cf->args->nelts == 3) {
- return NGX_CONF_OK;
- }
-
- if (ngx_strcmp(value[3].data, "always") != 0) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid parameter \"%V\"", &value[3]);
- return NGX_CONF_ERROR;
- }
-
- hv->always = 1;
-
- return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_headers_add_trailer(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
- ngx_http_headers_conf_t *hcf = conf;
-
- ngx_str_t *value;
- ngx_http_header_val_t *hv;
- ngx_http_compile_complex_value_t ccv;
-
- value = cf->args->elts;
-
- if (hcf->trailers == NULL) {
- hcf->trailers = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_header_val_t));
- if (hcf->trailers == NULL) {
- return NGX_CONF_ERROR;
- }
- }
-
- hv = ngx_array_push(hcf->trailers);
+ hv = ngx_array_push(*headers);
if (hv == NULL) {
return NGX_CONF_ERROR;
}
@@ -936,6 +816,22 @@
hv->offset = 0;
hv->always = 0;
+ if (headers == &hcf->headers) {
+ hv->handler = ngx_http_add_header;
+
+ set = ngx_http_set_headers;
+ for (i = 0; set[i].name.len; i++) {
+ if (ngx_strcasecmp(value[1].data, set[i].name.data) != 0) {
+ continue;
+ }
+
+ hv->offset = set[i].offset;
+ hv->handler = set[i].handler;
+
+ break;
+ }
+ }
+
if (value[2].len == 0) {
ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t));
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index e5306ef..29879f0 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -145,7 +145,6 @@
ngx_int_t ngx_http_filter_finalize_request(ngx_http_request_t *r,
ngx_module_t *m, ngx_int_t error);
void ngx_http_clean_header(ngx_http_request_t *r);
-ngx_int_t ngx_http_eval_trailers(ngx_http_request_t *r);
ngx_int_t ngx_http_discard_request_body(ngx_http_request_t *r);
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0dd7427..f2e7623 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -29,8 +29,6 @@
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
-static ngx_int_t ngx_http_process_te(ngx_http_request_t *r,
- ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
ngx_uint_t alloc);
@@ -130,10 +128,6 @@
offsetof(ngx_http_headers_in_t, if_range),
ngx_http_process_unique_header_line },
- { ngx_string("TE"),
- offsetof(ngx_http_headers_in_t, te),
- ngx_http_process_te },
-
{ ngx_string("Transfer-Encoding"),
offsetof(ngx_http_headers_in_t, transfer_encoding),
ngx_http_process_header_line },
@@ -1698,7 +1692,7 @@
#if (NGX_HTTP_V2)
- if (r->http_version >= NGX_HTTP_VERSION_20) {
+ if (r->stream) {
ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
"client sent HTTP/2 request with \"Connection\" header");
@@ -1793,63 +1787,6 @@
static ngx_int_t
-ngx_http_process_te(ngx_http_request_t *r, ngx_table_elt_t *h,
- ngx_uint_t offset)
-{
- u_char *p;
-
- if (ngx_http_process_multi_header_lines(r, h, offset) != NGX_OK) {
- return NGX_ERROR;
- }
-
- if (r->http_version < NGX_HTTP_VERSION_11) {
- return NGX_OK;
- }
-
- if (h->value.len == sizeof("trailers") - 1
- && ngx_memcmp(h->value.data, "trailers", sizeof("trailers") - 1) == 0)
- {
- r->allow_trailers = 1;
- return NGX_OK;
- }
-
-#if (NGX_HTTP_V2)
-
- if (r->http_version >= NGX_HTTP_VERSION_20) {
- ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
- "client sent HTTP/2 request with invalid value \"%V\" "
- "in \"TE\" header", &h->value);
-
- ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
- return NGX_ERROR;
- }
-
-#endif
-
- if (h->value.len < sizeof("trailers") - 1) {
- return NGX_OK;
- }
-
- p = ngx_strcasestrn(h->value.data, "trailers", sizeof("trailers") - 2);
- if (p == NULL) {
- return NGX_OK;
- }
-
- if (p == h->value.data || *(p - 1) == ',' || *(p - 1) == ' ') {
-
- p += sizeof("trailers") - 1;
-
- if (p == h->value.data + h->value.len || *p == ',' || *p == ' ') {
- r->allow_trailers = 1;
- return NGX_OK;
- }
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
ngx_uint_t offset)
{
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index e9fa52f..f6f209b 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -196,7 +196,6 @@
ngx_table_elt_t *range;
ngx_table_elt_t *if_range;
- ngx_array_t te;
ngx_table_elt_t *transfer_encoding;
ngx_table_elt_t *expect;
ngx_table_elt_t *upgrade;
@@ -516,7 +515,6 @@
unsigned pipeline:1;
unsigned chunked:1;
unsigned header_only:1;
- unsigned allow_trailers:1;
unsigned expect_trailers:1;
unsigned keepalive:1;
unsigned lingering_close:1;
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 026458f..9e99da8 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2766,7 +2766,7 @@
ngx_list_part_t *part;
ngx_table_elt_t *h, *ho;
- if (!u->conf->pass_trailers || !r->allow_trailers || !r->expect_trailers) {
+ if (!r->expect_trailers || !u->conf->pass_trailers) {
return NGX_OK;
}
@@ -5199,9 +5199,7 @@
{
ngx_table_elt_t *ho;
- if (!r->upstream->conf->pass_trailers
- || !r->allow_trailers || !r->expect_trailers)
- {
+ if (!r->expect_trailers || !r->upstream->conf->pass_trailers) {
return NGX_OK;
}
diff --git a/src/http/v2/ngx_http_v2_filter_module.c b/src/http/v2/ngx_http_v2_filter_module.c
index 29b07b6..8268a01 100644
--- a/src/http/v2/ngx_http_v2_filter_module.c
+++ b/src/http/v2/ngx_http_v2_filter_module.c
@@ -50,7 +50,7 @@
#define NGX_HTTP_V2_SERVER_INDEX 54
#define NGX_HTTP_V2_VARY_INDEX 59
-#define NGX_HTTP_V2_FRAME_ERROR (ngx_http_v2_out_frame_t *) -1
+#define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1
static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len,
@@ -133,12 +133,12 @@
u_char status, *pos, *start, *p, *tmp;
size_t len, tmp_len;
ngx_str_t host, location;
- ngx_uint_t i, port, fin;
+ ngx_uint_t i, port;
ngx_list_part_t *part;
ngx_table_elt_t *header;
ngx_connection_t *fc;
ngx_http_cleanup_t *cln;
- ngx_http_v2_out_frame_t *headers, *trailers;
+ ngx_http_v2_out_frame_t *frame;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
u_char addr[NGX_SOCKADDR_STRLEN];
@@ -625,6 +625,15 @@
header[i].value.len, tmp);
}
+ frame = ngx_http_v2_create_headers_frame(r, start, pos, r->header_only);
+ if (frame == NULL) {
+ return NGX_ERROR;
+ }
+
+ ngx_http_v2_queue_blocked_frame(r->stream->connection, frame);
+
+ r->stream->queued = 1;
+
cln = ngx_http_cleanup_add(r, 0);
if (cln == NULL) {
return NGX_ERROR;
@@ -633,32 +642,6 @@
cln->handler = ngx_http_v2_filter_cleanup;
cln->data = r->stream;
- if (r->header_only && r->allow_trailers && r->expect_trailers) {
- trailers = ngx_http_v2_create_trailers_frame(r);
- if (trailers == NGX_HTTP_V2_FRAME_ERROR) {
- return NGX_ERROR;
- }
-
- fin = trailers ? 0 : 1;
-
- } else {
- trailers = NULL;
- fin = r->header_only;
- }
-
- headers = ngx_http_v2_create_headers_frame(r, start, pos, fin);
- if (headers == NULL) {
- return NGX_ERROR;
- }
-
- ngx_http_v2_queue_blocked_frame(r->stream->connection, headers);
- r->stream->queued = 1;
-
- if (trailers) {
- ngx_http_v2_queue_blocked_frame(r->stream->connection, trailers);
- r->stream->queued++;
- }
-
fc->send_chain = ngx_http_v2_send_chain;
fc->need_last_buf = 1;
@@ -669,16 +652,11 @@
static ngx_http_v2_out_frame_t *
ngx_http_v2_create_trailers_frame(ngx_http_request_t *r)
{
- u_char *pos, *start, *tmp;
- size_t len, tmp_len;
- ngx_uint_t i;
- ngx_list_part_t *part;
- ngx_table_elt_t *header;
- ngx_http_v2_out_frame_t *frame;
-
- if (ngx_http_eval_trailers(r) != NGX_OK) {
- return NGX_HTTP_V2_FRAME_ERROR;
- }
+ u_char *pos, *start, *tmp;
+ size_t len, tmp_len;
+ ngx_uint_t i;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *header;
len = 0;
tmp_len = 0;
@@ -703,19 +681,17 @@
}
if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
"too long response trailer name: \"%V\"",
&header[i].key);
-
- return NGX_HTTP_V2_FRAME_ERROR;
+ return NULL;
}
if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
- ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
"too long response trailer value: \"%V: %V\"",
&header[i].key, &header[i].value);
-
- return NGX_HTTP_V2_FRAME_ERROR;
+ return NULL;
}
len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
@@ -731,14 +707,14 @@
}
if (len == 0) {
- return NULL;
+ return NGX_HTTP_V2_NO_TRAILERS;
}
tmp = ngx_palloc(r->pool, tmp_len);
pos = ngx_pnalloc(r->pool, len);
if (pos == NULL || tmp == NULL) {
- return NGX_HTTP_V2_FRAME_ERROR;
+ return NULL;
}
start = pos;
@@ -758,10 +734,7 @@
i = 0;
}
- if (header[i].hash == 0
- || header[i].key.len > NGX_HTTP_V2_MAX_FIELD
- || header[i].value.len > NGX_HTTP_V2_MAX_FIELD)
- {
+ if (header[i].hash == 0) {
continue;
}
@@ -784,12 +757,7 @@
header[i].value.len, tmp);
}
- frame = ngx_http_v2_create_headers_frame(r, start, pos, 1);
- if (frame == NULL) {
- return NGX_HTTP_V2_FRAME_ERROR;
- }
-
- return frame;
+ return ngx_http_v2_create_headers_frame(r, start, pos, 1);
}
@@ -1029,7 +997,7 @@
frame_size = (h2lcf->chunk_size < h2c->frame_size)
? h2lcf->chunk_size : h2c->frame_size;
- trailers = NULL;
+ trailers = NGX_HTTP_V2_NO_TRAILERS;
#if (NGX_SUPPRESS_WARN)
cl = NULL;
@@ -1093,19 +1061,20 @@
size -= rest;
}
- if (cl->buf->last_buf && r->allow_trailers && r->expect_trailers) {
+ if (cl->buf->last_buf) {
trailers = ngx_http_v2_create_trailers_frame(r);
- if (trailers == NGX_HTTP_V2_FRAME_ERROR) {
+ if (trailers == NULL) {
return NGX_CHAIN_ERROR;
}
- if (trailers) {
+ if (trailers != NGX_HTTP_V2_NO_TRAILERS) {
cl->buf->last_buf = 0;
}
}
if (frame_size || cl->buf->last_buf) {
- frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, out, cl);
+ frame = ngx_http_v2_filter_get_data_frame(stream, frame_size,
+ out, cl);
if (frame == NULL) {
return NGX_CHAIN_ERROR;
}
@@ -1118,12 +1087,13 @@
stream->queued++;
}
- if (trailers) {
- ngx_http_v2_queue_frame(h2c, trailers);
- stream->queued++;
- }
-
if (in == NULL) {
+
+ if (trailers != NGX_HTTP_V2_NO_TRAILERS) {
+ ngx_http_v2_queue_frame(h2c, trailers);
+ stream->queued++;
+ }
+
break;
}