Welcome! Log In Create A New Profile

Advanced

[PATCH 2 of 2] Headers filter: add "add_trailer" directive

Piotr Sikora
June 26, 2016 07:14PM
# HG changeset patch
# User Piotr Sikora <piotrsikora@google.com>
# Date 1466735587 25200
# Thu Jun 23 19:33:07 2016 -0700
# Node ID e21760ce55fdae50a6723aeb4cb6e0b0bcf73dcb
# Parent a96187a9806536ab2a8bf3fa7f7b659cf5d3ff13
Headers filter: add "add_trailer" directive.

Trailers added using this directive are evaluated after response body
is processed by output filters (but before it's written to the wire),
so it's possible to use variables calculated from the response body
as the trailer value.

Signed-off-by: Piotr Sikora <piotrsikora@google.com>

diff -r a96187a98065 -r e21760ce55fd src/http/modules/ngx_http_chunked_filter_module.c
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -254,6 +254,10 @@ ngx_http_chunked_get_trailers(ngx_http_r
ngx_table_elt_t *header;
ngx_http_chunked_filter_ctx_t *ctx;

+ if (ngx_http_eval_trailers(r) != NGX_OK) {
+ return NULL;
+ }
+
len = 0;

part = &r->headers_out.trailers.part;
diff -r a96187a98065 -r e21760ce55fd 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
@@ -48,6 +48,7 @@ typedef struct {
time_t expires_time;
ngx_http_complex_value_t *expires_value;
ngx_array_t *headers;
+ ngx_array_t *trailers;
} ngx_http_headers_conf_t;


@@ -72,6 +73,8 @@ static char *ngx_http_headers_expires(ng
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,6 +111,14 @@ static ngx_command_t ngx_http_headers_f
0,
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_LOC_CONF_OFFSET,
+ 0,
+ NULL},
+
ngx_null_command
};

@@ -149,15 +160,23 @@ static ngx_http_output_header_filter_pt
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;

+ if (r != r->main) {
+ return ngx_http_next_header_filter(r);
+ }
+
conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);

- if ((conf->expires == NGX_HTTP_EXPIRES_OFF && conf->headers == NULL)
- || r != r->main)
+ if (conf->expires == NGX_HTTP_EXPIRES_OFF
+ && conf->headers == NULL
+ && conf->trailers == NULL)
{
return ngx_http_next_header_filter(r);
}
@@ -205,6 +224,64 @@ ngx_http_headers_filter(ngx_http_request
}
}

+ if (conf->trailers && r->trailers_ok) {
+ len = 0;
+
+ 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) {
+ len += h[i].key.len + sizeof(", ") - 1;
+ }
+ }
+
+ 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');
+ }
+
return ngx_http_next_header_filter(r);
}

@@ -541,6 +618,67 @@ ngx_http_set_response_header(ngx_http_re
}


+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)
{
@@ -555,6 +693,7 @@ ngx_http_headers_create_conf(ngx_conf_t
* set by ngx_pcalloc():
*
* conf->headers = NULL;
+ * conf->trailers = NULL;
* conf->expires_time = 0;
* conf->expires_value = NULL;
*/
@@ -585,6 +724,10 @@ ngx_http_headers_merge_conf(ngx_conf_t *
conf->headers = prev->headers;
}

+ if (conf->trailers == NULL) {
+ conf->trailers = prev->trailers;
+ }
+
return NGX_CONF_OK;
}

@@ -739,3 +882,63 @@ ngx_http_headers_add(ngx_conf_t *cf, ngx

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);
+ if (hv == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ hv->key = value[1];
+ hv->handler = NULL;
+ hv->offset = 0;
+ hv->always = 0;
+
+ 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;
+}
diff -r a96187a98065 -r e21760ce55fd src/http/ngx_http.h
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -146,6 +146,7 @@ ngx_int_t ngx_http_special_response_hand
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 -r a96187a98065 -r e21760ce55fd src/http/v2/ngx_http_v2_filter_module.c
--- a/src/http/v2/ngx_http_v2_filter_module.c
+++ b/src/http/v2/ngx_http_v2_filter_module.c
@@ -606,6 +606,10 @@ ngx_http_v2_create_trailers_frame(ngx_ht
ngx_list_part_t *part;
ngx_table_elt_t *header;

+ if (ngx_http_eval_trailers(r) != NGX_OK) {
+ return NULL;
+ }
+
len = 0;
tmp_len = 0;


_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 934 June 26, 2016 07:14PM

[PATCH 2 of 2] Headers filter: add "add_trailer" directive

Piotr Sikora 427 June 26, 2016 07:14PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 384 June 27, 2016 09:46AM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 393 June 27, 2016 10:38AM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

shuxinyang 461 June 27, 2016 01:06PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 367 June 27, 2016 01:14PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

shuxinyang 387 June 27, 2016 02:56PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 482 June 27, 2016 03:16PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

shuxinyang 396 June 27, 2016 06:04PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 361 June 27, 2016 07:18PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

shuxinyang 366 June 27, 2016 09:00PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 332 June 27, 2016 09:46PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 371 June 27, 2016 01:54PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 371 June 27, 2016 03:06PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 339 June 30, 2016 03:58PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 377 July 04, 2016 10:22AM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 373 July 06, 2016 05:04PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 359 July 07, 2016 11:02AM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 341 July 07, 2016 04:10PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 345 July 07, 2016 07:22PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 398 July 13, 2016 01:28PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 409 July 13, 2016 02:44PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Piotr Sikora 317 July 13, 2016 08:36PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Alexey Ivanov 342 July 20, 2016 06:36PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 321 July 20, 2016 09:24PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Alexey Ivanov 352 July 20, 2016 09:34PM

Re: [PATCH 1 of 2] HTTP: add support for trailers in HTTP responses

Maxim Dounin 426 July 21, 2016 09:46AM

[PATCH] HTTP: add support for trailers in HTTP responses

Piotr Sikora 328 August 01, 2016 01:00AM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Piotr Sikora 316 August 01, 2016 03:36AM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Maxim Dounin 289 August 01, 2016 09:24AM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Piotr Sikora 448 August 01, 2016 01:58PM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Maxim Dounin 347 August 03, 2016 10:26PM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Piotr Sikora 302 August 18, 2016 09:14PM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Valentin V. Bartenev 296 August 19, 2016 07:16AM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Maxim Dounin 299 August 23, 2016 11:00AM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Maxim Dounin 515 August 23, 2016 10:24AM

Re: [PATCH] HTTP: add support for trailers in HTTP responses

Piotr Sikora 989 August 31, 2016 09:32PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 283
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready