comparison src/http/ngx_http_upstream.c @ 7220:20f139e9ffa8

Generic subrequests in memory. Previously, only the upstream response body could be accessed with the NGX_HTTP_SUBREQUEST_IN_MEMORY feature. Now any response body from a subrequest can be saved in a memory buffer. It is available as a single buffer in r->out and the buffer size is configured by the subrequest_output_buffer_size directive. Upstream, proxy and fastcgi code used to handle the old-style feature is removed.
author Roman Arutyunyan <arut@nginx.com>
date Wed, 28 Feb 2018 16:56:58 +0300
parents 6ba68ad8b24c
children 098bbd076a2d
comparison
equal deleted inserted replaced
7219:d0d32b33167d 7220:20f139e9ffa8
52 ngx_http_upstream_t *u); 52 ngx_http_upstream_t *u);
53 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r, 53 static ngx_int_t ngx_http_upstream_intercept_errors(ngx_http_request_t *r,
54 ngx_http_upstream_t *u); 54 ngx_http_upstream_t *u);
55 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c); 55 static ngx_int_t ngx_http_upstream_test_connect(ngx_connection_t *c);
56 static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r, 56 static ngx_int_t ngx_http_upstream_process_headers(ngx_http_request_t *r,
57 ngx_http_upstream_t *u);
58 static void ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
59 ngx_http_upstream_t *u); 57 ngx_http_upstream_t *u);
60 static void ngx_http_upstream_send_response(ngx_http_request_t *r, 58 static void ngx_http_upstream_send_response(ngx_http_request_t *r,
61 ngx_http_upstream_t *u); 59 ngx_http_upstream_t *u);
62 static void ngx_http_upstream_upgrade(ngx_http_request_t *r, 60 static void ngx_http_upstream_upgrade(ngx_http_request_t *r,
63 ngx_http_upstream_t *u); 61 ngx_http_upstream_t *u);
2333 2331
2334 if (ngx_http_upstream_process_headers(r, u) != NGX_OK) { 2332 if (ngx_http_upstream_process_headers(r, u) != NGX_OK) {
2335 return; 2333 return;
2336 } 2334 }
2337 2335
2338 if (!r->subrequest_in_memory) { 2336 ngx_http_upstream_send_response(r, u);
2339 ngx_http_upstream_send_response(r, u);
2340 return;
2341 }
2342
2343 /* subrequest content in memory */
2344
2345 if (u->input_filter == NULL) {
2346 u->input_filter_init = ngx_http_upstream_non_buffered_filter_init;
2347 u->input_filter = ngx_http_upstream_non_buffered_filter;
2348 u->input_filter_ctx = r;
2349 }
2350
2351 if (u->input_filter_init(u->input_filter_ctx) == NGX_ERROR) {
2352 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2353 return;
2354 }
2355
2356 n = u->buffer.last - u->buffer.pos;
2357
2358 if (n) {
2359 u->buffer.last = u->buffer.pos;
2360
2361 u->state->response_length += n;
2362
2363 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2364 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2365 return;
2366 }
2367 }
2368
2369 if (u->length == 0) {
2370 ngx_http_upstream_finalize_request(r, u, 0);
2371 return;
2372 }
2373
2374 u->read_event_handler = ngx_http_upstream_process_body_in_memory;
2375
2376 ngx_http_upstream_process_body_in_memory(r, u);
2377 } 2337 }
2378 2338
2379 2339
2380 static ngx_int_t 2340 static ngx_int_t
2381 ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u) 2341 ngx_http_upstream_test_next(ngx_http_request_t *r, ngx_http_upstream_t *u)
2770 } 2730 }
2771 2731
2772 u->length = -1; 2732 u->length = -1;
2773 2733
2774 return NGX_OK; 2734 return NGX_OK;
2775 }
2776
2777
2778 static void
2779 ngx_http_upstream_process_body_in_memory(ngx_http_request_t *r,
2780 ngx_http_upstream_t *u)
2781 {
2782 size_t size;
2783 ssize_t n;
2784 ngx_buf_t *b;
2785 ngx_event_t *rev;
2786 ngx_connection_t *c;
2787
2788 c = u->peer.connection;
2789 rev = c->read;
2790
2791 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
2792 "http upstream process body in memory");
2793
2794 if (rev->timedout) {
2795 ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out");
2796 ngx_http_upstream_finalize_request(r, u, NGX_HTTP_GATEWAY_TIME_OUT);
2797 return;
2798 }
2799
2800 b = &u->buffer;
2801
2802 for ( ;; ) {
2803
2804 size = b->end - b->last;
2805
2806 if (size == 0) {
2807 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2808 "upstream buffer is too small to read response");
2809 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2810 return;
2811 }
2812
2813 n = c->recv(c, b->last, size);
2814
2815 if (n == NGX_AGAIN) {
2816 break;
2817 }
2818
2819 if (n == 0 || n == NGX_ERROR) {
2820 ngx_http_upstream_finalize_request(r, u, n);
2821 return;
2822 }
2823
2824 u->state->bytes_received += n;
2825 u->state->response_length += n;
2826
2827 if (u->input_filter(u->input_filter_ctx, n) == NGX_ERROR) {
2828 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2829 return;
2830 }
2831
2832 if (!rev->ready) {
2833 break;
2834 }
2835 }
2836
2837 if (u->length == 0) {
2838 ngx_http_upstream_finalize_request(r, u, 0);
2839 return;
2840 }
2841
2842 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2843 ngx_http_upstream_finalize_request(r, u, NGX_ERROR);
2844 return;
2845 }
2846
2847 if (rev->active) {
2848 ngx_add_timer(rev, u->conf->read_timeout);
2849
2850 } else if (rev->timer_set) {
2851 ngx_del_timer(rev);
2852 }
2853 } 2735 }
2854 2736
2855 2737
2856 static void 2738 static void
2857 ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) 2739 ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u)
4357 ngx_http_file_cache_free(r->cache, u->pipe->temp_file); 4239 ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
4358 } 4240 }
4359 4241
4360 #endif 4242 #endif
4361 4243
4362 if (r->subrequest_in_memory
4363 && u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE)
4364 {
4365 u->buffer.last = u->buffer.pos;
4366 }
4367
4368 r->read_event_handler = ngx_http_block_reading; 4244 r->read_event_handler = ngx_http_block_reading;
4369 4245
4370 if (rc == NGX_DECLINED) { 4246 if (rc == NGX_DECLINED) {
4371 return; 4247 return;
4372 } 4248 }