diff src/http/ngx_http_postpone_filter_module.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 d87f29d764ce
children 43585e0e12a3
line wrap: on
line diff
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -12,6 +12,8 @@
 
 static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r,
     ngx_chain_t *in);
+static ngx_int_t ngx_http_postpone_filter_in_memory(ngx_http_request_t *r,
+    ngx_chain_t *in);
 static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf);
 
 
@@ -60,6 +62,10 @@ ngx_http_postpone_filter(ngx_http_reques
     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
 
+    if (r->subrequest_in_memory) {
+        return ngx_http_postpone_filter_in_memory(r, in);
+    }
+
     if (r != c->data) {
 
         if (in) {
@@ -172,6 +178,78 @@ found:
 
 
 static ngx_int_t
+ngx_http_postpone_filter_in_memory(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    size_t                     len;
+    ngx_buf_t                 *b;
+    ngx_connection_t          *c;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    c = r->connection;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http postpone filter in memory");
+
+    if (r->out == NULL) {
+        r->out = ngx_alloc_chain_link(r->pool);
+        if (r->out == NULL) {
+            return NGX_ERROR;
+        }
+
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+        if (r->headers_out.content_length_n != -1) {
+            len = r->headers_out.content_length_n;
+
+            if (len > clcf->subrequest_output_buffer_size) {
+                ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                              "too big subrequest response: %uz", len);
+                return NGX_ERROR;
+            }
+
+        } else {
+            len = clcf->subrequest_output_buffer_size;
+        }
+
+        b = ngx_create_temp_buf(r->pool, len);
+        if (b == NULL) {
+            return NGX_ERROR;
+        }
+
+        b->last_buf = 1;
+
+        r->out->buf = b;
+        r->out->next = NULL;
+    }
+
+    b = r->out->buf;
+
+    for ( /* void */ ; in; in = in->next) {
+
+        if (ngx_buf_special(in->buf)) {
+            continue;
+        }
+
+        len = in->buf->last - in->buf->pos;
+
+        if (len > (size_t) (b->end - b->last)) {
+            ngx_log_error(NGX_LOG_ERR, c->log, 0,
+                          "too big subrequest response");
+            return NGX_ERROR;
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                       "http postpone filter in memory %uz bytes", len);
+
+        b->last = ngx_cpymem(b->last, in->buf->pos, len);
+        in->buf->pos = in->buf->last;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_postpone_filter_init(ngx_conf_t *cf)
 {
     ngx_http_next_body_filter = ngx_http_top_body_filter;