Request body: unbuffered reading.
The r->request_body_no_buffering flag was introduced. It instructs
client request body reading code to avoid reading the whole body, and
to call post_handler early instead. The caller should use the
ngx_http_read_unbuffered_request_body() function to read remaining
parts of the body.
Upstream module is now able to use this mode, if configured with
the proxy_request_buffering directive.
Maxim Dounin
7 years ago
291 | 291 | offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering), |
292 | 292 | NULL }, |
293 | 293 | |
294 | { ngx_string("proxy_request_buffering"), | |
295 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
296 | ngx_conf_set_flag_slot, | |
297 | NGX_HTTP_LOC_CONF_OFFSET, | |
298 | offsetof(ngx_http_proxy_loc_conf_t, upstream.request_buffering), | |
299 | NULL }, | |
300 | ||
294 | 301 | { ngx_string("proxy_ignore_client_abort"), |
295 | 302 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, |
296 | 303 | ngx_conf_set_flag_slot, |
875 | 882 | |
876 | 883 | u->accel = 1; |
877 | 884 | |
885 | if (!plcf->upstream.request_buffering | |
886 | && plcf->body_values == NULL && plcf->upstream.pass_request_body | |
887 | && !r->headers_in.chunked) | |
888 | { | |
889 | /* TODO: support chunked when using HTTP/1.1 */ | |
890 | ||
891 | r->request_body_no_buffering = 1; | |
892 | } | |
893 | ||
878 | 894 | rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init); |
879 | 895 | |
880 | 896 | if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { |
1392 | 1408 | "http proxy header:%N\"%*s\"", |
1393 | 1409 | (size_t) (b->last - b->pos), b->pos); |
1394 | 1410 | |
1395 | if (plcf->body_values == NULL && plcf->upstream.pass_request_body) { | |
1411 | if (r->request_body_no_buffering) { | |
1412 | ||
1413 | u->request_bufs = cl; | |
1414 | ||
1415 | } else if (plcf->body_values == NULL && plcf->upstream.pass_request_body) { | |
1396 | 1416 | |
1397 | 1417 | body = u->request_bufs; |
1398 | 1418 | u->request_bufs = cl; |
2581 | 2601 | conf->upstream.store_access = NGX_CONF_UNSET_UINT; |
2582 | 2602 | conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT; |
2583 | 2603 | conf->upstream.buffering = NGX_CONF_UNSET; |
2604 | conf->upstream.request_buffering = NGX_CONF_UNSET; | |
2584 | 2605 | conf->upstream.ignore_client_abort = NGX_CONF_UNSET; |
2585 | 2606 | conf->upstream.force_ranges = NGX_CONF_UNSET; |
2586 | 2607 | |
2689 | 2710 | |
2690 | 2711 | ngx_conf_merge_value(conf->upstream.buffering, |
2691 | 2712 | prev->upstream.buffering, 1); |
2713 | ||
2714 | ngx_conf_merge_value(conf->upstream.request_buffering, | |
2715 | prev->upstream.request_buffering, 1); | |
2692 | 2716 | |
2693 | 2717 | ngx_conf_merge_value(conf->upstream.ignore_client_abort, |
2694 | 2718 | prev->upstream.ignore_client_abort, 0); |
137 | 137 | |
138 | 138 | ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, |
139 | 139 | ngx_http_client_body_handler_pt post_handler); |
140 | ngx_int_t ngx_http_read_unbuffered_request_body(ngx_http_request_t *r); | |
140 | 141 | |
141 | 142 | ngx_int_t ngx_http_send_header(ngx_http_request_t *r); |
142 | 143 | ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r, |
2524 | 2524 | return; |
2525 | 2525 | } |
2526 | 2526 | |
2527 | if (r->reading_body) { | |
2528 | r->keepalive = 0; | |
2529 | r->lingering_close = 1; | |
2530 | } | |
2531 | ||
2527 | 2532 | if (!ngx_terminate |
2528 | 2533 | && !ngx_exiting |
2529 | 2534 | && r->keepalive |
472 | 472 | unsigned request_body_in_clean_file:1; |
473 | 473 | unsigned request_body_file_group_access:1; |
474 | 474 | unsigned request_body_file_log_level:3; |
475 | unsigned request_body_no_buffering:1; | |
475 | 476 | |
476 | 477 | unsigned subrequest_in_memory:1; |
477 | 478 | unsigned waited:1; |
508 | 509 | unsigned keepalive:1; |
509 | 510 | unsigned lingering_close:1; |
510 | 511 | unsigned discard_body:1; |
512 | unsigned reading_body:1; | |
511 | 513 | unsigned internal:1; |
512 | 514 | unsigned error_page:1; |
513 | 515 | unsigned filter_finalize:1; |
41 | 41 | |
42 | 42 | #if (NGX_HTTP_SPDY) |
43 | 43 | if (r->spdy_stream && r == r->main) { |
44 | r->request_body_no_buffering = 0; | |
44 | 45 | rc = ngx_http_spdy_read_request_body(r, post_handler); |
45 | 46 | goto done; |
46 | 47 | } |
47 | 48 | #endif |
48 | 49 | |
49 | 50 | if (r != r->main || r->request_body || r->discard_body) { |
51 | r->request_body_no_buffering = 0; | |
50 | 52 | post_handler(r); |
51 | 53 | return NGX_OK; |
52 | 54 | } |
54 | 56 | if (ngx_http_test_expect(r) != NGX_OK) { |
55 | 57 | rc = NGX_HTTP_INTERNAL_SERVER_ERROR; |
56 | 58 | goto done; |
59 | } | |
60 | ||
61 | if (r->request_body_no_buffering) { | |
62 | r->request_body_in_file_only = 0; | |
57 | 63 | } |
58 | 64 | |
59 | 65 | rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); |
78 | 84 | r->request_body = rb; |
79 | 85 | |
80 | 86 | if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) { |
87 | r->request_body_no_buffering = 0; | |
81 | 88 | post_handler(r); |
82 | 89 | return NGX_OK; |
83 | 90 | } |
170 | 177 | } |
171 | 178 | } |
172 | 179 | |
180 | r->request_body_no_buffering = 0; | |
181 | ||
173 | 182 | post_handler(r); |
174 | 183 | |
175 | 184 | return NGX_OK; |
213 | 222 | |
214 | 223 | done: |
215 | 224 | |
225 | if (r->request_body_no_buffering | |
226 | && (rc == NGX_OK || rc == NGX_AGAIN)) | |
227 | { | |
228 | if (rc == NGX_OK) { | |
229 | r->request_body_no_buffering = 0; | |
230 | ||
231 | } else { | |
232 | /* rc == NGX_AGAIN */ | |
233 | r->reading_body = 1; | |
234 | } | |
235 | ||
236 | r->read_event_handler = ngx_http_block_reading; | |
237 | post_handler(r); | |
238 | } | |
239 | ||
216 | 240 | if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { |
217 | 241 | r->main->count--; |
242 | } | |
243 | ||
244 | return rc; | |
245 | } | |
246 | ||
247 | ||
248 | ngx_int_t | |
249 | ngx_http_read_unbuffered_request_body(ngx_http_request_t *r) | |
250 | { | |
251 | ngx_int_t rc; | |
252 | ||
253 | if (r->connection->read->timedout) { | |
254 | r->connection->timedout = 1; | |
255 | return NGX_HTTP_REQUEST_TIME_OUT; | |
256 | } | |
257 | ||
258 | rc = ngx_http_do_read_client_request_body(r); | |
259 | ||
260 | if (rc == NGX_OK) { | |
261 | r->reading_body = 0; | |
218 | 262 | } |
219 | 263 | |
220 | 264 | return rc; |
263 | 307 | for ( ;; ) { |
264 | 308 | if (rb->buf->last == rb->buf->end) { |
265 | 309 | |
310 | if (rb->buf->pos != rb->buf->last) { | |
311 | ||
312 | /* pass buffer to request body filter chain */ | |
313 | ||
314 | out.buf = rb->buf; | |
315 | out.next = NULL; | |
316 | ||
317 | rc = ngx_http_request_body_filter(r, &out); | |
318 | ||
319 | if (rc != NGX_OK) { | |
320 | return rc; | |
321 | } | |
322 | ||
323 | } else { | |
324 | ||
325 | /* update chains */ | |
326 | ||
327 | rc = ngx_http_request_body_filter(r, NULL); | |
328 | ||
329 | if (rc != NGX_OK) { | |
330 | return rc; | |
331 | } | |
332 | } | |
333 | ||
334 | if (rb->busy != NULL) { | |
335 | if (r->request_body_no_buffering) { | |
336 | if (c->read->timer_set) { | |
337 | ngx_del_timer(c->read); | |
338 | } | |
339 | ||
340 | if (ngx_handle_read_event(c->read, 0) != NGX_OK) { | |
341 | return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
342 | } | |
343 | ||
344 | return NGX_AGAIN; | |
345 | } | |
346 | ||
347 | return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
348 | } | |
349 | ||
350 | rb->buf->pos = rb->buf->start; | |
351 | rb->buf->last = rb->buf->start; | |
352 | } | |
353 | ||
354 | size = rb->buf->end - rb->buf->last; | |
355 | rest = rb->rest - (rb->buf->last - rb->buf->pos); | |
356 | ||
357 | if ((off_t) size > rest) { | |
358 | size = (size_t) rest; | |
359 | } | |
360 | ||
361 | n = c->recv(c, rb->buf->last, size); | |
362 | ||
363 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
364 | "http client request body recv %z", n); | |
365 | ||
366 | if (n == NGX_AGAIN) { | |
367 | break; | |
368 | } | |
369 | ||
370 | if (n == 0) { | |
371 | ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
372 | "client prematurely closed connection"); | |
373 | } | |
374 | ||
375 | if (n == 0 || n == NGX_ERROR) { | |
376 | c->error = 1; | |
377 | return NGX_HTTP_BAD_REQUEST; | |
378 | } | |
379 | ||
380 | rb->buf->last += n; | |
381 | r->request_length += n; | |
382 | ||
383 | if (n == rest) { | |
266 | 384 | /* pass buffer to request body filter chain */ |
267 | 385 | |
268 | 386 | out.buf = rb->buf; |
273 | 391 | if (rc != NGX_OK) { |
274 | 392 | return rc; |
275 | 393 | } |
276 | ||
277 | if (rb->busy != NULL) { | |
278 | return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
279 | } | |
280 | ||
281 | rb->buf->pos = rb->buf->start; | |
282 | rb->buf->last = rb->buf->start; | |
283 | } | |
284 | ||
285 | size = rb->buf->end - rb->buf->last; | |
286 | rest = rb->rest - (rb->buf->last - rb->buf->pos); | |
287 | ||
288 | if ((off_t) size > rest) { | |
289 | size = (size_t) rest; | |
290 | } | |
291 | ||
292 | n = c->recv(c, rb->buf->last, size); | |
293 | ||
294 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
295 | "http client request body recv %z", n); | |
296 | ||
297 | if (n == NGX_AGAIN) { | |
394 | } | |
395 | ||
396 | if (rb->rest == 0) { | |
298 | 397 | break; |
299 | 398 | } |
300 | 399 | |
301 | if (n == 0) { | |
302 | ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
303 | "client prematurely closed connection"); | |
304 | } | |
305 | ||
306 | if (n == 0 || n == NGX_ERROR) { | |
307 | c->error = 1; | |
308 | return NGX_HTTP_BAD_REQUEST; | |
309 | } | |
310 | ||
311 | rb->buf->last += n; | |
312 | r->request_length += n; | |
313 | ||
314 | if (n == rest) { | |
400 | if (rb->buf->last < rb->buf->end) { | |
401 | break; | |
402 | } | |
403 | } | |
404 | ||
405 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
406 | "http client request body rest %O", rb->rest); | |
407 | ||
408 | if (rb->rest == 0) { | |
409 | break; | |
410 | } | |
411 | ||
412 | if (!c->read->ready) { | |
413 | ||
414 | if (r->request_body_no_buffering | |
415 | && rb->buf->pos != rb->buf->last) | |
416 | { | |
315 | 417 | /* pass buffer to request body filter chain */ |
316 | 418 | |
317 | 419 | out.buf = rb->buf; |
324 | 426 | } |
325 | 427 | } |
326 | 428 | |
327 | if (rb->rest == 0) { | |
328 | break; | |
329 | } | |
330 | ||
331 | if (rb->buf->last < rb->buf->end) { | |
332 | break; | |
333 | } | |
334 | } | |
335 | ||
336 | ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
337 | "http client request body rest %O", rb->rest); | |
338 | ||
339 | if (rb->rest == 0) { | |
340 | break; | |
341 | } | |
342 | ||
343 | if (!c->read->ready) { | |
344 | 429 | clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); |
345 | 430 | ngx_add_timer(c->read, clcf->client_body_timeout); |
346 | 431 | |
386 | 471 | } |
387 | 472 | } |
388 | 473 | |
389 | r->read_event_handler = ngx_http_block_reading; | |
390 | ||
391 | rb->post_handler(r); | |
474 | if (!r->request_body_no_buffering) { | |
475 | r->read_event_handler = ngx_http_block_reading; | |
476 | rb->post_handler(r); | |
477 | } | |
392 | 478 | |
393 | 479 | return NGX_OK; |
394 | 480 | } |
1084 | 1170 | } |
1085 | 1171 | |
1086 | 1172 | if (rb->rest > 0 |
1087 | && rb->buf && rb->buf->last == rb->buf->end) | |
1173 | && rb->buf && rb->buf->last == rb->buf->end | |
1174 | && !r->request_body_no_buffering) | |
1088 | 1175 | { |
1089 | 1176 | if (ngx_http_write_request_body(r) != NGX_OK) { |
1090 | 1177 | return NGX_HTTP_INTERNAL_SERVER_ERROR; |
35 | 35 | static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r, |
36 | 36 | ngx_http_upstream_t *u); |
37 | 37 | static void ngx_http_upstream_send_request(ngx_http_request_t *r, |
38 | ngx_http_upstream_t *u); | |
38 | ngx_http_upstream_t *u, ngx_uint_t do_write); | |
39 | static ngx_int_t ngx_http_upstream_send_request_body(ngx_http_request_t *r, | |
40 | ngx_http_upstream_t *u, ngx_uint_t do_write); | |
39 | 41 | static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r, |
40 | 42 | ngx_http_upstream_t *u); |
43 | static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r); | |
41 | 44 | static void ngx_http_upstream_process_header(ngx_http_request_t *r, |
42 | 45 | ngx_http_upstream_t *u); |
43 | 46 | static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r, |
567 | 570 | u->output.pool = r->pool; |
568 | 571 | u->output.bufs.num = 1; |
569 | 572 | u->output.bufs.size = clcf->client_body_buffer_size; |
570 | u->output.output_filter = ngx_chain_writer; | |
571 | u->output.filter_ctx = &u->writer; | |
573 | ||
574 | if (u->output.output_filter == NULL) { | |
575 | u->output.output_filter = ngx_chain_writer; | |
576 | u->output.filter_ctx = &u->writer; | |
577 | } | |
572 | 578 | |
573 | 579 | u->writer.pool = r->pool; |
574 | 580 | |
1431 | 1437 | |
1432 | 1438 | #endif |
1433 | 1439 | |
1434 | ngx_http_upstream_send_request(r, u); | |
1440 | ngx_http_upstream_send_request(r, u, 1); | |
1435 | 1441 | } |
1436 | 1442 | |
1437 | 1443 | |
1535 | 1541 | |
1536 | 1542 | c = r->connection; |
1537 | 1543 | |
1538 | ngx_http_upstream_send_request(r, u); | |
1544 | ngx_http_upstream_send_request(r, u, 1); | |
1539 | 1545 | |
1540 | 1546 | ngx_http_run_posted_requests(c); |
1541 | 1547 | return; |
1723 | 1729 | |
1724 | 1730 | |
1725 | 1731 | static void |
1726 | ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u) | |
1732 | ngx_http_upstream_send_request(ngx_http_request_t *r, ngx_http_upstream_t *u, | |
1733 | ngx_uint_t do_write) | |
1727 | 1734 | { |
1728 | 1735 | ngx_int_t rc; |
1729 | 1736 | ngx_connection_t *c; |
1740 | 1747 | |
1741 | 1748 | c->log->action = "sending request to upstream"; |
1742 | 1749 | |
1743 | rc = ngx_output_chain(&u->output, u->request_sent ? NULL : u->request_bufs); | |
1744 | ||
1745 | u->request_sent = 1; | |
1750 | rc = ngx_http_upstream_send_request_body(r, u, do_write); | |
1746 | 1751 | |
1747 | 1752 | if (rc == NGX_ERROR) { |
1748 | 1753 | ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); |
1749 | 1754 | return; |
1750 | 1755 | } |
1751 | 1756 | |
1752 | if (c->write->timer_set) { | |
1753 | ngx_del_timer(c->write); | |
1757 | if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
1758 | ngx_http_upstream_finalize_request(r, u, rc); | |
1759 | return; | |
1754 | 1760 | } |
1755 | 1761 | |
1756 | 1762 | if (rc == NGX_AGAIN) { |
1757 | ngx_add_timer(c->write, u->conf->send_timeout); | |
1763 | if (!c->write->ready) { | |
1764 | ngx_add_timer(c->write, u->conf->send_timeout); | |
1765 | ||
1766 | } else if (c->write->timer_set) { | |
1767 | ngx_del_timer(c->write); | |
1768 | } | |
1758 | 1769 | |
1759 | 1770 | if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) { |
1760 | 1771 | ngx_http_upstream_finalize_request(r, u, |
1766 | 1777 | } |
1767 | 1778 | |
1768 | 1779 | /* rc == NGX_OK */ |
1780 | ||
1781 | if (c->write->timer_set) { | |
1782 | ngx_del_timer(c->write); | |
1783 | } | |
1769 | 1784 | |
1770 | 1785 | if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) { |
1771 | 1786 | if (ngx_tcp_push(c->fd) == NGX_ERROR) { |
1796 | 1811 | } |
1797 | 1812 | |
1798 | 1813 | |
1814 | static ngx_int_t | |
1815 | ngx_http_upstream_send_request_body(ngx_http_request_t *r, | |
1816 | ngx_http_upstream_t *u, ngx_uint_t do_write) | |
1817 | { | |
1818 | int tcp_nodelay; | |
1819 | ngx_int_t rc; | |
1820 | ngx_chain_t *out, *cl, *ln; | |
1821 | ngx_connection_t *c; | |
1822 | ngx_http_core_loc_conf_t *clcf; | |
1823 | ||
1824 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1825 | "http upstream send request body"); | |
1826 | ||
1827 | if (!r->request_body_no_buffering) { | |
1828 | ||
1829 | /* buffered request body */ | |
1830 | ||
1831 | if (!u->request_sent) { | |
1832 | u->request_sent = 1; | |
1833 | out = u->request_bufs; | |
1834 | ||
1835 | } else { | |
1836 | out = NULL; | |
1837 | } | |
1838 | ||
1839 | return ngx_output_chain(&u->output, out); | |
1840 | } | |
1841 | ||
1842 | if (!u->request_sent) { | |
1843 | u->request_sent = 1; | |
1844 | out = u->request_bufs; | |
1845 | ||
1846 | if (r->request_body->bufs) { | |
1847 | for (cl = out; cl->next; cl = out->next) { /* void */ } | |
1848 | cl->next = r->request_body->bufs; | |
1849 | r->request_body->bufs = NULL; | |
1850 | } | |
1851 | ||
1852 | c = u->peer.connection; | |
1853 | clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
1854 | ||
1855 | if (clcf->tcp_nodelay && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET) { | |
1856 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay"); | |
1857 | ||
1858 | tcp_nodelay = 1; | |
1859 | ||
1860 | if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, | |
1861 | (const void *) &tcp_nodelay, sizeof(int)) == -1) | |
1862 | { | |
1863 | ngx_connection_error(c, ngx_socket_errno, | |
1864 | "setsockopt(TCP_NODELAY) failed"); | |
1865 | return NGX_ERROR; | |
1866 | } | |
1867 | ||
1868 | c->tcp_nodelay = NGX_TCP_NODELAY_SET; | |
1869 | } | |
1870 | ||
1871 | r->read_event_handler = ngx_http_upstream_read_request_handler; | |
1872 | ||
1873 | } else { | |
1874 | out = NULL; | |
1875 | } | |
1876 | ||
1877 | for ( ;; ) { | |
1878 | ||
1879 | if (do_write) { | |
1880 | rc = ngx_output_chain(&u->output, out); | |
1881 | ||
1882 | if (rc == NGX_ERROR) { | |
1883 | return NGX_ERROR; | |
1884 | } | |
1885 | ||
1886 | while (out) { | |
1887 | ln = out; | |
1888 | out = out->next; | |
1889 | ngx_free_chain(r->pool, ln); | |
1890 | } | |
1891 | ||
1892 | if (rc == NGX_OK && !r->reading_body) { | |
1893 | break; | |
1894 | } | |
1895 | } | |
1896 | ||
1897 | if (r->reading_body) { | |
1898 | /* read client request body */ | |
1899 | ||
1900 | rc = ngx_http_read_unbuffered_request_body(r); | |
1901 | ||
1902 | if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { | |
1903 | return rc; | |
1904 | } | |
1905 | ||
1906 | out = r->request_body->bufs; | |
1907 | r->request_body->bufs = NULL; | |
1908 | } | |
1909 | ||
1910 | /* stop if there is nothing to send */ | |
1911 | ||
1912 | if (out == NULL) { | |
1913 | rc = NGX_AGAIN; | |
1914 | break; | |
1915 | } | |
1916 | ||
1917 | do_write = 1; | |
1918 | } | |
1919 | ||
1920 | if (!r->reading_body) { | |
1921 | if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { | |
1922 | r->read_event_handler = | |
1923 | ngx_http_upstream_rd_check_broken_connection; | |
1924 | } | |
1925 | } | |
1926 | ||
1927 | return rc; | |
1928 | } | |
1929 | ||
1930 | ||
1799 | 1931 | static void |
1800 | 1932 | ngx_http_upstream_send_request_handler(ngx_http_request_t *r, |
1801 | 1933 | ngx_http_upstream_t *u) |
1829 | 1961 | return; |
1830 | 1962 | } |
1831 | 1963 | |
1832 | ngx_http_upstream_send_request(r, u); | |
1964 | ngx_http_upstream_send_request(r, u, 1); | |
1965 | } | |
1966 | ||
1967 | ||
1968 | static void | |
1969 | ngx_http_upstream_read_request_handler(ngx_http_request_t *r) | |
1970 | { | |
1971 | ngx_connection_t *c; | |
1972 | ngx_http_upstream_t *u; | |
1973 | ||
1974 | c = r->connection; | |
1975 | u = r->upstream; | |
1976 | ||
1977 | ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1978 | "http upstream read request handler"); | |
1979 | ||
1980 | if (c->read->timedout) { | |
1981 | c->timedout = 1; | |
1982 | ngx_http_upstream_finalize_request(r, u, NGX_HTTP_REQUEST_TIME_OUT); | |
1983 | return; | |
1984 | } | |
1985 | ||
1986 | ngx_http_upstream_send_request(r, u, 0); | |
1833 | 1987 | } |
1834 | 1988 | |
1835 | 1989 | |
3625 | 3779 | "upstream timed out"); |
3626 | 3780 | } |
3627 | 3781 | |
3628 | if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR) { | |
3782 | if (u->peer.cached && ft_type == NGX_HTTP_UPSTREAM_FT_ERROR | |
3783 | && (!u->request_sent || !r->request_body_no_buffering)) | |
3784 | { | |
3629 | 3785 | status = 0; |
3630 | 3786 | |
3631 | 3787 | /* TODO: inform balancer instead */ |
3673 | 3829 | |
3674 | 3830 | if (u->peer.tries == 0 |
3675 | 3831 | || !(u->conf->next_upstream & ft_type) |
3832 | || (u->request_sent && r->request_body_no_buffering) | |
3676 | 3833 | || (timeout && ngx_current_msec - u->peer.start_time >= timeout)) |
3677 | 3834 | { |
3678 | 3835 | #if (NGX_HTTP_CACHE) |
159 | 159 | ngx_uint_t store_access; |
160 | 160 | ngx_uint_t next_upstream_tries; |
161 | 161 | ngx_flag_t buffering; |
162 | ngx_flag_t request_buffering; | |
162 | 163 | ngx_flag_t pass_request_headers; |
163 | 164 | ngx_flag_t pass_request_body; |
164 | 165 |