Ticket #907: body2.patch
| File body2.patch, 26.2 KB (added by , 11 years ago) |
|---|
-
src/http/ngx_http_request.h
diff -r ce946e0976dc -r edacc9766e8e src/http/ngx_http_request.h
a b typedef struct { 284 284 ngx_chain_t *bufs; 285 285 ngx_buf_t *buf; 286 286 off_t rest; 287 #if (NGX_HTTP_V2) 288 off_t received; 289 #endif 287 290 ngx_chain_t *free; 288 291 ngx_chain_t *busy; 289 292 ngx_http_chunked_t *chunked; -
src/http/ngx_http_request_body.c
diff -r ce946e0976dc -r edacc9766e8e src/http/ngx_http_request_body.c
a b ngx_http_read_client_request_body(ngx_ht 34 34 ssize_t size; 35 35 ngx_int_t rc; 36 36 ngx_buf_t *b; 37 ngx_chain_t out , *cl;37 ngx_chain_t out; 38 38 ngx_http_request_body_t *rb; 39 39 ngx_http_core_loc_conf_t *clcf; 40 40 41 41 r->main->count++; 42 42 43 #if (NGX_HTTP_V2)44 if (r->stream && r == r->main) {45 r->request_body_no_buffering = 0;46 rc = ngx_http_v2_read_request_body(r, post_handler);47 goto done;48 }49 #endif50 51 43 if (r != r->main || r->request_body || r->discard_body) { 52 44 r->request_body_no_buffering = 0; 53 45 post_handler(r); 54 46 return NGX_OK; 55 47 } 56 48 49 #if (NGX_HTTP_V2) 50 if (r->stream) { 51 r->request_body_no_buffering = 0; 52 rc = ngx_http_v2_read_request_body(r, post_handler); 53 goto done; 54 } 55 #endif 56 57 57 if (ngx_http_test_expect(r) != NGX_OK) { 58 58 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; 59 59 goto done; 60 60 } 61 61 62 if (r->request_body_no_buffering) {63 r->request_body_in_file_only = 0;64 }65 66 62 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); 67 63 if (rb == NULL) { 68 64 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; … … ngx_http_read_client_request_body(ngx_ht 148 144 149 145 if (rb->rest == 0) { 150 146 /* the whole request body was pre-read */ 151 152 if (r->request_body_in_file_only) {153 if (ngx_http_write_request_body(r) != NGX_OK) {154 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;155 goto done;156 }157 158 if (rb->temp_file->file.offset != 0) {159 160 cl = ngx_chain_get_free_buf(r->pool, &rb->free);161 if (cl == NULL) {162 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;163 goto done;164 }165 166 b = cl->buf;167 168 ngx_memzero(b, sizeof(ngx_buf_t));169 170 b->in_file = 1;171 b->file_last = rb->temp_file->file.offset;172 b->file = &rb->temp_file->file;173 174 rb->bufs = cl;175 }176 }177 178 147 r->request_body_no_buffering = 0; 179 180 148 post_handler(r); 181 182 149 return NGX_OK; 183 150 } 184 151 … … ngx_http_do_read_client_request_body(ngx 289 256 size_t size; 290 257 ssize_t n; 291 258 ngx_int_t rc; 292 ngx_buf_t *b; 293 ngx_chain_t *cl, out; 259 ngx_chain_t out; 294 260 ngx_connection_t *c; 295 261 ngx_http_request_body_t *rb; 296 262 ngx_http_core_loc_conf_t *clcf; … … ngx_http_do_read_client_request_body(ngx 439 405 ngx_del_timer(c->read); 440 406 } 441 407 442 if (rb->temp_file || r->request_body_in_file_only) {443 444 /* save the last part */445 446 if (ngx_http_write_request_body(r) != NGX_OK) {447 return NGX_HTTP_INTERNAL_SERVER_ERROR;448 }449 450 if (rb->temp_file->file.offset != 0) {451 452 cl = ngx_chain_get_free_buf(r->pool, &rb->free);453 if (cl == NULL) {454 return NGX_HTTP_INTERNAL_SERVER_ERROR;455 }456 457 b = cl->buf;458 459 ngx_memzero(b, sizeof(ngx_buf_t));460 461 b->in_file = 1;462 b->file_last = rb->temp_file->file.offset;463 b->file = &rb->temp_file->file;464 465 rb->bufs = cl;466 }467 }468 469 408 if (!r->request_body_no_buffering) { 470 409 r->read_event_handler = ngx_http_block_reading; 471 410 rb->post_handler(r); … … ngx_http_discard_request_body(ngx_http_r 564 503 ngx_int_t rc; 565 504 ngx_event_t *rev; 566 505 506 if (r != r->main || r->discard_body || r->request_body) { 507 return NGX_OK; 508 } 509 567 510 #if (NGX_HTTP_V2) 568 if (r->stream && r == r->main) {569 r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;511 if (r->stream) { 512 r->stream->skip_data = 1; 570 513 return NGX_OK; 571 514 } 572 515 #endif 573 516 574 if (r != r->main || r->discard_body || r->request_body) {575 return NGX_OK;576 }577 578 517 if (ngx_http_test_expect(r) != NGX_OK) { 579 518 return NGX_HTTP_INTERNAL_SERVER_ERROR; 580 519 } … … ngx_http_request_body_chunked_filter(ngx 1127 1066 ngx_int_t 1128 1067 ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) 1129 1068 { 1130 #if (NGX_DEBUG) 1069 ngx_buf_t *b; 1131 1070 ngx_chain_t *cl; 1132 #endif1133 1071 ngx_http_request_body_t *rb; 1134 1072 1135 1073 rb = r->request_body; … … ngx_http_request_body_save_filter(ngx_ht 1166 1104 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1167 1105 } 1168 1106 1169 if (rb->rest > 0 1170 && rb->buf && rb->buf->last == rb->buf->end 1171 && !r->request_body_no_buffering) 1172 { 1107 if (r->request_body_no_buffering) { 1108 return NGX_OK; 1109 } 1110 1111 if (rb->rest > 0) { 1112 1113 if (rb->buf && rb->buf->last == rb->buf->end 1114 && ngx_http_write_request_body(r) != NGX_OK) 1115 { 1116 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1117 } 1118 1119 return NGX_OK; 1120 } 1121 1122 /* rb->rest == 0 */ 1123 1124 if (rb->temp_file || r->request_body_in_file_only) { 1125 1173 1126 if (ngx_http_write_request_body(r) != NGX_OK) { 1174 1127 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1175 1128 } 1129 1130 if (rb->temp_file->file.offset != 0) { 1131 1132 cl = ngx_chain_get_free_buf(r->pool, &rb->free); 1133 if (cl == NULL) { 1134 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1135 } 1136 1137 b = cl->buf; 1138 1139 ngx_memzero(b, sizeof(ngx_buf_t)); 1140 1141 b->in_file = 1; 1142 b->file_last = rb->temp_file->file.offset; 1143 b->file = &rb->temp_file->file; 1144 1145 rb->bufs = cl; 1146 } 1176 1147 } 1177 1148 1178 1149 return NGX_OK; -
src/http/v2/ngx_http_v2.c
diff -r ce946e0976dc -r edacc9766e8e src/http/v2/ngx_http_v2.c
a b 51 51 #define NGX_HTTP_V2_MAX_WINDOW ((1U << 31) - 1) 52 52 #define NGX_HTTP_V2_DEFAULT_WINDOW 65535 53 53 54 #define NGX_HTTP_V2_INITIAL_WINDOW 0 55 54 56 #define NGX_HTTP_V2_ROOT (void *) -1 55 57 56 58 … … static ngx_int_t ngx_http_v2_cookie(ngx_ 163 165 ngx_http_v2_header_t *header); 164 166 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); 165 167 static void ngx_http_v2_run_request(ngx_http_request_t *r); 166 static ngx_int_t ngx_http_v2_init_request_body(ngx_http_request_t *r); 168 static ngx_int_t ngx_http_v2_account_request_body(ngx_http_request_t *r, 169 size_t size, ngx_uint_t last); 170 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, 171 u_char *pos, size_t size, ngx_uint_t last); 167 172 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); 168 173 169 174 static ngx_int_t ngx_http_v2_terminate_stream(ngx_http_v2_connection_t *h2c, … … ngx_http_v2_state_head(ngx_http_v2_conne 754 759 static u_char * 755 760 ngx_http_v2_state_data(ngx_http_v2_connection_t *h2c, u_char *pos, u_char *end) 756 761 { 762 ngx_int_t rc; 757 763 ngx_http_v2_node_t *node; 758 764 ngx_http_v2_stream_t *stream; 759 765 … … ngx_http_v2_state_data(ngx_http_v2_conne 845 851 846 852 stream->recv_window -= h2c->state.length; 847 853 848 if (stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) { 849 854 if (stream->no_flow_control 855 && stream->recv_window < NGX_HTTP_V2_MAX_WINDOW / 4) 856 { 850 857 if (ngx_http_v2_send_window_update(h2c, node->id, 851 858 NGX_HTTP_V2_MAX_WINDOW 852 859 - stream->recv_window) … … ngx_http_v2_state_data(ngx_http_v2_conne 875 882 return ngx_http_v2_state_skip_padded(h2c, pos, end); 876 883 } 877 884 885 stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; 886 887 rc = ngx_http_v2_account_request_body(stream->request, h2c->state.length, 888 stream->in_closed); 889 if (rc != NGX_OK) { 890 stream->skip_data = 1; 891 ngx_http_finalize_request(stream->request, rc); 892 return ngx_http_v2_state_skip_padded(h2c, pos, end); 893 } 894 878 895 h2c->state.stream = stream; 879 896 880 897 return ngx_http_v2_state_read_data(h2c, pos, end); … … static u_char * 885 902 ngx_http_v2_state_read_data(ngx_http_v2_connection_t *h2c, u_char *pos, 886 903 u_char *end) 887 904 { 888 size_t size; 889 ssize_t n; 890 ngx_buf_t *buf; 891 ngx_int_t rc; 892 ngx_temp_file_t *tf; 893 ngx_connection_t *fc; 894 ngx_http_request_t *r; 895 ngx_http_v2_stream_t *stream; 896 ngx_http_request_body_t *rb; 897 ngx_http_core_loc_conf_t *clcf; 905 size_t size; 906 ngx_int_t rc; 907 ngx_uint_t last; 908 ngx_http_v2_stream_t *stream; 898 909 899 910 stream = h2c->state.stream; 900 911 … … ngx_http_v2_state_read_data(ngx_http_v2_ 903 914 } 904 915 905 916 if (stream->skip_data) { 906 stream->in_closed = h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG; 907 908 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, 909 "skipping http2 DATA frame, reason: %d", 910 stream->skip_data); 917 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, 918 "skipping http2 DATA frame"); 911 919 912 920 return ngx_http_v2_state_skip_padded(h2c, pos, end); 913 921 } 914 922 923 last = 0; 915 924 size = end - pos; 916 925 917 if (size > h2c->state.length) {926 if (size >= h2c->state.length) { 918 927 size = h2c->state.length; 919 } 920 921 r = stream->request; 922 923 if (r->request_body == NULL 924 && ngx_http_v2_init_request_body(r) != NGX_OK) 925 { 926 stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; 927 return ngx_http_v2_state_skip_padded(h2c, pos, end); 928 } 929 930 fc = r->connection; 931 rb = r->request_body; 932 tf = rb->temp_file; 933 buf = rb->buf; 934 935 if (size) { 936 rb->rest += size; 937 938 if (r->headers_in.content_length_n != -1 939 && r->headers_in.content_length_n < rb->rest) 940 { 941 ngx_log_error(NGX_LOG_INFO, fc->log, 0, 942 "client intended to send body data " 943 "larger than declared"); 944 945 stream->skip_data = NGX_HTTP_V2_DATA_ERROR; 946 goto error; 947 948 } else { 949 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 950 951 if (clcf->client_max_body_size 952 && clcf->client_max_body_size < rb->rest) 953 { 954 ngx_log_error(NGX_LOG_ERR, fc->log, 0, 955 "client intended to send " 956 "too large chunked body: %O bytes", rb->rest); 957 958 stream->skip_data = NGX_HTTP_V2_DATA_ERROR; 959 goto error; 960 } 961 } 962 963 h2c->state.length -= size; 964 965 if (tf) { 966 buf->start = pos; 967 buf->pos = pos; 968 969 pos += size; 970 971 buf->end = pos; 972 buf->last = pos; 973 974 n = ngx_write_chain_to_temp_file(tf, rb->bufs); 975 976 /* TODO: n == 0 or not complete and level event */ 977 978 if (n == NGX_ERROR) { 979 stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; 980 goto error; 981 } 982 983 tf->offset += n; 984 985 } else { 986 buf->last = ngx_cpymem(buf->last, pos, size); 987 pos += size; 988 } 989 990 r->request_length += size; 991 } 928 last = stream->in_closed; 929 } 930 931 rc = ngx_http_v2_process_request_body(stream->request, pos, size, last); 932 if (rc != NGX_OK) { 933 stream->skip_data = 1; 934 ngx_http_finalize_request(stream->request, rc); 935 } 936 937 pos += size; 938 h2c->state.length -= size; 992 939 993 940 if (h2c->state.length) { 994 if (rb->post_handler) {995 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);996 ngx_add_timer(fc->read, clcf->client_body_timeout);997 }998 999 941 return ngx_http_v2_state_save(h2c, pos, end, 1000 942 ngx_http_v2_state_read_data); 1001 943 } 1002 944 1003 if (h2c->state.flags & NGX_HTTP_V2_END_STREAM_FLAG) {1004 stream->in_closed = 1;1005 1006 if (r->headers_in.content_length_n < 0) {1007 r->headers_in.content_length_n = rb->rest;1008 1009 } else if (r->headers_in.content_length_n != rb->rest) {1010 ngx_log_error(NGX_LOG_INFO, fc->log, 0,1011 "client prematurely closed stream: "1012 "only %O out of %O bytes of request body received",1013 rb->rest, r->headers_in.content_length_n);1014 1015 stream->skip_data = NGX_HTTP_V2_DATA_ERROR;1016 goto error;1017 }1018 1019 if (tf) {1020 ngx_memzero(buf, sizeof(ngx_buf_t));1021 1022 buf->in_file = 1;1023 buf->file_last = tf->file.offset;1024 buf->file = &tf->file;1025 1026 rb->buf = NULL;1027 }1028 1029 if (rb->post_handler) {1030 if (fc->read->timer_set) {1031 ngx_del_timer(fc->read);1032 }1033 1034 r->read_event_handler = ngx_http_block_reading;1035 rb->post_handler(r);1036 }1037 1038 } else if (rb->post_handler) {1039 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);1040 ngx_add_timer(fc->read, clcf->client_body_timeout);1041 }1042 1043 945 if (h2c->state.padding) { 1044 946 return ngx_http_v2_state_skip_padded(h2c, pos, end); 1045 947 } 1046 948 1047 949 return ngx_http_v2_state_complete(h2c, pos, end); 1048 1049 error:1050 1051 if (rb->post_handler) {1052 if (fc->read->timer_set) {1053 ngx_del_timer(fc->read);1054 }1055 1056 if (stream->skip_data == NGX_HTTP_V2_DATA_ERROR) {1057 rc = (r->headers_in.content_length_n == -1)1058 ? NGX_HTTP_REQUEST_ENTITY_TOO_LARGE : NGX_HTTP_BAD_REQUEST;1059 1060 } else {1061 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;1062 }1063 1064 ngx_http_finalize_request(r, rc);1065 }1066 1067 return ngx_http_v2_state_skip_padded(h2c, pos, end);1068 950 } 1069 951 1070 952 … … ngx_http_v2_send_settings(ngx_http_v2_co 2556 2438 buf->last = ngx_http_v2_write_uint16(buf->last, 2557 2439 NGX_HTTP_V2_INIT_WINDOW_SIZE_SETTING); 2558 2440 buf->last = ngx_http_v2_write_uint32(buf->last, 2559 NGX_HTTP_V2_ MAX_WINDOW);2441 NGX_HTTP_V2_INITIAL_WINDOW); 2560 2442 2561 2443 buf->last = ngx_http_v2_write_uint16(buf->last, 2562 2444 NGX_HTTP_V2_MAX_FRAME_SIZE_SETTING); … … ngx_http_v2_create_stream(ngx_http_v2_co 2867 2749 stream->connection = h2c; 2868 2750 2869 2751 stream->send_window = h2c->init_window; 2870 stream->recv_window = NGX_HTTP_V2_ MAX_WINDOW;2752 stream->recv_window = NGX_HTTP_V2_INITIAL_WINDOW; 2871 2753 2872 2754 h2c->processing++; 2873 2755 … … ngx_http_v2_run_request(ngx_http_request 3504 3386 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 3505 3387 "client prematurely closed stream"); 3506 3388 3507 r->stream->skip_data = NGX_HTTP_V2_DATA_ERROR;3389 r->stream->skip_data = 1; 3508 3390 3509 3391 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); 3510 3392 return; … … ngx_http_v2_run_request(ngx_http_request 3514 3396 } 3515 3397 3516 3398 3517 static ngx_int_t3518 ngx_http_v2_init_request_body(ngx_http_request_t *r)3519 {3520 ngx_buf_t *buf;3521 ngx_temp_file_t *tf;3522 ngx_http_request_body_t *rb;3523 ngx_http_core_loc_conf_t *clcf;3524 3525 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));3526 if (rb == NULL) {3527 return NGX_ERROR;3528 }3529 3530 r->request_body = rb;3531 3532 if (r->stream->in_closed) {3533 return NGX_OK;3534 }3535 3536 rb->rest = r->headers_in.content_length_n;3537 3538 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);3539 3540 if (r->request_body_in_file_only3541 || rb->rest > (off_t) clcf->client_body_buffer_size3542 || rb->rest < 0)3543 {3544 tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));3545 if (tf == NULL) {3546 return NGX_ERROR;3547 }3548 3549 tf->file.fd = NGX_INVALID_FILE;3550 tf->file.log = r->connection->log;3551 tf->path = clcf->client_body_temp_path;3552 tf->pool = r->pool;3553 tf->warn = "a client request body is buffered to a temporary file";3554 tf->log_level = r->request_body_file_log_level;3555 tf->persistent = r->request_body_in_persistent_file;3556 tf->clean = r->request_body_in_clean_file;3557 3558 if (r->request_body_file_group_access) {3559 tf->access = 0660;3560 }3561 3562 rb->temp_file = tf;3563 3564 if (r->stream->in_closed3565 && ngx_create_temp_file(&tf->file, tf->path, tf->pool,3566 tf->persistent, tf->clean, tf->access)3567 != NGX_OK)3568 {3569 return NGX_ERROR;3570 }3571 3572 buf = ngx_calloc_buf(r->pool);3573 if (buf == NULL) {3574 return NGX_ERROR;3575 }3576 3577 } else {3578 3579 if (rb->rest == 0) {3580 return NGX_OK;3581 }3582 3583 buf = ngx_create_temp_buf(r->pool, (size_t) rb->rest);3584 if (buf == NULL) {3585 return NGX_ERROR;3586 }3587 }3588 3589 rb->buf = buf;3590 3591 rb->bufs = ngx_alloc_chain_link(r->pool);3592 if (rb->bufs == NULL) {3593 return NGX_ERROR;3594 }3595 3596 rb->bufs->buf = buf;3597 rb->bufs->next = NULL;3598 3599 rb->rest = 0;3600 3601 return NGX_OK;3602 }3603 3604 3605 3399 ngx_int_t 3606 3400 ngx_http_v2_read_request_body(ngx_http_request_t *r, 3607 3401 ngx_http_client_body_handler_pt post_handler) 3608 3402 { 3403 off_t len; 3609 3404 ngx_http_v2_stream_t *stream; 3405 ngx_http_request_body_t *rb; 3610 3406 ngx_http_core_loc_conf_t *clcf; 3611 3407 3612 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,3613 "http2 read request body");3614 3615 3408 stream = r->stream; 3616 3409 3617 switch (stream->skip_data) { 3618 3619 case NGX_HTTP_V2_DATA_DISCARD: 3620 post_handler(r); 3410 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); 3411 if (rb == NULL) { 3412 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3413 } 3414 3415 /* 3416 * set by ngx_pcalloc(): 3417 * 3418 * rb->bufs = NULL; 3419 * rb->buf = NULL; 3420 * rb->received = 0; 3421 * rb->free = NULL; 3422 * rb->busy = NULL; 3423 */ 3424 3425 rb->post_handler = post_handler; 3426 3427 r->request_body = rb; 3428 3429 if (stream->skip_data) { 3430 return NGX_HTTP_BAD_REQUEST; 3431 } 3432 3433 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 3434 3435 len = r->headers_in.content_length_n; 3436 3437 if (stream->in_closed && len < 0) { 3438 len = 0; 3439 } 3440 3441 if (len != 0) { 3442 if (len < 0 3443 || len > (off_t) clcf->client_body_buffer_size 3444 || r->request_body_in_file_only) 3445 { 3446 rb->buf = ngx_calloc_buf(r->pool); 3447 3448 if (rb->buf != NULL) { 3449 rb->buf->memory = 1; 3450 rb->buf->sync = 1; 3451 } 3452 3453 } else { 3454 rb->buf = ngx_create_temp_buf(r->pool, (size_t) len); 3455 } 3456 3457 if (rb->buf == NULL) { 3458 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3459 } 3460 } 3461 3462 if (stream->in_closed) { 3463 return ngx_http_v2_process_request_body(r, NULL, 0, 1); 3464 } 3465 3466 stream->recv_window = NGX_HTTP_V2_MAX_WINDOW; 3467 3468 if (ngx_http_v2_send_window_update(stream->connection, stream->node->id, 3469 stream->recv_window) 3470 == NGX_ERROR) 3471 { 3472 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3473 } 3474 3475 stream->no_flow_control = 1; 3476 3477 ngx_add_timer(r->connection->read, clcf->client_body_timeout); 3478 3479 r->read_event_handler = ngx_http_v2_read_client_request_body_handler; 3480 r->write_event_handler = ngx_http_request_empty_handler; 3481 3482 return NGX_AGAIN; 3483 } 3484 3485 3486 static ngx_int_t 3487 ngx_http_v2_account_request_body(ngx_http_request_t *r, size_t size, 3488 ngx_uint_t last) 3489 { 3490 ngx_http_request_body_t *rb; 3491 ngx_http_core_loc_conf_t *clcf; 3492 3493 rb = r->request_body; 3494 3495 if (rb == NULL) { 3621 3496 return NGX_OK; 3622 3623 case NGX_HTTP_V2_DATA_ERROR: 3624 if (r->headers_in.content_length_n == -1) { 3625 return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; 3626 } else { 3497 } 3498 3499 if (size) { 3500 r->request_length += size; 3501 rb->received += size; 3502 3503 if (r->headers_in.content_length_n != -1 3504 && r->headers_in.content_length_n < rb->received) 3505 { 3506 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 3507 "client intended to send body data " 3508 "larger than declared"); 3509 3627 3510 return NGX_HTTP_BAD_REQUEST; 3628 3511 } 3629 3512 3630 case NGX_HTTP_V2_DATA_INTERNAL_ERROR: 3631 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3632 } 3633 3634 if (!r->request_body && ngx_http_v2_init_request_body(r) != NGX_OK) { 3635 stream->skip_data = NGX_HTTP_V2_DATA_INTERNAL_ERROR; 3636 return NGX_HTTP_INTERNAL_SERVER_ERROR; 3637 } 3638 3639 if (stream->in_closed) { 3640 post_handler(r); 3513 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 3514 3515 if (clcf->client_max_body_size 3516 && clcf->client_max_body_size < rb->received) 3517 { 3518 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, 3519 "client intended to send too large chunked body: " 3520 "%O bytes", rb->received); 3521 3522 return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; 3523 } 3524 } 3525 3526 if (last) { 3527 if (r->headers_in.content_length_n != -1 3528 && r->headers_in.content_length_n != rb->received) 3529 { 3530 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, 3531 "client prematurely closed stream: " 3532 "only %O out of %O bytes of request body received", 3533 rb->received, r->headers_in.content_length_n); 3534 3535 return NGX_HTTP_BAD_REQUEST; 3536 } 3537 } 3538 3539 return NGX_OK; 3540 } 3541 3542 3543 static ngx_int_t 3544 ngx_http_v2_process_request_body(ngx_http_request_t *r, u_char *pos, 3545 size_t size, ngx_uint_t last) 3546 { 3547 ngx_buf_t *buf; 3548 ngx_int_t rc; 3549 ngx_chain_t out; 3550 ngx_connection_t *fc; 3551 ngx_http_request_body_t *rb; 3552 ngx_http_core_loc_conf_t *clcf; 3553 3554 fc = r->connection; 3555 rb = r->request_body; 3556 3557 if (rb == NULL) { 3641 3558 return NGX_OK; 3642 3559 } 3643 3560 3644 r->request_body->post_handler = post_handler; 3645 3646 r->read_event_handler = ngx_http_v2_read_client_request_body_handler; 3647 r->write_event_handler = ngx_http_request_empty_handler; 3561 rb->rest = !last; 3562 3563 buf = rb->buf; 3564 3565 if (size) { 3566 if (buf->sync) { 3567 buf->start = pos; 3568 buf->pos = pos; 3569 3570 pos += size; 3571 3572 buf->end = pos; 3573 buf->last = pos; 3574 3575 buf->last_buf = last; 3576 3577 out.buf = buf; 3578 out.next = NULL; 3579 3580 rc = ngx_http_top_request_body_filter(r, &out); 3581 3582 if (rc != NGX_OK) { 3583 return rc; 3584 } 3585 3586 } else { 3587 buf->last = ngx_cpymem(buf->last, pos, size); 3588 } 3589 } 3590 3591 if (last) { 3592 if (r->headers_in.content_length_n < 0) { 3593 r->headers_in.content_length_n = rb->received; 3594 } 3595 3596 if (buf) { 3597 if (buf->sync) { 3598 /* prevent reusing this buffer in the upstream module */ 3599 rb->buf = NULL; 3600 3601 rc = size ? NGX_OK : ngx_http_top_request_body_filter(r, NULL); 3602 3603 } else { 3604 buf->last_buf = 1; 3605 3606 out.buf = buf; 3607 out.next = NULL; 3608 3609 rc = ngx_http_top_request_body_filter(r, &out); 3610 } 3611 3612 } else { 3613 rc = ngx_http_top_request_body_filter(r, NULL); 3614 } 3615 3616 if (rc != NGX_OK) { 3617 return rc; 3618 } 3619 3620 if (fc->read->timer_set) { 3621 ngx_del_timer(fc->read); 3622 } 3623 3624 r->read_event_handler = ngx_http_block_reading; 3625 rb->post_handler(r); 3626 3627 return NGX_OK; 3628 } 3648 3629 3649 3630 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 3650 ngx_add_timer( r->connection->read, clcf->client_body_timeout);3651 3652 return NGX_ AGAIN;3631 ngx_add_timer(fc->read, clcf->client_body_timeout); 3632 3633 return NGX_OK; 3653 3634 } 3654 3635 3655 3636 … … ngx_http_v2_read_client_request_body_han 3667 3648 ngx_log_error(NGX_LOG_INFO, fc->log, NGX_ETIMEDOUT, "client timed out"); 3668 3649 3669 3650 fc->timedout = 1; 3670 r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;3651 r->stream->skip_data = 1; 3671 3652 3672 3653 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); 3673 3654 return; … … ngx_http_v2_read_client_request_body_han 3677 3658 ngx_log_error(NGX_LOG_INFO, fc->log, 0, 3678 3659 "client prematurely closed stream"); 3679 3660 3680 r->stream->skip_data = NGX_HTTP_V2_DATA_DISCARD;3661 r->stream->skip_data = 1; 3681 3662 3682 3663 ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST); 3683 3664 return; -
src/http/v2/ngx_http_v2.h
diff -r ce946e0976dc -r edacc9766e8e src/http/v2/ngx_http_v2.h
a b struct ngx_http_v2_stream_s { 194 194 unsigned exhausted:1; 195 195 unsigned in_closed:1; 196 196 unsigned out_closed:1; 197 unsigned skip_data:2; 197 unsigned no_flow_control:1; 198 unsigned skip_data:1; 198 199 }; 199 200 200 201
