Klaus Demo nginx / 2743bb6
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
8 changed file(s) with 353 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
291291 offsetof(ngx_http_proxy_loc_conf_t, upstream.buffering),
292292 NULL },
293293
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
294301 { ngx_string("proxy_ignore_client_abort"),
295302 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
296303 ngx_conf_set_flag_slot,
875882
876883 u->accel = 1;
877884
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
878894 rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
879895
880896 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
13921408 "http proxy header:%N\"%*s\"",
13931409 (size_t) (b->last - b->pos), b->pos);
13941410
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) {
13961416
13971417 body = u->request_bufs;
13981418 u->request_bufs = cl;
25812601 conf->upstream.store_access = NGX_CONF_UNSET_UINT;
25822602 conf->upstream.next_upstream_tries = NGX_CONF_UNSET_UINT;
25832603 conf->upstream.buffering = NGX_CONF_UNSET;
2604 conf->upstream.request_buffering = NGX_CONF_UNSET;
25842605 conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
25852606 conf->upstream.force_ranges = NGX_CONF_UNSET;
25862607
26892710
26902711 ngx_conf_merge_value(conf->upstream.buffering,
26912712 prev->upstream.buffering, 1);
2713
2714 ngx_conf_merge_value(conf->upstream.request_buffering,
2715 prev->upstream.request_buffering, 1);
26922716
26932717 ngx_conf_merge_value(conf->upstream.ignore_client_abort,
26942718 prev->upstream.ignore_client_abort, 0);
137137
138138 ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
139139 ngx_http_client_body_handler_pt post_handler);
140 ngx_int_t ngx_http_read_unbuffered_request_body(ngx_http_request_t *r);
140141
141142 ngx_int_t ngx_http_send_header(ngx_http_request_t *r);
142143 ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r,
25242524 return;
25252525 }
25262526
2527 if (r->reading_body) {
2528 r->keepalive = 0;
2529 r->lingering_close = 1;
2530 }
2531
25272532 if (!ngx_terminate
25282533 && !ngx_exiting
25292534 && r->keepalive
472472 unsigned request_body_in_clean_file:1;
473473 unsigned request_body_file_group_access:1;
474474 unsigned request_body_file_log_level:3;
475 unsigned request_body_no_buffering:1;
475476
476477 unsigned subrequest_in_memory:1;
477478 unsigned waited:1;
508509 unsigned keepalive:1;
509510 unsigned lingering_close:1;
510511 unsigned discard_body:1;
512 unsigned reading_body:1;
511513 unsigned internal:1;
512514 unsigned error_page:1;
513515 unsigned filter_finalize:1;
4141
4242 #if (NGX_HTTP_SPDY)
4343 if (r->spdy_stream && r == r->main) {
44 r->request_body_no_buffering = 0;
4445 rc = ngx_http_spdy_read_request_body(r, post_handler);
4546 goto done;
4647 }
4748 #endif
4849
4950 if (r != r->main || r->request_body || r->discard_body) {
51 r->request_body_no_buffering = 0;
5052 post_handler(r);
5153 return NGX_OK;
5254 }
5456 if (ngx_http_test_expect(r) != NGX_OK) {
5557 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
5658 goto done;
59 }
60
61 if (r->request_body_no_buffering) {
62 r->request_body_in_file_only = 0;
5763 }
5864
5965 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
7884 r->request_body = rb;
7985
8086 if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
87 r->request_body_no_buffering = 0;
8188 post_handler(r);
8289 return NGX_OK;
8390 }
170177 }
171178 }
172179
180 r->request_body_no_buffering = 0;
181
173182 post_handler(r);
174183
175184 return NGX_OK;
213222
214223 done:
215224
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
216240 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
217241 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;
218262 }
219263
220264 return rc;
263307 for ( ;; ) {
264308 if (rb->buf->last == rb->buf->end) {
265309
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) {
266384 /* pass buffer to request body filter chain */
267385
268386 out.buf = rb->buf;
273391 if (rc != NGX_OK) {
274392 return rc;
275393 }
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) {
298397 break;
299398 }
300399
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 {
315417 /* pass buffer to request body filter chain */
316418
317419 out.buf = rb->buf;
324426 }
325427 }
326428
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) {
344429 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
345430 ngx_add_timer(c->read, clcf->client_body_timeout);
346431
386471 }
387472 }
388473
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 }
392478
393479 return NGX_OK;
394480 }
10841170 }
10851171
10861172 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)
10881175 {
10891176 if (ngx_http_write_request_body(r) != NGX_OK) {
10901177 return NGX_HTTP_INTERNAL_SERVER_ERROR;
3535 static ngx_int_t ngx_http_upstream_reinit(ngx_http_request_t *r,
3636 ngx_http_upstream_t *u);
3737 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);
3941 static void ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
4042 ngx_http_upstream_t *u);
43 static void ngx_http_upstream_read_request_handler(ngx_http_request_t *r);
4144 static void ngx_http_upstream_process_header(ngx_http_request_t *r,
4245 ngx_http_upstream_t *u);
4346 static ngx_int_t ngx_http_upstream_test_next(ngx_http_request_t *r,
567570 u->output.pool = r->pool;
568571 u->output.bufs.num = 1;
569572 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 }
572578
573579 u->writer.pool = r->pool;
574580
14311437
14321438 #endif
14331439
1434 ngx_http_upstream_send_request(r, u);
1440 ngx_http_upstream_send_request(r, u, 1);
14351441 }
14361442
14371443
15351541
15361542 c = r->connection;
15371543
1538 ngx_http_upstream_send_request(r, u);
1544 ngx_http_upstream_send_request(r, u, 1);
15391545
15401546 ngx_http_run_posted_requests(c);
15411547 return;
17231729
17241730
17251731 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)
17271734 {
17281735 ngx_int_t rc;
17291736 ngx_connection_t *c;
17401747
17411748 c->log->action = "sending request to upstream";
17421749
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);
17461751
17471752 if (rc == NGX_ERROR) {
17481753 ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR);
17491754 return;
17501755 }
17511756
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;
17541760 }
17551761
17561762 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 }
17581769
17591770 if (ngx_handle_write_event(c->write, u->conf->send_lowat) != NGX_OK) {
17601771 ngx_http_upstream_finalize_request(r, u,
17661777 }
17671778
17681779 /* rc == NGX_OK */
1780
1781 if (c->write->timer_set) {
1782 ngx_del_timer(c->write);
1783 }
17691784
17701785 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
17711786 if (ngx_tcp_push(c->fd) == NGX_ERROR) {
17961811 }
17971812
17981813
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
17991931 static void
18001932 ngx_http_upstream_send_request_handler(ngx_http_request_t *r,
18011933 ngx_http_upstream_t *u)
18291961 return;
18301962 }
18311963
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);
18331987 }
18341988
18351989
36253779 "upstream timed out");
36263780 }
36273781
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 {
36293785 status = 0;
36303786
36313787 /* TODO: inform balancer instead */
36733829
36743830 if (u->peer.tries == 0
36753831 || !(u->conf->next_upstream & ft_type)
3832 || (u->request_sent && r->request_body_no_buffering)
36763833 || (timeout && ngx_current_msec - u->peer.start_time >= timeout))
36773834 {
36783835 #if (NGX_HTTP_CACHE)
159159 ngx_uint_t store_access;
160160 ngx_uint_t next_upstream_tries;
161161 ngx_flag_t buffering;
162 ngx_flag_t request_buffering;
162163 ngx_flag_t pass_request_headers;
163164 ngx_flag_t pass_request_body;
164165
10801080 v->no_cacheable = 0;
10811081 v->not_found = 0;
10821082
1083 } else if (r->reading_body) {
1084 v->not_found = 1;
1085 v->no_cacheable = 1;
1086
10831087 } else if (r->headers_in.content_length_n >= 0) {
10841088 p = ngx_pnalloc(r->pool, NGX_OFF_T_LEN);
10851089 if (p == NULL) {