Mercurial > hg > nginx
comparison src/http/ngx_http_request_body.c @ 8839:fac88e160653 quic
Merged with the default branch.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Wed, 01 Sep 2021 10:57:25 +0300 |
parents | 6bd8ed493b85 9cf043a5d9ca |
children | 61d0fa67b55e |
comparison
equal
deleted
inserted
replaced
8838:d6e191a583cc | 8839:fac88e160653 |
---|---|
60 } | 60 } |
61 | 61 |
62 /* | 62 /* |
63 * set by ngx_pcalloc(): | 63 * set by ngx_pcalloc(): |
64 * | 64 * |
65 * rb->temp_file = NULL; | |
65 * rb->bufs = NULL; | 66 * rb->bufs = NULL; |
66 * rb->buf = NULL; | 67 * rb->buf = NULL; |
67 * rb->free = NULL; | 68 * rb->free = NULL; |
68 * rb->busy = NULL; | 69 * rb->busy = NULL; |
69 * rb->chunked = NULL; | 70 * rb->chunked = NULL; |
71 * rb->received = 0; | |
72 * rb->filter_need_buffering = 0; | |
73 * rb->last_sent = 0; | |
74 * rb->last_saved = 0; | |
70 */ | 75 */ |
71 | 76 |
72 rb->rest = -1; | 77 rb->rest = -1; |
73 rb->post_handler = post_handler; | 78 rb->post_handler = post_handler; |
74 | 79 |
149 if (rc != NGX_OK) { | 154 if (rc != NGX_OK) { |
150 goto done; | 155 goto done; |
151 } | 156 } |
152 } | 157 } |
153 | 158 |
154 if (rb->rest == 0) { | 159 if (rb->rest == 0 && rb->last_saved) { |
155 /* the whole request body was pre-read */ | 160 /* the whole request body was pre-read */ |
156 r->request_body_no_buffering = 0; | 161 r->request_body_no_buffering = 0; |
157 post_handler(r); | 162 post_handler(r); |
158 return NGX_OK; | 163 return NGX_OK; |
159 } | 164 } |
177 | 182 |
178 if (r->request_body_in_single_buf) { | 183 if (r->request_body_in_single_buf) { |
179 size += preread; | 184 size += preread; |
180 } | 185 } |
181 | 186 |
187 if (size == 0) { | |
188 size++; | |
189 } | |
190 | |
182 } else { | 191 } else { |
183 size = clcf->client_body_buffer_size; | 192 size = clcf->client_body_buffer_size; |
184 } | 193 } |
185 | 194 |
186 rb->buf = ngx_create_temp_buf(r->pool, size); | 195 rb->buf = ngx_create_temp_buf(r->pool, size); |
287 { | 296 { |
288 off_t rest; | 297 off_t rest; |
289 size_t size; | 298 size_t size; |
290 ssize_t n; | 299 ssize_t n; |
291 ngx_int_t rc; | 300 ngx_int_t rc; |
301 ngx_uint_t flush; | |
292 ngx_chain_t out; | 302 ngx_chain_t out; |
293 ngx_connection_t *c; | 303 ngx_connection_t *c; |
294 ngx_http_request_body_t *rb; | 304 ngx_http_request_body_t *rb; |
295 ngx_http_core_loc_conf_t *clcf; | 305 ngx_http_core_loc_conf_t *clcf; |
296 | 306 |
297 c = r->connection; | 307 c = r->connection; |
298 rb = r->request_body; | 308 rb = r->request_body; |
309 flush = 1; | |
299 | 310 |
300 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | 311 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
301 "http read client request body"); | 312 "http read client request body"); |
302 | 313 |
303 for ( ;; ) { | 314 for ( ;; ) { |
304 for ( ;; ) { | 315 for ( ;; ) { |
316 if (rb->rest == 0) { | |
317 break; | |
318 } | |
319 | |
305 if (rb->buf->last == rb->buf->end) { | 320 if (rb->buf->last == rb->buf->end) { |
306 | 321 |
307 /* update chains */ | 322 /* update chains */ |
308 | 323 |
309 rc = ngx_http_request_body_filter(r, NULL); | 324 rc = ngx_http_request_body_filter(r, NULL); |
323 } | 338 } |
324 | 339 |
325 return NGX_AGAIN; | 340 return NGX_AGAIN; |
326 } | 341 } |
327 | 342 |
343 if (rb->filter_need_buffering) { | |
344 clcf = ngx_http_get_module_loc_conf(r, | |
345 ngx_http_core_module); | |
346 ngx_add_timer(c->read, clcf->client_body_timeout); | |
347 | |
348 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | |
349 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
350 } | |
351 | |
352 return NGX_AGAIN; | |
353 } | |
354 | |
328 ngx_log_error(NGX_LOG_ALERT, c->log, 0, | 355 ngx_log_error(NGX_LOG_ALERT, c->log, 0, |
329 "busy buffers after request body flush"); | 356 "busy buffers after request body flush"); |
330 | 357 |
331 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 358 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
332 } | 359 } |
333 | 360 |
361 flush = 0; | |
334 rb->buf->pos = rb->buf->start; | 362 rb->buf->pos = rb->buf->start; |
335 rb->buf->last = rb->buf->start; | 363 rb->buf->last = rb->buf->start; |
336 } | 364 } |
337 | 365 |
338 size = rb->buf->end - rb->buf->last; | 366 size = rb->buf->end - rb->buf->last; |
339 rest = rb->rest - (rb->buf->last - rb->buf->pos); | 367 rest = rb->rest - (rb->buf->last - rb->buf->pos); |
340 | 368 |
341 if ((off_t) size > rest) { | 369 if ((off_t) size > rest) { |
342 size = (size_t) rest; | 370 size = (size_t) rest; |
371 } | |
372 | |
373 if (size == 0) { | |
374 break; | |
343 } | 375 } |
344 | 376 |
345 n = c->recv(c, rb->buf->last, size); | 377 n = c->recv(c, rb->buf->last, size); |
346 | 378 |
347 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 379 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
364 rb->buf->last += n; | 396 rb->buf->last += n; |
365 r->request_length += n; | 397 r->request_length += n; |
366 | 398 |
367 /* pass buffer to request body filter chain */ | 399 /* pass buffer to request body filter chain */ |
368 | 400 |
401 flush = 0; | |
369 out.buf = rb->buf; | 402 out.buf = rb->buf; |
370 out.next = NULL; | 403 out.next = NULL; |
371 | 404 |
372 rc = ngx_http_request_body_filter(r, &out); | 405 rc = ngx_http_request_body_filter(r, &out); |
373 | 406 |
385 } | 418 } |
386 | 419 |
387 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | 420 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, |
388 "http client request body rest %O", rb->rest); | 421 "http client request body rest %O", rb->rest); |
389 | 422 |
390 if (rb->rest == 0) { | 423 if (flush) { |
424 rc = ngx_http_request_body_filter(r, NULL); | |
425 | |
426 if (rc != NGX_OK) { | |
427 return rc; | |
428 } | |
429 } | |
430 | |
431 if (rb->rest == 0 && rb->last_saved) { | |
391 break; | 432 break; |
392 } | 433 } |
393 | 434 |
394 if (!c->read->ready) { | 435 if (!c->read->ready || rb->rest == 0) { |
395 | 436 |
396 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | 437 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
397 ngx_add_timer(c->read, clcf->client_body_timeout); | 438 ngx_add_timer(c->read, clcf->client_body_timeout); |
398 | 439 |
399 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | 440 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { |
958 ngx_chain_t *cl, *tl, *out, **ll; | 999 ngx_chain_t *cl, *tl, *out, **ll; |
959 ngx_http_request_body_t *rb; | 1000 ngx_http_request_body_t *rb; |
960 | 1001 |
961 rb = r->request_body; | 1002 rb = r->request_body; |
962 | 1003 |
1004 out = NULL; | |
1005 ll = &out; | |
1006 | |
963 if (rb->rest == -1) { | 1007 if (rb->rest == -1) { |
964 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1008 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
965 "http request body content length filter"); | 1009 "http request body content length filter"); |
966 | 1010 |
967 rb->rest = r->headers_in.content_length_n; | 1011 rb->rest = r->headers_in.content_length_n; |
968 } | 1012 |
969 | 1013 if (rb->rest == 0) { |
970 out = NULL; | 1014 |
971 ll = &out; | 1015 tl = ngx_chain_get_free_buf(r->pool, &rb->free); |
1016 if (tl == NULL) { | |
1017 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1018 } | |
1019 | |
1020 b = tl->buf; | |
1021 | |
1022 ngx_memzero(b, sizeof(ngx_buf_t)); | |
1023 | |
1024 b->last_buf = 1; | |
1025 | |
1026 *ll = tl; | |
1027 ll = &tl->next; | |
1028 } | |
1029 } | |
972 | 1030 |
973 for (cl = in; cl; cl = cl->next) { | 1031 for (cl = in; cl; cl = cl->next) { |
974 | 1032 |
975 if (rb->rest == 0) { | 1033 if (rb->rest == 0) { |
976 break; | 1034 break; |
1030 ngx_http_core_loc_conf_t *clcf; | 1088 ngx_http_core_loc_conf_t *clcf; |
1031 ngx_http_core_srv_conf_t *cscf; | 1089 ngx_http_core_srv_conf_t *cscf; |
1032 | 1090 |
1033 rb = r->request_body; | 1091 rb = r->request_body; |
1034 | 1092 |
1093 out = NULL; | |
1094 ll = &out; | |
1095 | |
1035 if (rb->rest == -1) { | 1096 if (rb->rest == -1) { |
1036 | 1097 |
1037 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | 1098 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
1038 "http request body chunked filter"); | 1099 "http request body chunked filter"); |
1039 | 1100 |
1045 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | 1106 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
1046 | 1107 |
1047 r->headers_in.content_length_n = 0; | 1108 r->headers_in.content_length_n = 0; |
1048 rb->rest = cscf->large_client_header_buffers.size; | 1109 rb->rest = cscf->large_client_header_buffers.size; |
1049 } | 1110 } |
1050 | |
1051 out = NULL; | |
1052 ll = &out; | |
1053 | 1111 |
1054 for (cl = in; cl; cl = cl->next) { | 1112 for (cl = in; cl; cl = cl->next) { |
1055 | 1113 |
1056 b = NULL; | 1114 b = NULL; |
1057 | 1115 |
1205 | 1263 |
1206 ngx_int_t | 1264 ngx_int_t |
1207 ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) | 1265 ngx_http_request_body_save_filter(ngx_http_request_t *r, ngx_chain_t *in) |
1208 { | 1266 { |
1209 ngx_buf_t *b; | 1267 ngx_buf_t *b; |
1210 ngx_chain_t *cl; | 1268 ngx_chain_t *cl, *tl, **ll; |
1211 ngx_http_request_body_t *rb; | 1269 ngx_http_request_body_t *rb; |
1212 | 1270 |
1213 rb = r->request_body; | 1271 rb = r->request_body; |
1214 | 1272 |
1215 #if (NGX_DEBUG) | 1273 ll = &rb->bufs; |
1274 | |
1275 for (cl = rb->bufs; cl; cl = cl->next) { | |
1216 | 1276 |
1217 #if 0 | 1277 #if 0 |
1218 for (cl = rb->bufs; cl; cl = cl->next) { | |
1219 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, | 1278 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, |
1220 "http body old buf t:%d f:%d %p, pos %p, size: %z " | 1279 "http body old buf t:%d f:%d %p, pos %p, size: %z " |
1221 "file: %O, size: %O", | 1280 "file: %O, size: %O", |
1222 cl->buf->temporary, cl->buf->in_file, | 1281 cl->buf->temporary, cl->buf->in_file, |
1223 cl->buf->start, cl->buf->pos, | 1282 cl->buf->start, cl->buf->pos, |
1224 cl->buf->last - cl->buf->pos, | 1283 cl->buf->last - cl->buf->pos, |
1225 cl->buf->file_pos, | 1284 cl->buf->file_pos, |
1226 cl->buf->file_last - cl->buf->file_pos); | 1285 cl->buf->file_last - cl->buf->file_pos); |
1227 } | |
1228 #endif | 1286 #endif |
1229 | 1287 |
1288 ll = &cl->next; | |
1289 } | |
1290 | |
1230 for (cl = in; cl; cl = cl->next) { | 1291 for (cl = in; cl; cl = cl->next) { |
1292 | |
1231 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, | 1293 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0, |
1232 "http body new buf t:%d f:%d %p, pos %p, size: %z " | 1294 "http body new buf t:%d f:%d %p, pos %p, size: %z " |
1233 "file: %O, size: %O", | 1295 "file: %O, size: %O", |
1234 cl->buf->temporary, cl->buf->in_file, | 1296 cl->buf->temporary, cl->buf->in_file, |
1235 cl->buf->start, cl->buf->pos, | 1297 cl->buf->start, cl->buf->pos, |
1236 cl->buf->last - cl->buf->pos, | 1298 cl->buf->last - cl->buf->pos, |
1237 cl->buf->file_pos, | 1299 cl->buf->file_pos, |
1238 cl->buf->file_last - cl->buf->file_pos); | 1300 cl->buf->file_last - cl->buf->file_pos); |
1239 } | 1301 |
1240 | 1302 if (cl->buf->last_buf) { |
1241 #endif | 1303 |
1242 | 1304 if (rb->last_saved) { |
1243 /* TODO: coalesce neighbouring buffers */ | 1305 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, |
1244 | 1306 "duplicate last buf in save filter"); |
1245 if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) { | 1307 *ll = NULL; |
1246 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1308 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1247 } | 1309 } |
1310 | |
1311 rb->last_saved = 1; | |
1312 } | |
1313 | |
1314 tl = ngx_alloc_chain_link(r->pool); | |
1315 if (tl == NULL) { | |
1316 *ll = NULL; | |
1317 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1318 } | |
1319 | |
1320 tl->buf = cl->buf; | |
1321 *ll = tl; | |
1322 ll = &tl->next; | |
1323 } | |
1324 | |
1325 *ll = NULL; | |
1248 | 1326 |
1249 if (r->request_body_no_buffering) { | 1327 if (r->request_body_no_buffering) { |
1250 return NGX_OK; | 1328 return NGX_OK; |
1251 } | 1329 } |
1252 | 1330 |
1259 } | 1337 } |
1260 | 1338 |
1261 return NGX_OK; | 1339 return NGX_OK; |
1262 } | 1340 } |
1263 | 1341 |
1264 /* rb->rest == 0 */ | 1342 if (!rb->last_saved) { |
1343 return NGX_OK; | |
1344 } | |
1265 | 1345 |
1266 if (rb->temp_file || r->request_body_in_file_only) { | 1346 if (rb->temp_file || r->request_body_in_file_only) { |
1347 | |
1348 if (rb->bufs && rb->bufs->buf->in_file) { | |
1349 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
1350 "body already in file"); | |
1351 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
1352 } | |
1267 | 1353 |
1268 if (ngx_http_write_request_body(r) != NGX_OK) { | 1354 if (ngx_http_write_request_body(r) != NGX_OK) { |
1269 return NGX_HTTP_INTERNAL_SERVER_ERROR; | 1355 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1270 } | 1356 } |
1271 | 1357 |