comparison src/http/ngx_http_request_body.c @ 8510:532fe796b0e2 quic

Merged with the default branch.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 18 Aug 2020 16:22:00 +0300
parents e5d4f057a6cb f5a2af0e7079
children 357b8afe915e
comparison
equal deleted inserted replaced
8509:bce9e9643444 8510:532fe796b0e2
10 #include <ngx_http.h> 10 #include <ngx_http.h>
11 11
12 12
13 static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r); 13 static void ngx_http_read_client_request_body_handler(ngx_http_request_t *r);
14 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r); 14 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r);
15 static ngx_int_t ngx_http_copy_pipelined_header(ngx_http_request_t *r,
16 ngx_buf_t *buf);
15 static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r); 17 static ngx_int_t ngx_http_write_request_body(ngx_http_request_t *r);
16 static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r); 18 static ngx_int_t ngx_http_read_discarded_request_body(ngx_http_request_t *r);
17 static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r, 19 static ngx_int_t ngx_http_discard_request_body_filter(ngx_http_request_t *r,
18 ngx_buf_t *b); 20 ngx_buf_t *b);
19 static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r); 21 static ngx_int_t ngx_http_test_expect(ngx_http_request_t *r);
280 282
281 for ( ;; ) { 283 for ( ;; ) {
282 for ( ;; ) { 284 for ( ;; ) {
283 if (rb->buf->last == rb->buf->end) { 285 if (rb->buf->last == rb->buf->end) {
284 286
285 if (rb->buf->pos != rb->buf->last) { 287 /* update chains */
286 288
287 /* pass buffer to request body filter chain */ 289 rc = ngx_http_request_body_filter(r, NULL);
288 290
289 out.buf = rb->buf; 291 if (rc != NGX_OK) {
290 out.next = NULL; 292 return rc;
291
292 rc = ngx_http_request_body_filter(r, &out);
293
294 if (rc != NGX_OK) {
295 return rc;
296 }
297
298 } else {
299
300 /* update chains */
301
302 rc = ngx_http_request_body_filter(r, NULL);
303
304 if (rc != NGX_OK) {
305 return rc;
306 }
307 } 293 }
308 294
309 if (rb->busy != NULL) { 295 if (rb->busy != NULL) {
310 if (r->request_body_no_buffering) { 296 if (r->request_body_no_buffering) {
311 if (c->read->timer_set) { 297 if (c->read->timer_set) {
352 } 338 }
353 339
354 rb->buf->last += n; 340 rb->buf->last += n;
355 r->request_length += n; 341 r->request_length += n;
356 342
357 if (n == rest || n == 0) { 343 /* pass buffer to request body filter chain */
358 /* pass buffer to request body filter chain */ 344
359 345 out.buf = rb->buf;
360 out.buf = rb->buf; 346 out.next = NULL;
361 out.next = NULL; 347
362 348 rc = ngx_http_request_body_filter(r, &out);
363 rc = ngx_http_request_body_filter(r, &out); 349
364 350 if (rc != NGX_OK) {
365 if (rc != NGX_OK) { 351 return rc;
366 return rc;
367 }
368 } 352 }
369 353
370 if (rb->rest == 0) { 354 if (rb->rest == 0) {
371 break; 355 break;
372 } 356 }
383 break; 367 break;
384 } 368 }
385 369
386 if (!c->read->ready) { 370 if (!c->read->ready) {
387 371
388 if (r->request_body_no_buffering
389 && rb->buf->pos != rb->buf->last)
390 {
391 /* pass buffer to request body filter chain */
392
393 out.buf = rb->buf;
394 out.next = NULL;
395
396 rc = ngx_http_request_body_filter(r, &out);
397
398 if (rc != NGX_OK) {
399 return rc;
400 }
401 }
402
403 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 372 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
404 ngx_add_timer(c->read, clcf->client_body_timeout); 373 ngx_add_timer(c->read, clcf->client_body_timeout);
405 374
406 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { 375 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
407 return NGX_HTTP_INTERNAL_SERVER_ERROR; 376 return NGX_HTTP_INTERNAL_SERVER_ERROR;
408 } 377 }
409 378
410 return NGX_AGAIN; 379 return NGX_AGAIN;
411 } 380 }
381 }
382
383 if (ngx_http_copy_pipelined_header(r, rb->buf) != NGX_OK) {
384 return NGX_HTTP_INTERNAL_SERVER_ERROR;
412 } 385 }
413 386
414 if (c->read->timer_set) { 387 if (c->read->timer_set) {
415 ngx_del_timer(c->read); 388 ngx_del_timer(c->read);
416 } 389 }
417 390
418 if (!r->request_body_no_buffering) { 391 if (!r->request_body_no_buffering) {
419 r->read_event_handler = ngx_http_block_reading; 392 r->read_event_handler = ngx_http_block_reading;
420 rb->post_handler(r); 393 rb->post_handler(r);
421 } 394 }
395
396 return NGX_OK;
397 }
398
399
400 static ngx_int_t
401 ngx_http_copy_pipelined_header(ngx_http_request_t *r, ngx_buf_t *buf)
402 {
403 size_t n;
404 ngx_buf_t *b;
405 ngx_chain_t *cl;
406 ngx_http_connection_t *hc;
407 ngx_http_core_srv_conf_t *cscf;
408
409 b = r->header_in;
410 n = buf->last - buf->pos;
411
412 if (buf == b || n == 0) {
413 return NGX_OK;
414 }
415
416 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
417 "http body pipelined header: %uz", n);
418
419 /*
420 * if there is a pipelined request in the client body buffer,
421 * copy it to the r->header_in buffer if there is enough room,
422 * or allocate a large client header buffer
423 */
424
425 if (n > (size_t) (b->end - b->last)) {
426
427 hc = r->http_connection;
428
429 if (hc->free) {
430 cl = hc->free;
431 hc->free = cl->next;
432
433 b = cl->buf;
434
435 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
436 "http large header free: %p %uz",
437 b->pos, b->end - b->last);
438
439 } else {
440 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
441
442 b = ngx_create_temp_buf(r->connection->pool,
443 cscf->large_client_header_buffers.size);
444 if (b == NULL) {
445 return NGX_ERROR;
446 }
447
448 cl = ngx_alloc_chain_link(r->connection->pool);
449 if (cl == NULL) {
450 return NGX_ERROR;
451 }
452
453 cl->buf = b;
454
455 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
456 "http large header alloc: %p %uz",
457 b->pos, b->end - b->last);
458 }
459
460 cl->next = hc->busy;
461 hc->busy = cl;
462 hc->nbusy++;
463
464 r->header_in = b;
465
466 if (n > (size_t) (b->end - b->last)) {
467 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
468 "too large pipelined header after reading body");
469 return NGX_ERROR;
470 }
471 }
472
473 ngx_memcpy(b->last, buf->pos, n);
474
475 b->last += n;
476 r->request_length -= n;
422 477
423 return NGX_OK; 478 return NGX_OK;
424 } 479 }
425 480
426 481
667 722
668 b.temporary = 1; 723 b.temporary = 1;
669 724
670 for ( ;; ) { 725 for ( ;; ) {
671 if (r->headers_in.content_length_n == 0) { 726 if (r->headers_in.content_length_n == 0) {
672 r->read_event_handler = ngx_http_block_reading; 727 break;
673 return NGX_OK;
674 } 728 }
675 729
676 if (!r->connection->read->ready) { 730 if (!r->connection->read->ready) {
677 return NGX_AGAIN; 731 return NGX_AGAIN;
678 } 732 }
702 756
703 if (rc != NGX_OK) { 757 if (rc != NGX_OK) {
704 return rc; 758 return rc;
705 } 759 }
706 } 760 }
761
762 if (ngx_http_copy_pipelined_header(r, &b) != NGX_OK) {
763 return NGX_HTTP_INTERNAL_SERVER_ERROR;
764 }
765
766 r->read_event_handler = ngx_http_block_reading;
767
768 return NGX_OK;
707 } 769 }
708 770
709 771
710 static ngx_int_t 772 static ngx_int_t
711 ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b) 773 ngx_http_discard_request_body_filter(ngx_http_request_t *r, ngx_buf_t *b)
712 { 774 {
713 size_t size; 775 size_t size;
714 ngx_int_t rc; 776 ngx_int_t rc;
715 ngx_http_request_body_t *rb; 777 ngx_http_request_body_t *rb;
778 ngx_http_core_srv_conf_t *cscf;
716 779
717 if (r->headers_in.chunked) { 780 if (r->headers_in.chunked) {
718 781
719 rb = r->request_body; 782 rb = r->request_body;
720 783
774 837
775 if (rc == NGX_AGAIN) { 838 if (rc == NGX_AGAIN) {
776 839
777 /* set amount of data we want to see next time */ 840 /* set amount of data we want to see next time */
778 841
779 r->headers_in.content_length_n = rb->chunked->length; 842 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
843
844 r->headers_in.content_length_n = ngx_max(rb->chunked->length,
845 (off_t) cscf->large_client_header_buffers.size);
780 break; 846 break;
781 } 847 }
782 848
783 /* invalid */ 849 /* invalid */
784 850
943 ngx_int_t rc; 1009 ngx_int_t rc;
944 ngx_buf_t *b; 1010 ngx_buf_t *b;
945 ngx_chain_t *cl, *out, *tl, **ll; 1011 ngx_chain_t *cl, *out, *tl, **ll;
946 ngx_http_request_body_t *rb; 1012 ngx_http_request_body_t *rb;
947 ngx_http_core_loc_conf_t *clcf; 1013 ngx_http_core_loc_conf_t *clcf;
1014 ngx_http_core_srv_conf_t *cscf;
948 1015
949 rb = r->request_body; 1016 rb = r->request_body;
950 1017
951 if (rb->rest == -1) { 1018 if (rb->rest == -1) {
952 1019
956 rb->chunked = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_t)); 1023 rb->chunked = ngx_pcalloc(r->pool, sizeof(ngx_http_chunked_t));
957 if (rb->chunked == NULL) { 1024 if (rb->chunked == NULL) {
958 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1025 return NGX_HTTP_INTERNAL_SERVER_ERROR;
959 } 1026 }
960 1027
1028 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1029
961 r->headers_in.content_length_n = 0; 1030 r->headers_in.content_length_n = 0;
1031 rb->rest = cscf->large_client_header_buffers.size;
962 1032
963 #if (NGX_HTTP_V3) 1033 #if (NGX_HTTP_V3)
964 if (r->http_version == NGX_HTTP_VERSION_30) { 1034 if (r->http_version == NGX_HTTP_VERSION_30) {
965 rb->rest = 1; 1035 rb->rest = 1;
966 1036 }
967 } else
968 #endif 1037 #endif
969 {
970 rb->rest = 3;
971 }
972 } 1038 }
973 1039
974 out = NULL; 1040 out = NULL;
975 ll = &out; 1041 ll = &out;
976 1042
977 for (cl = in; cl; cl = cl->next) { 1043 for (cl = in; cl; cl = cl->next) {
1044
1045 b = NULL;
978 1046
979 for ( ;; ) { 1047 for ( ;; ) {
980 1048
981 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, 1049 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
982 "http body chunked buf " 1050 "http body chunked buf "
1017 r->lingering_close = 1; 1085 r->lingering_close = 1;
1018 1086
1019 return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; 1087 return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
1020 } 1088 }
1021 1089
1090 if (b
1091 && rb->chunked->size <= 128
1092 && cl->buf->last - cl->buf->pos >= rb->chunked->size)
1093 {
1094 r->headers_in.content_length_n += rb->chunked->size;
1095
1096 if (rb->chunked->size < 8) {
1097
1098 while (rb->chunked->size) {
1099 *b->last++ = *cl->buf->pos++;
1100 rb->chunked->size--;
1101 }
1102
1103 } else {
1104 ngx_memmove(b->last, cl->buf->pos, rb->chunked->size);
1105 b->last += rb->chunked->size;
1106 cl->buf->pos += rb->chunked->size;
1107 rb->chunked->size = 0;
1108 }
1109
1110 continue;
1111 }
1112
1022 tl = ngx_chain_get_free_buf(r->pool, &rb->free); 1113 tl = ngx_chain_get_free_buf(r->pool, &rb->free);
1023 if (tl == NULL) { 1114 if (tl == NULL) {
1024 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1115 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1025 } 1116 }
1026 1117
1082 1173
1083 if (rc == NGX_AGAIN) { 1174 if (rc == NGX_AGAIN) {
1084 1175
1085 /* set rb->rest, amount of data we want to see next time */ 1176 /* set rb->rest, amount of data we want to see next time */
1086 1177
1087 rb->rest = rb->chunked->length; 1178 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1179
1180 rb->rest = ngx_max(rb->chunked->length,
1181 (off_t) cscf->large_client_header_buffers.size);
1088 1182
1089 break; 1183 break;
1090 } 1184 }
1091 1185
1092 /* invalid */ 1186 /* invalid */