Mercurial > hg > nginx
comparison src/http/ngx_http_request_body.c @ 8689:6bd8ed493b85 quic
HTTP/3: refactored request body parser.
The change reduces diff to the default branch for
src/http/ngx_http_request_body.c.
Also, client Content-Length, if present, is now checked against the real body
size sent by client.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Mon, 25 Jan 2021 16:16:47 +0300 |
parents | 507da0d3b070 |
children | fac88e160653 |
comparison
equal
deleted
inserted
replaced
8688:a346905c359f | 8689:6bd8ed493b85 |
---|---|
85 rc = ngx_http_v2_read_request_body(r); | 85 rc = ngx_http_v2_read_request_body(r); |
86 goto done; | 86 goto done; |
87 } | 87 } |
88 #endif | 88 #endif |
89 | 89 |
90 #if (NGX_HTTP_V3) | |
91 if (r->http_version == NGX_HTTP_VERSION_30) { | |
92 rc = ngx_http_v3_read_request_body(r); | |
93 goto done; | |
94 } | |
95 #endif | |
96 | |
90 preread = r->header_in->last - r->header_in->pos; | 97 preread = r->header_in->last - r->header_in->pos; |
91 | 98 |
92 if (preread) { | 99 if (preread) { |
93 | 100 |
94 /* there is the pre-read part of the request body */ | 101 /* there is the pre-read part of the request body */ |
218 ngx_int_t rc; | 225 ngx_int_t rc; |
219 | 226 |
220 #if (NGX_HTTP_V2) | 227 #if (NGX_HTTP_V2) |
221 if (r->stream) { | 228 if (r->stream) { |
222 rc = ngx_http_v2_read_unbuffered_request_body(r); | 229 rc = ngx_http_v2_read_unbuffered_request_body(r); |
230 | |
231 if (rc == NGX_OK) { | |
232 r->reading_body = 0; | |
233 } | |
234 | |
235 return rc; | |
236 } | |
237 #endif | |
238 | |
239 #if (NGX_HTTP_V3) | |
240 if (r->http_version == NGX_HTTP_VERSION_30) { | |
241 rc = ngx_http_v3_read_unbuffered_request_body(r); | |
223 | 242 |
224 if (rc == NGX_OK) { | 243 if (rc == NGX_OK) { |
225 r->reading_body = 0; | 244 r->reading_body = 0; |
226 } | 245 } |
227 | 246 |
331 if (n == NGX_AGAIN) { | 350 if (n == NGX_AGAIN) { |
332 break; | 351 break; |
333 } | 352 } |
334 | 353 |
335 if (n == 0) { | 354 if (n == 0) { |
336 rb->buf->last_buf = 1; | 355 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
337 } | 356 "client prematurely closed connection"); |
338 | 357 } |
339 if (n == NGX_ERROR) { | 358 |
359 if (n == 0 || n == NGX_ERROR) { | |
340 c->error = 1; | 360 c->error = 1; |
341 return NGX_HTTP_BAD_REQUEST; | 361 return NGX_HTTP_BAD_REQUEST; |
342 } | 362 } |
343 | 363 |
344 rb->buf->last += n; | 364 rb->buf->last += n; |
581 r->stream->skip_data = 1; | 601 r->stream->skip_data = 1; |
582 return NGX_OK; | 602 return NGX_OK; |
583 } | 603 } |
584 #endif | 604 #endif |
585 | 605 |
586 #if (NGX_HTTP_QUIC) | 606 #if (NGX_HTTP_V3) |
587 if (r->connection->quic) { | 607 if (r->http_version == NGX_HTTP_VERSION_30) { |
588 return NGX_OK; | 608 return NGX_OK; |
589 } | 609 } |
590 #endif | 610 #endif |
591 | 611 |
592 if (ngx_http_test_expect(r) != NGX_OK) { | 612 if (ngx_http_test_expect(r) != NGX_OK) { |
952 | 972 |
953 for (cl = in; cl; cl = cl->next) { | 973 for (cl = in; cl; cl = cl->next) { |
954 | 974 |
955 if (rb->rest == 0) { | 975 if (rb->rest == 0) { |
956 break; | 976 break; |
957 } | |
958 | |
959 size = cl->buf->last - cl->buf->pos; | |
960 | |
961 if (cl->buf->last_buf && (off_t) size < rb->rest) { | |
962 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
963 "client prematurely closed connection"); | |
964 r->connection->error = 1; | |
965 return NGX_HTTP_BAD_REQUEST; | |
966 } | 977 } |
967 | 978 |
968 tl = ngx_chain_get_free_buf(r->pool, &rb->free); | 979 tl = ngx_chain_get_free_buf(r->pool, &rb->free); |
969 if (tl == NULL) { | 980 if (tl == NULL) { |
970 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 981 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
979 b->start = cl->buf->pos; | 990 b->start = cl->buf->pos; |
980 b->pos = cl->buf->pos; | 991 b->pos = cl->buf->pos; |
981 b->last = cl->buf->last; | 992 b->last = cl->buf->last; |
982 b->end = cl->buf->end; | 993 b->end = cl->buf->end; |
983 b->flush = r->request_body_no_buffering; | 994 b->flush = r->request_body_no_buffering; |
995 | |
996 size = cl->buf->last - cl->buf->pos; | |
984 | 997 |
985 if ((off_t) size < rb->rest) { | 998 if ((off_t) size < rb->rest) { |
986 cl->buf->pos = cl->buf->last; | 999 cl->buf->pos = cl->buf->last; |
987 rb->rest -= size; | 1000 rb->rest -= size; |
988 | 1001 |
1051 cl->buf->start, cl->buf->pos, | 1064 cl->buf->start, cl->buf->pos, |
1052 cl->buf->last - cl->buf->pos, | 1065 cl->buf->last - cl->buf->pos, |
1053 cl->buf->file_pos, | 1066 cl->buf->file_pos, |
1054 cl->buf->file_last - cl->buf->file_pos); | 1067 cl->buf->file_last - cl->buf->file_pos); |
1055 | 1068 |
1056 switch (r->http_version) { | 1069 rc = ngx_http_parse_chunked(r, cl->buf, rb->chunked); |
1057 #if (NGX_HTTP_V3) | |
1058 case NGX_HTTP_VERSION_30: | |
1059 rc = ngx_http_v3_parse_request_body(r, cl->buf, rb->chunked); | |
1060 break; | |
1061 #endif | |
1062 | |
1063 default: /* HTTP/1.x */ | |
1064 rc = ngx_http_parse_chunked(r, cl->buf, rb->chunked); | |
1065 } | |
1066 | 1070 |
1067 if (rc == NGX_OK) { | 1071 if (rc == NGX_OK) { |
1068 | 1072 |
1069 /* a chunk has been parsed successfully */ | 1073 /* a chunk has been parsed successfully */ |
1070 | 1074 |
1142 } | 1146 } |
1143 | 1147 |
1144 b->last = cl->buf->pos; | 1148 b->last = cl->buf->pos; |
1145 | 1149 |
1146 continue; | 1150 continue; |
1147 } | |
1148 | |
1149 if (rc == NGX_AGAIN && cl->buf->last_buf) { | |
1150 | |
1151 /* last body buffer */ | |
1152 | |
1153 if (rb->chunked->length > 0) { | |
1154 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, | |
1155 "client prematurely closed connection"); | |
1156 r->connection->error = 1; | |
1157 return NGX_HTTP_BAD_REQUEST; | |
1158 } | |
1159 | |
1160 rc = NGX_DONE; | |
1161 } | 1151 } |
1162 | 1152 |
1163 if (rc == NGX_DONE) { | 1153 if (rc == NGX_DONE) { |
1164 | 1154 |
1165 /* a whole response has been parsed successfully */ | 1155 /* a whole response has been parsed successfully */ |