[PATCH] HTTP/2: add fast-path for HTTP/2 requests without request body
Valentin V. Bartenev
vbart at nginx.com
Wed Apr 5 15:55:08 UTC 2017
On Wednesday 05 April 2017 18:13:52 Valentin V. Bartenev wrote:
> On Wednesday 05 April 2017 05:32:50 Piotr Sikora via nginx-devel wrote:
> > Hey Valentin,
> >
> > > # HG changeset patch
> > > # User Piotr Sikora <piotrsikora at google.com>
> > > # Date 1490516712 25200
> > > # Sun Mar 26 01:25:12 2017 -0700
> > > # Node ID 630a8209defe25add7094dfc7b9bc9bcabe0933d
> > > # Parent 22be63bf21edaa1b8ea916c7d8cd4e5fe4892061
> > > HTTP/2: add fast-path for HTTP/2 requests without request body.
> > >
> > > Signed-off-by: Piotr Sikora <piotrsikora at google.com>
> > >
> > > diff -r 22be63bf21ed -r 630a8209defe src/http/v2/ngx_http_v2.c
> > > --- a/src/http/v2/ngx_http_v2.c
> > > +++ b/src/http/v2/ngx_http_v2.c
> > > @@ -3520,6 +3520,12 @@ ngx_http_v2_read_request_body(ngx_http_r
> > >
> > > r->request_body = rb;
> > >
> > > + if (stream->in_closed && stream->preread == NULL) {
> > > + r->request_body_no_buffering = 0;
> > > + post_handler(r);
> > > + return NGX_OK;
> > > + }
> > > +
> > > h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
> > > clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
> > >
> >
> > Any thoughts on the updated patch? Thanks!
> >
> [..]
>
> With your patch the behavior is different in these cases:
>
> GET / HTTP/1.1
> Host: example.com
> Transfer-Encoding: chunked
>
> 0
>
> and
>
> HEADERS
> DATA length:0 END_STREAM
>
> Moreover, it depends on the time when DATA frame is processed:
> before ngx_http_read_request_body() call or after.
>
In fact, to eliminate the difference the check must be identical:
# HG changeset patch
# User Valentin Bartenev <vbart at nginx.com>
# Date 1491405913 -10800
# Wed Apr 05 18:25:13 2017 +0300
# Node ID daf8ee97e898b679b00759c9ff1081de4c3515a3
# Parent 28dc369899ea77b03fab44d8878b273d28f06437
HTTP/2: fast-path for requests without body.
This eliminates difference in behavior between HTTP/1.x and HTTP/2 code paths.
diff -r 28dc369899ea -r daf8ee97e898 src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Sun Mar 26 01:25:01 2017 -0700
+++ b/src/http/v2/ngx_http_v2.c Wed Apr 05 18:25:13 2017 +0300
@@ -3525,6 +3525,12 @@ ngx_http_v2_read_request_body(ngx_http_r
r->request_body = rb;
+ if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
+ r->request_body_no_buffering = 0;
+ post_handler(r);
+ return NGX_OK;
+ }
+
h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
or another way:
# HG changeset patch
# User Valentin Bartenev <vbart at nginx.com>
# Date 1491407679 -10800
# Wed Apr 05 18:54:39 2017 +0300
# Node ID 3398c1d446dddc4d1677370f9c8189e6aa4ff4e8
# Parent 29ba1d6a2da9320e68ef2b7a2516c4c424672ea8
HTTP/2: reduced difference to HTTP/1.x in reading request body.
This also eliminates difference in behavior for requests without body.
diff -r 29ba1d6a2da9 -r 3398c1d446dd src/http/ngx_http_request_body.c
--- a/src/http/ngx_http_request_body.c Tue Apr 04 18:01:57 2017 +0300
+++ b/src/http/ngx_http_request_body.c Wed Apr 05 18:54:39 2017 +0300
@@ -46,13 +46,6 @@ ngx_http_read_client_request_body(ngx_ht
return NGX_OK;
}
-#if (NGX_HTTP_V2)
- if (r->stream) {
- rc = ngx_http_v2_read_request_body(r, post_handler);
- goto done;
- }
-#endif
-
if (ngx_http_test_expect(r) != NGX_OK) {
rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
goto done;
@@ -85,6 +78,13 @@ ngx_http_read_client_request_body(ngx_ht
return NGX_OK;
}
+#if (NGX_HTTP_V2)
+ if (r->stream) {
+ rc = ngx_http_v2_read_request_body(r);
+ goto done;
+ }
+#endif
+
preread = r->header_in->last - r->header_in->pos;
if (preread) {
@@ -805,7 +805,8 @@ ngx_http_test_expect(ngx_http_request_t
if (r->expect_tested
|| r->headers_in.expect == NULL
- || r->http_version < NGX_HTTP_VERSION_11)
+ || r->http_version < NGX_HTTP_VERSION_11
+ || r->http_version == NGX_HTTP_VERSION_20)
{
return NGX_OK;
}
diff -r 29ba1d6a2da9 -r 3398c1d446dd src/http/v2/ngx_http_v2.c
--- a/src/http/v2/ngx_http_v2.c Tue Apr 04 18:01:57 2017 +0300
+++ b/src/http/v2/ngx_http_v2.c Wed Apr 05 18:54:39 2017 +0300
@@ -3484,8 +3484,7 @@ ngx_http_v2_run_request(ngx_http_request
ngx_int_t
-ngx_http_v2_read_request_body(ngx_http_request_t *r,
- ngx_http_client_body_handler_pt post_handler)
+ngx_http_v2_read_request_body(ngx_http_request_t *r)
{
off_t len;
size_t size;
@@ -3498,32 +3497,7 @@ ngx_http_v2_read_request_body(ngx_http_r
ngx_http_v2_connection_t *h2c;
stream = r->stream;
-
- if (stream->skip_data) {
- r->request_body_no_buffering = 0;
- post_handler(r);
- return NGX_OK;
- }
-
- rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
- if (rb == NULL) {
- return NGX_HTTP_INTERNAL_SERVER_ERROR;
- }
-
- /*
- * set by ngx_pcalloc():
- *
- * rb->bufs = NULL;
- * rb->buf = NULL;
- * rb->received = 0;
- * rb->free = NULL;
- * rb->busy = NULL;
- */
-
- rb->rest = 1;
- rb->post_handler = post_handler;
-
- r->request_body = rb;
+ rb = r->request_body;
h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module);
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
@@ -3574,6 +3548,8 @@ ngx_http_v2_read_request_body(ngx_http_r
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+ rb->rest = 1;
+
buf = stream->preread;
if (stream->in_closed) {
diff -r 29ba1d6a2da9 -r 3398c1d446dd src/http/v2/ngx_http_v2.h
--- a/src/http/v2/ngx_http_v2.h Tue Apr 04 18:01:57 2017 +0300
+++ b/src/http/v2/ngx_http_v2.h Wed Apr 05 18:54:39 2017 +0300
@@ -264,8 +264,7 @@ ngx_http_v2_queue_blocked_frame(ngx_http
void ngx_http_v2_init(ngx_event_t *rev);
void ngx_http_v2_request_headers_init(void);
-ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r,
- ngx_http_client_body_handler_pt post_handler);
+ngx_int_t ngx_http_v2_read_request_body(ngx_http_request_t *r);
ngx_int_t ngx_http_v2_read_unbuffered_request_body(ngx_http_request_t *r);
void ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc);
More information about the nginx-devel
mailing list