Welcome! Log In Create A New Profile

Advanced

[PATCH] HTTP/2: added support for setting custom push request headers

Alessandro Ghedini
February 12, 2018 07:38AM
# HG changeset patch
# User Alessandro Ghedini <alessandro@ghedini.me>
# Date 1518438578 0
# Mon Feb 12 12:29:38 2018 +0000
# Branch http2-push-header
# Node ID 4eb0c9e8da0bc52065578e4ee78df1833617ac35
# Parent a49af443656f2b65ca5de9d8cad5594f44e18ff7
HTTP/2: added support for setting custom push request headers.

This implementa the http2_push_header configuration directive that makes
it possible to set custom request headers for pushed requests.

Complex values are evaluated in the context of the original request,
so it's possible to copy its headers into pushed requests.

Example usage:

http2_push_header User-Agent $http_user_agent;

diff -r a49af443656f -r 4eb0c9e8da0b src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Thu Feb 08 12:11:30 2018 +0300
+++ b/src/http/v2/ngx_http_v2.c Mon Feb 12 12:29:38 2018 +0000
@@ -2516,15 +2516,22 @@

ngx_int_t
ngx_http_v2_push_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t depend,
- size_t request_length, ngx_str_t *path, ngx_str_t *authority)
+ size_t request_length, ngx_str_t *path, ngx_str_t *authority,
+ ngx_http_headers_in_t *headers_in)
{
ngx_int_t rc;
ngx_str_t value;
+ ngx_uint_t i;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *hdr, *h;
ngx_connection_t *fc;
+ ngx_http_header_t *hh;
ngx_http_request_t *r;
ngx_http_v2_node_t *node;
ngx_http_v2_stream_t *stream;

+ ngx_http_core_main_conf_t *cmcf;
+
node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1);

if (node == NULL) {
@@ -2605,6 +2612,57 @@
goto error;
}

+ cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+ part = &headers_in->headers.part;
+ hdr = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ hdr = part->elts;
+ i = 0;
+ }
+
+ h = ngx_list_push(&r->headers_in.headers);
+ if (h == NULL) {
+ goto error;
+ }
+
+ h->key = hdr[i].key;
+
+ h->hash = hdr[i].hash;
+
+ h->value.len = hdr[i].value.len;
+
+ h->value.data = ngx_pnalloc(r->stream->pool, h->value.len + 1);
+ if (h->key.data == NULL) {
+ h->hash = 0;
+ goto error;
+ }
+
+ (void) ngx_cpystrn(h->value.data, hdr[i].value.data, h->value.len + 1);
+
+ h->lowcase_key = h->key.data;
+
+ hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
+ h->lowcase_key, h->key.len);
+
+ if (hh == NULL) {
+ continue;
+ }
+
+ rc = hh->handler(r, h, hh->offset);
+ if (rc != NGX_OK) {
+ goto error;
+ }
+ }
+
fc->write->handler = ngx_http_v2_run_request_handler;
ngx_post_event(fc->write, &ngx_posted_events);

diff -r a49af443656f -r 4eb0c9e8da0b src/http/v2/ngx_http_v2.h
--- a/src/http/v2/ngx_http_v2.h Thu Feb 08 12:11:30 2018 +0300
+++ b/src/http/v2/ngx_http_v2.h Mon Feb 12 12:29:38 2018 +0000
@@ -285,7 +285,7 @@

ngx_int_t ngx_http_v2_push_stream(ngx_http_v2_connection_t *h2c,
ngx_uint_t depend, size_t request_length, ngx_str_t *path,
- ngx_str_t *authority);
+ ngx_str_t *authority, ngx_http_headers_in_t *headers_in);

void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc);

diff -r a49af443656f -r 4eb0c9e8da0b src/http/v2/ngx_http_v2_filter_module.c
--- a/src/http/v2/ngx_http_v2_filter_module.c Thu Feb 08 12:11:30 2018 +0300
+++ b/src/http/v2/ngx_http_v2_filter_module.c Mon Feb 12 12:29:38 2018 +0000
@@ -907,13 +907,19 @@
ngx_http_v2_push_resource(ngx_http_request_t *r, ngx_str_t *path,
ngx_str_t *authority)
{
- u_char *start, *pos, *tmp;
- size_t len;
- ngx_table_elt_t *host;
- ngx_connection_t *fc;
- ngx_http_v2_stream_t *stream;
- ngx_http_v2_out_frame_t *frame;
- ngx_http_v2_connection_t *h2c;
+ u_char *start, *pos, *tmp;
+ size_t len;
+ ngx_str_t value;
+ ngx_uint_t i;
+ ngx_list_part_t *part;
+ ngx_table_elt_t *host, *h;
+ ngx_connection_t *fc;
+ ngx_http_headers_in_t headers_in;
+ ngx_http_v2_stream_t *stream;
+ ngx_http_v2_loc_conf_t *h2lcf;
+ ngx_http_v2_out_frame_t *frame;
+ ngx_http_v2_connection_t *h2c;
+ ngx_http_v2_push_header_val_t *hv;

fc = r->connection;

@@ -972,6 +978,43 @@
+ authority->len
+ 1;

+ h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module);
+
+ if ((h2lcf->push_headers != NULL) && (h2lcf->push_headers->nelts > 0)) {
+
+ if (ngx_list_init(&headers_in.headers, r->pool,
+ h2lcf->push_headers->nelts,
+ sizeof(ngx_table_elt_t))
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ hv = h2lcf->push_headers->elts;
+ for (i = 0; i < h2lcf->push_headers->nelts; i++) {
+
+ if (ngx_http_complex_value(r, &hv[i].value, &value) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ if (value.len) {
+ h = ngx_list_push(&headers_in.headers);
+ if (h == NULL) {
+ return NGX_ERROR;
+ }
+
+ h->key = hv[i].key;
+
+ h->hash = hv[i].hash;
+
+ h->value = value;
+
+ len += 1 + NGX_HTTP_V2_INT_OCTETS + h->key.len
+ + NGX_HTTP_V2_INT_OCTETS + h->value.len;
+ }
+ }
+ }
+
tmp = ngx_palloc(r->pool, len);
pos = ngx_pnalloc(r->pool, len);

@@ -1018,6 +1061,26 @@
*pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX);
}

