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 */