Welcome! Log In Create A New Profile

Advanced

[PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Piotr Sikora via nginx-devel
June 02, 2017 05:06AM
# HG changeset patch
# User Piotr Sikora <piotrsikora@google.com>
# Date 1493191954 25200
# Wed Apr 26 00:32:34 2017 -0700
# Node ID e84aa49c5bc7a3250d4844b581e4bf3ed42db5f5
# Parent b0a910ad494158427ba102bdac71ce01d0667f72
HTTP/2: added support for trailers in HTTP responses.

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

diff -r b0a910ad4941 -r e84aa49c5bc7 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
@@ -50,13 +50,17 @@
#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
+

static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len,
u_char *tmp, ngx_uint_t lower);
static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix,
ngx_uint_t value);
static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame(
- ngx_http_request_t *r, u_char *pos, u_char *end);
+ ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin);
+static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame(
+ ngx_http_request_t *r);

static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc,
ngx_chain_t *in, off_t limit);
@@ -612,7 +616,7 @@ ngx_http_v2_header_filter(ngx_http_reque
header[i].value.len, tmp);
}

- frame = ngx_http_v2_create_headers_frame(r, start, pos);
+ frame = ngx_http_v2_create_headers_frame(r, start, pos, r->header_only);
if (frame == NULL) {
return NGX_ERROR;
}
@@ -636,6 +640,126 @@ ngx_http_v2_header_filter(ngx_http_reque
}