+ part = &headers_in.headers.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;
+ }
+
+ *pos++ = 0;
+ pos = ngx_http_v2_write_name(pos, h[i].key.data, h[i].key.len, tmp);
+ pos = ngx_http_v2_write_value(pos, h[i].value.data, h[i].value.len, tmp);
+ }
+
frame = ngx_http_v2_create_push_frame(r, start, pos);
if (frame == NULL) {
return NGX_ERROR;
@@ -1028,7 +1091,7 @@
stream->queued++;

return ngx_http_v2_push_stream(h2c, stream->node->id, pos - start,
- path, &host->value);
+ path, &host->value, &headers_in);
}


diff -r a49af443656f -r 4eb0c9e8da0b src/http/v2/ngx_http_v2_module.c
--- a/src/http/v2/ngx_http_v2_module.c Thu Feb 08 12:11:30 2018 +0300
+++ b/src/http/v2/ngx_http_v2_module.c Mon Feb 12 12:29:38 2018 +0000
@@ -28,6 +28,8 @@
void *child);

static char *ngx_http_v2_push(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_http_v2_push_header(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);

static char *ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post,
void *data);
@@ -152,6 +154,13 @@
0,
NULL },

+ { ngx_string("http2_push_header"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+ ngx_http_v2_push_header,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("spdy_recv_buffer_size"),
NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
ngx_http_v2_spdy_deprecated,
@@ -416,6 +425,7 @@
* set by ngx_pcalloc():
*
* h2lcf->pushes = NULL;
+ * h2lcf->push_headers = NULL;
*/

h2lcf->chunk_size = NGX_CONF_UNSET_SIZE;
@@ -441,6 +451,10 @@
conf->pushes = prev->pushes;
}

+ if (conf->push && conf->push_headers == NULL) {
+ conf->push_headers = prev->push_headers;
+ }
+
ngx_conf_merge_value(conf->push_preload, prev->push_preload, 0);

return NGX_CONF_OK;
@@ -506,6 +520,55 @@


static char *
+ngx_http_v2_push_header(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_v2_loc_conf_t *h2lcf = conf;
+
+ ngx_str_t *value;
+ ngx_http_v2_push_header_val_t *hv;
+ ngx_http_compile_complex_value_t ccv;
+
+ value = cf->args->elts;
+
+ if (h2lcf->push_headers == NULL) {
+ h2lcf->push_headers = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_v2_push_header_val_t));
+ if (h2lcf->push_headers == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ hv = ngx_array_push(h2lcf->push_headers);
+ if (hv == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ hv->key = value[1];
+
+ ngx_strlow(hv->key.data, hv->key.data, hv->key.len);
+
+ hv->hash = ngx_hash_key(hv->key.data, hv->key.len);
+
+ 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;
+ }
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
ngx_http_v2_recv_buffer_size(ngx_conf_t *cf, void *post, void *data)
{
size_t *sp = data;
diff -r a49af443656f -r 4eb0c9e8da0b src/http/v2/ngx_http_v2_module.h
--- a/src/http/v2/ngx_http_v2_module.h Thu Feb 08 12:11:30 2018 +0300
+++ b/src/http/v2/ngx_http_v2_module.h Mon Feb 12 12:29:38 2018 +0000
@@ -41,9 +41,17 @@

ngx_flag_t push;
ngx_array_t *pushes;
+ ngx_array_t *push_headers;
} ngx_http_v2_loc_conf_t;


+typedef struct {
+ ngx_http_complex_value_t value;
+ ngx_str_t key;
+ ngx_uint_t hash;
+} ngx_http_v2_push_header_val_t;
+
+
extern ngx_module_t ngx_http_v2_module;


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

[PATCH] HTTP/2: added support for setting custom push request headers

Alessandro Ghedini 611 February 12, 2018 07:38AM

Re: [PATCH] HTTP/2: added support for setting custom push request headers

ru@nginx.com 670 February 12, 2018 09:14AM

Re: [PATCH] HTTP/2: added support for setting custom push request headers

Alessandro Ghedini 370 February 12, 2018 10:20AM

Re: [PATCH] HTTP/2: added support for setting custom push request headers

Alessandro Ghedini 493 February 12, 2018 10:32AM

Re: [PATCH] HTTP/2: added support for setting custom push request headers

Alessandro Ghedini 409 February 13, 2018 07:00AM

Re: [PATCH] HTTP/2: added support for setting custom push request headers

ru@nginx.com 532 February 14, 2018 02:50PM



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

Online Users

Guests: 298
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