Mercurial > hg > nginx
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 } |