comparison src/http/ngx_http_request_body.c @ 6050:a08fad30aeac

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.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 23 Mar 2015 21:09:19 +0300
parents 42d9beeb22db
children 231a5bbd9e9c
comparison
equal deleted inserted replaced
6049:42d9beeb22db 6050:a08fad30aeac
40 40
41 r->main->count++; 41 r->main->count++;
42 42
43 #if (NGX_HTTP_SPDY) 43 #if (NGX_HTTP_SPDY)
44 if (r->spdy_stream && r == r->main) { 44 if (r->spdy_stream && r == r->main) {
45 r->request_body_no_buffering = 0;
45 rc = ngx_http_spdy_read_request_body(r, post_handler); 46 rc = ngx_http_spdy_read_request_body(r, post_handler);
46 goto done; 47 goto done;
47 } 48 }
48 #endif 49 #endif
49 50
50 if (r != r->main || r->request_body || r->discard_body) { 51 if (r != r->main || r->request_body || r->discard_body) {
52 r->request_body_no_buffering = 0;
51 post_handler(r); 53 post_handler(r);
52 return NGX_OK; 54 return NGX_OK;
53 } 55 }
54 56
55 if (ngx_http_test_expect(r) != NGX_OK) { 57 if (ngx_http_test_expect(r) != NGX_OK) {
56 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; 58 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
57 goto done; 59 goto done;
60 }
61
62 if (r->request_body_no_buffering) {
63 r->request_body_in_file_only = 0;
58 } 64 }
59 65
60 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)); 66 rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
61 if (rb == NULL) { 67 if (rb == NULL) {
62 rc = NGX_HTTP_INTERNAL_SERVER_ERROR; 68 rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
77 rb->post_handler = post_handler; 83 rb->post_handler = post_handler;
78 84
79 r->request_body = rb; 85 r->request_body = rb;
80 86
81 if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) { 87 if (r->headers_in.content_length_n < 0 && !r->headers_in.chunked) {
88 r->request_body_no_buffering = 0;
82 post_handler(r); 89 post_handler(r);
83 return NGX_OK; 90 return NGX_OK;
84 } 91 }
85 92
86 preread = r->header_in->last - r->header_in->pos; 93 preread = r->header_in->last - r->header_in->pos;
169 } else { 176 } else {
170 rb->bufs = NULL; 177 rb->bufs = NULL;
171 } 178 }
172 } 179 }
173 180
181 r->request_body_no_buffering = 0;
182
174 post_handler(r); 183 post_handler(r);
175 184
176 return NGX_OK; 185 return NGX_OK;
177 } 186 }
178 187
212 221
213 rc = ngx_http_do_read_client_request_body(r); 222 rc = ngx_http_do_read_client_request_body(r);
214 223
215 done: 224 done:
216 225
226 if (r->request_body_no_buffering
227 && (rc == NGX_OK || rc == NGX_AGAIN))
228 {
229 if (rc == NGX_OK) {
230 r->request_body_no_buffering = 0;
231
232 } else {
233 /* rc == NGX_AGAIN */
234 r->reading_body = 1;
235 }
236
237 r->read_event_handler = ngx_http_block_reading;
238 post_handler(r);
239 }
240
217 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { 241 if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
218 r->main->count--; 242 r->main->count--;
243 }
244
245 return rc;
246 }
247
248
249 ngx_int_t
250 ngx_http_read_unbuffered_request_body(ngx_http_request_t *r)
251 {
252 ngx_int_t rc;
253
254 if (r->connection->read->timedout) {
255 r->connection->timedout = 1;
256 return NGX_HTTP_REQUEST_TIME_OUT;
257 }
258
259 rc = ngx_http_do_read_client_request_body(r);
260
261 if (rc == NGX_OK) {
262 r->reading_body = 0;
219 } 263 }
220 264
221 return rc; 265 return rc;
222 } 266 }
223 267
262 306
263 for ( ;; ) { 307 for ( ;; ) {
264 for ( ;; ) { 308 for ( ;; ) {
265 if (rb->buf->last == rb->buf->end) { 309 if (rb->buf->last == rb->buf->end) {
266 310
311 if (rb->buf->pos != rb->buf->last) {
312
313 /* pass buffer to request body filter chain */
314
315 out.buf = rb->buf;
316 out.next = NULL;
317
318 rc = ngx_http_request_body_filter(r, &out);
319
320 if (rc != NGX_OK) {
321 return rc;
322 }
323
324 } else {
325
326 /* update chains */
327
328 rc = ngx_http_request_body_filter(r, NULL);
329
330 if (rc != NGX_OK) {
331 return rc;
332 }
333 }
334
335 if (rb->busy != NULL) {
336 if (r->request_body_no_buffering) {
337 if (c->read->timer_set) {
338 ngx_del_timer(c->read);
339 }
340
341 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
342 return NGX_HTTP_INTERNAL_SERVER_ERROR;
343 }
344
345 return NGX_AGAIN;
346 }
347
348 return NGX_HTTP_INTERNAL_SERVER_ERROR;
349 }
350
351 rb->buf->pos = rb->buf->start;
352 rb->buf->last = rb->buf->start;
353 }
354
355 size = rb->buf->end - rb->buf->last;
356 rest = rb->rest - (rb->buf->last - rb->buf->pos);
357
358 if ((off_t) size > rest) {
359 size = (size_t) rest;
360 }
361
362 n = c->recv(c, rb->buf->last, size);
363
364 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
365 "http client request body recv %z", n);
366
367 if (n == NGX_AGAIN) {
368 break;
369 }
370
371 if (n == 0) {
372 ngx_log_error(NGX_LOG_INFO, c->log, 0,
373 "client prematurely closed connection");
374 }
375
376 if (n == 0 || n == NGX_ERROR) {
377 c->error = 1;
378 return NGX_HTTP_BAD_REQUEST;
379 }
380
381 rb->buf->last += n;
382 r->request_length += n;
383
384 if (n == rest) {
267 /* pass buffer to request body filter chain */ 385 /* pass buffer to request body filter chain */
268 386
269 out.buf = rb->buf; 387 out.buf = rb->buf;
270 out.next = NULL; 388 out.next = NULL;
271 389
272 rc = ngx_http_request_body_filter(r, &out); 390 rc = ngx_http_request_body_filter(r, &out);
273 391
274 if (rc != NGX_OK) { 392 if (rc != NGX_OK) {
275 return rc; 393 return rc;
276 } 394 }
277 395 }
278 if (rb->busy != NULL) { 396
279 return NGX_HTTP_INTERNAL_SERVER_ERROR; 397 if (rb->rest == 0) {
280 }
281
282 rb->buf->pos = rb->buf->start;
283 rb->buf->last = rb->buf->start;
284 }
285
286 size = rb->buf->end - rb->buf->last;
287 rest = rb->rest - (rb->buf->last - rb->buf->pos);
288
289 if ((off_t) size > rest) {
290 size = (size_t) rest;
291 }
292
293 n = c->recv(c, rb->buf->last, size);
294
295 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
296 "http client request body recv %z", n);
297
298 if (n == NGX_AGAIN) {
299 break; 398 break;
300 } 399 }
301 400
302 if (n == 0) { 401 if (rb->buf->last < rb->buf->end) {
303 ngx_log_error(NGX_LOG_INFO, c->log, 0, 402 break;
304 "client prematurely closed connection"); 403 }
305 } 404 }
306 405
307 if (n == 0 || n == NGX_ERROR) { 406 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
308 c->error = 1; 407 "http client request body rest %O", rb->rest);
309 return NGX_HTTP_BAD_REQUEST; 408
310 } 409 if (rb->rest == 0) {
311 410 break;
312 rb->buf->last += n; 411 }
313 r->request_length += n; 412
314 413 if (!c->read->ready) {
315 if (n == rest) { 414
415 if (r->request_body_no_buffering
416 && rb->buf->pos != rb->buf->last)
417 {
316 /* pass buffer to request body filter chain */ 418 /* pass buffer to request body filter chain */
317 419
318 out.buf = rb->buf; 420 out.buf = rb->buf;
319 out.next = NULL; 421 out.next = NULL;
320 422
323 if (rc != NGX_OK) { 425 if (rc != NGX_OK) {
324 return rc; 426 return rc;
325 } 427 }
326 } 428 }
327 429
328 if (rb->rest == 0) {
329 break;
330 }
331
332 if (rb->buf->last < rb->buf->end) {
333 break;
334 }
335 }
336
337 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
338 "http client request body rest %O", rb->rest);
339
340 if (rb->rest == 0) {
341 break;
342 }
343
344 if (!c->read->ready) {
345 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 430 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
346 ngx_add_timer(c->read, clcf->client_body_timeout); 431 ngx_add_timer(c->read, clcf->client_body_timeout);
347 432
348 if (ngx_handle_read_event(c->read, 0) != NGX_OK) { 433 if (ngx_handle_read_event(c->read, 0) != NGX_OK) {
349 return NGX_HTTP_INTERNAL_SERVER_ERROR; 434 return NGX_HTTP_INTERNAL_SERVER_ERROR;
385 } else { 470 } else {
386 rb->bufs = NULL; 471 rb->bufs = NULL;
387 } 472 }
388 } 473 }
389 474
390 r->read_event_handler = ngx_http_block_reading; 475 if (!r->request_body_no_buffering) {
391 476 r->read_event_handler = ngx_http_block_reading;
392 rb->post_handler(r); 477 rb->post_handler(r);
478 }
393 479
394 return NGX_OK; 480 return NGX_OK;
395 } 481 }
396 482
397 483
1083 if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) { 1169 if (ngx_chain_add_copy(r->pool, &rb->bufs, in) != NGX_OK) {
1084 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1170 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1085 } 1171 }
1086 1172
1087 if (rb->rest > 0 1173 if (rb->rest > 0
1088 && rb->buf && rb->buf->last == rb->buf->end) 1174 && rb->buf && rb->buf->last == rb->buf->end
1175 && !r->request_body_no_buffering)
1089 { 1176 {
1090 if (ngx_http_write_request_body(r) != NGX_OK) { 1177 if (ngx_http_write_request_body(r) != NGX_OK) {
1091 return NGX_HTTP_INTERNAL_SERVER_ERROR; 1178 return NGX_HTTP_INTERNAL_SERVER_ERROR;
1092 } 1179 }
1093 } 1180 }