+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;
+
+ len = 0;
+ tmp_len = 0;
+
+ part = &r->headers_out.trailers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ if (header[i].hash == 0) {
+ continue;
+ }
+
+ if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "too long response trailer name: \"%V\"",
+ &header[i].key);
+
+ return NGX_HTTP_V2_FRAME_ERROR;
+ }
+
+ if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) {
+ ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
+ "too long response trailer value: \"%V: %V\"",
+ &header[i].key, &header[i].value);
+
+ return NGX_HTTP_V2_FRAME_ERROR;
+ }
+
+ len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len
+ + NGX_HTTP_V2_INT_OCTETS + header[i].value.len;
+
+ if (header[i].key.len > tmp_len) {
+ tmp_len = header[i].key.len;
+ }
+
+ if (header[i].value.len > tmp_len) {
+ tmp_len = header[i].value.len;
+ }
+ }
+
+ if (len == 0) {
+ return NULL;
+ }
+
+ tmp = ngx_palloc(r->pool, tmp_len);
+ pos = ngx_pnalloc(r->pool, len);
+
+ if (pos == NULL || tmp == NULL) {
+ return NGX_HTTP_V2_FRAME_ERROR;
+ }
+
+ start = pos;
+
+ part = &r->headers_out.trailers.part;
+ header = part->elts;
+
+ for (i = 0; /* void */; i++) {
+
+ if (i >= part->nelts) {
+ if (part->next == NULL) {
+ break;
+ }
+
+ part = part->next;
+ header = part->elts;
+ i = 0;
+ }
+
+ if (header[i].hash == 0) {
+ continue;
+ }
+
+#if (NGX_DEBUG)
+ if (r->connection->log->log_level & NGX_LOG_DEBUG_HTTP) {
+ ngx_strlow(tmp, header[i].key.data, header[i].key.len);
+
+ ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http2 output trailer: \"%*s: %V\"",
+ header[i].key.len, tmp, &header[i].value);
+ }
+#endif
+
+ *pos++ = 0;
+
+ pos = ngx_http_v2_write_name(pos, header[i].key.data,
+ header[i].key.len, tmp);
+
+ pos = ngx_http_v2_write_value(pos, header[i].value.data,
+ 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;
+}
+
+
static u_char *
ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp,
ngx_uint_t lower)
@@ -686,7 +810,7 @@ ngx_http_v2_write_int(u_char *pos, ngx_u

static ngx_http_v2_out_frame_t *
ngx_http_v2_create_headers_frame(ngx_http_request_t *r, u_char *pos,
- u_char *end)
+ u_char *end, ngx_uint_t fin)
{
u_char type, flags;
size_t rest, frame_size;
@@ -707,12 +831,12 @@ ngx_http_v2_create_headers_frame(ngx_htt
frame->stream = stream;
frame->length = rest;
frame->blocked = 1;
- frame->fin = r->header_only;
+ frame->fin = fin;

ll = &frame->first;

type = NGX_HTTP_V2_HEADERS_FRAME;
- flags = r->header_only ? NGX_HTTP_V2_END_STREAM_FLAG : NGX_HTTP_V2_NO_FLAG;
+ flags = fin ? NGX_HTTP_V2_END_STREAM_FLAG : NGX_HTTP_V2_NO_FLAG;
frame_size = stream->connection->frame_size;

for ( ;; ) {
@@ -776,7 +900,7 @@ ngx_http_v2_create_headers_frame(ngx_htt
continue;
}

- b->last_buf = r->header_only;
+ b->last_buf = fin;
cl->next = NULL;
frame->last = cl;

@@ -798,7 +922,7 @@ ngx_http_v2_send_chain(ngx_connection_t
ngx_http_request_t *r;
ngx_http_v2_stream_t *stream;
ngx_http_v2_loc_conf_t *h2lcf;
- ngx_http_v2_out_frame_t *frame;
+ ngx_http_v2_out_frame_t *frame, *trailers;
ngx_http_v2_connection_t *h2c;

r = fc->data;
@@ -872,6 +996,8 @@ ngx_http_v2_send_chain(ngx_connection_t
frame_size = (h2lcf->chunk_size < h2c->frame_size)
? h2lcf->chunk_size : h2c->frame_size;

+ trailers = NULL;
+
#if (NGX_SUPPRESS_WARN)
cl = NULL;
#endif
@@ -934,17 +1060,36 @@ ngx_http_v2_send_chain(ngx_connection_t
size -= rest;
}

- frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, out, cl);
- if (frame == NULL) {
- return NGX_CHAIN_ERROR;
+ if (cl->buf->last_buf && r->expect_trailers) {
+ trailers = ngx_http_v2_create_trailers_frame(r);
+ if (trailers == NGX_HTTP_V2_FRAME_ERROR) {
+ return NGX_CHAIN_ERROR;
+ }
+
+ if (trailers) {
+ cl->buf->last_buf = 0;
+ }
}

- ngx_http_v2_queue_frame(h2c, frame);
+ if (frame_size || cl->buf->last_buf) {
+ frame = ngx_http_v2_filter_get_data_frame(stream, frame_size, out,
+ cl);
+ if (frame == NULL) {
+ return NGX_CHAIN_ERROR;
+ }

- h2c->send_window -= frame_size;
+ ngx_http_v2_queue_frame(h2c, frame);

- stream->send_window -= frame_size;
- stream->queued++;
+ h2c->send_window -= frame_size;
+
+ stream->send_window -= frame_size;
+ stream->queued++;
+ }
+
+ if (trailers) {
+ ngx_http_v2_queue_frame(h2c, trailers);
+ stream->queued++;
+ }

if (in == NULL) {
break;
_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

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

Piotr Sikora via nginx-devel 604 March 24, 2017 06:50AM

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

Piotr Sikora via nginx-devel 298 March 24, 2017 06:50AM

[PATCH 3 of 3] Upstream: add support for trailers in HTTP responses

Piotr Sikora via nginx-devel 308 March 24, 2017 06:50AM

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

Piotr Sikora via nginx-devel 268 April 05, 2017 08:34AM

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

Maxim Dounin 276 April 05, 2017 11:26AM

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

Maxim Dounin 305 April 21, 2017 01:42PM

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

Piotr Sikora via nginx-devel 308 April 26, 2017 02:36PM

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

Maxim Dounin 298 April 27, 2017 02:48PM

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

Piotr Sikora via nginx-devel 422 May 01, 2017 12:46AM

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

Maxim Dounin 259 May 03, 2017 10:02AM

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

Piotr Sikora via nginx-devel 216 June 02, 2017 05:06AM

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

Maxim Dounin 315 June 02, 2017 08:32AM

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

Piotr Sikora via nginx-devel 224 June 02, 2017 11:34PM

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

Maxim Dounin 300 April 21, 2017 01:42PM

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

Piotr Sikora via nginx-devel 289 June 02, 2017 05:12AM

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

Maxim Dounin 730 June 02, 2017 12:22PM

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

Piotr Sikora via nginx-devel 614 June 02, 2017 11:40PM

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

Maxim Dounin 273 April 21, 2017 01:44PM

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

Piotr Sikora via nginx-devel 291 June 02, 2017 05:16AM

[PATCH 3 of 3] Headers filter: added "add_trailer" directive

Piotr Sikora via nginx-devel 371 June 02, 2017 05:06AM

[PATCH 1 of 3] Added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 218 June 02, 2017 05:06AM

Re: [PATCH 1 of 3] Added support for trailers in HTTP responses

Maxim Dounin 259 June 02, 2017 11:38AM

Re: [PATCH 1 of 3] Added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 256 June 02, 2017 11:34PM

[PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 242 June 02, 2017 05:06AM

[PATCH 1 of 3] Added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 281 June 02, 2017 11:34PM

Re: [PATCH 1 of 3] Added support for trailers in HTTP responses

Maxim Dounin 277 June 05, 2017 12:30PM

Re: [PATCH 1 of 3] Added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 212 June 06, 2017 12:58AM

Re: [PATCH 1 of 3] Added support for trailers in HTTP responses

Maxim Dounin 326 June 06, 2017 08:26AM

Re: [PATCH 1 of 3] Added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 176 June 13, 2017 08:22AM

[PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 212 June 02, 2017 11:34PM

Re: [PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Maxim Dounin 273 June 05, 2017 02:02PM

Re: [PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Maxim Konovalov 370 June 06, 2017 03:26AM

Re: [PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Valentin V. Bartenev 199 June 07, 2017 03:18PM

Re: [PATCH 2 of 3] HTTP/2: added support for trailers in HTTP responses

Piotr Sikora via nginx-devel 285 June 13, 2017 08:26AM

[PATCH 3 of 3] Headers filter: added "add_trailer" directive

Piotr Sikora via nginx-devel 437 June 02, 2017 11:36PM

Re: [PATCH 3 of 3] Headers filter: added "add_trailer" directive

Maxim Dounin 243 June 05, 2017 01:54PM

Re: [PATCH 3 of 3] Headers filter: added "add_trailer" directive

Piotr Sikora via nginx-devel 212 June 06, 2017 01:00AM

Re: [PATCH 3 of 3] Headers filter: added "add_trailer" directive

Maxim Dounin 348 June 06, 2017 08:36AM



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

Online Users

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