Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.15.12 ]​[ nginx-1.16.0 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 static ngx_int_t ngx_http_postpone_filter_add(ngx_http_request_t *r,
0014     ngx_chain_t *in);
0015 static ngx_int_t ngx_http_postpone_filter_in_memory(ngx_http_request_t *r,
0016     ngx_chain_t *in);
0017 static ngx_int_t ngx_http_postpone_filter_init(ngx_conf_t *cf);
0018 
0019 
0020 static ngx_http_module_t  ngx_http_postpone_filter_module_ctx = {
0021     NULL,                                  /* preconfiguration */
0022     ngx_http_postpone_filter_init,         /* postconfiguration */
0023 
0024     NULL,                                  /* create main configuration */
0025     NULL,                                  /* init main configuration */
0026 
0027     NULL,                                  /* create server configuration */
0028     NULL,                                  /* merge server configuration */
0029 
0030     NULL,                                  /* create location configuration */
0031     NULL                                   /* merge location configuration */
0032 };
0033 
0034 
0035 ngx_module_t  ngx_http_postpone_filter_module = {
0036     NGX_MODULE_V1,
0037     &ngx_http_postpone_filter_module_ctx,  /* module context */
0038     NULL,                                  /* module directives */
0039     NGX_HTTP_MODULE,                       /* module type */
0040     NULL,                                  /* init master */
0041     NULL,                                  /* init module */
0042     NULL,                                  /* init process */
0043     NULL,                                  /* init thread */
0044     NULL,                                  /* exit thread */
0045     NULL,                                  /* exit process */
0046     NULL,                                  /* exit master */
0047     NGX_MODULE_V1_PADDING
0048 };
0049 
0050 
0051 static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
0052 
0053 
0054 static ngx_int_t
0055 ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
0056 {
0057     ngx_connection_t              *c;
0058     ngx_http_postponed_request_t  *pr;
0059 
0060     c = r->connection;
0061 
0062     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
0063                    "http postpone filter \"%V?%V\" %p", &r->uri, &r->args, in);
0064 
0065     if (r->subrequest_in_memory) {
0066         return ngx_http_postpone_filter_in_memory(r, in);
0067     }
0068 
0069     if (r != c->data) {
0070 
0071         if (in) {
0072             if (ngx_http_postpone_filter_add(r, in) != NGX_OK) {
0073                 return NGX_ERROR;
0074             }
0075 
0076             return NGX_OK;
0077         }
0078 
0079 #if 0
0080         /* TODO: SSI may pass NULL */
0081         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0082                       "http postpone filter NULL inactive request");
0083 #endif
0084 
0085         return NGX_OK;
0086     }
0087 
0088     if (r->postponed == NULL) {
0089 
0090         if (in || c->buffered) {
0091             return ngx_http_next_body_filter(r->main, in);
0092         }
0093 
0094         return NGX_OK;
0095     }
0096 
0097     if (in) {
0098         if (ngx_http_postpone_filter_add(r, in) != NGX_OK) {
0099             return NGX_ERROR;
0100         }
0101     }
0102 
0103     do {
0104         pr = r->postponed;
0105 
0106         if (pr->request) {
0107 
0108             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
0109                            "http postpone filter wake \"%V?%V\"",
0110                            &pr->request->uri, &pr->request->args);
0111 
0112             r->postponed = pr->next;
0113 
0114             c->data = pr->request;
0115 
0116             return ngx_http_post_request(pr->request, NULL);
0117         }
0118 
0119         if (pr->out == NULL) {
0120             ngx_log_error(NGX_LOG_ALERT, c->log, 0,
0121                           "http postpone filter NULL output");
0122 
0123         } else {
0124             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
0125                            "http postpone filter output \"%V?%V\"",
0126                            &r->uri, &r->args);
0127 
0128             if (ngx_http_next_body_filter(r->main, pr->out) == NGX_ERROR) {
0129                 return NGX_ERROR;
0130             }
0131         }
0132 
0133         r->postponed = pr->next;
0134 
0135     } while (r->postponed);
0136 
0137     return NGX_OK;
0138 }
0139 
0140 
0141 static ngx_int_t
0142 ngx_http_postpone_filter_add(ngx_http_request_t *r, ngx_chain_t *in)
0143 {
0144     ngx_http_postponed_request_t  *pr, **ppr;
0145 
0146     if (r->postponed) {
0147         for (pr = r->postponed; pr->next; pr = pr->next) { /* void */ }
0148 
0149         if (pr->request == NULL) {
0150             goto found;
0151         }
0152 
0153         ppr = &pr->next;
0154 
0155     } else {
0156         ppr = &r->postponed;
0157     }
0158 
0159     pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
0160     if (pr == NULL) {
0161         return NGX_ERROR;
0162     }
0163 
0164     *ppr = pr;
0165 
0166     pr->request = NULL;
0167     pr->out = NULL;
0168     pr->next = NULL;
0169 
0170 found:
0171 
0172     if (ngx_chain_add_copy(r->pool, &pr->out, in) == NGX_OK) {
0173         return NGX_OK;
0174     }
0175 
0176     return NGX_ERROR;
0177 }
0178 
0179 
0180 static ngx_int_t
0181 ngx_http_postpone_filter_in_memory(ngx_http_request_t *r, ngx_chain_t *in)
0182 {
0183     size_t                     len;
0184     ngx_buf_t                 *b;
0185     ngx_connection_t          *c;
0186     ngx_http_core_loc_conf_t  *clcf;
0187 
0188     c = r->connection;
0189 
0190     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
0191                    "http postpone filter in memory");
0192 
0193     if (r->out == NULL) {
0194         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0195 
0196         if (r->headers_out.content_length_n != -1) {
0197             len = r->headers_out.content_length_n;
0198 
0199             if (len > clcf->subrequest_output_buffer_size) {
0200                 ngx_log_error(NGX_LOG_ERR, c->log, 0,
0201                               "too big subrequest response: %uz", len);
0202                 return NGX_ERROR;
0203             }
0204 
0205         } else {
0206             len = clcf->subrequest_output_buffer_size;
0207         }
0208 
0209         b = ngx_create_temp_buf(r->pool, len);
0210         if (b == NULL) {
0211             return NGX_ERROR;
0212         }
0213 
0214         b->last_buf = 1;
0215 
0216         r->out = ngx_alloc_chain_link(r->pool);
0217         if (r->out == NULL) {
0218             return NGX_ERROR;
0219         }
0220 
0221         r->out->buf = b;
0222         r->out->next = NULL;
0223     }
0224 
0225     b = r->out->buf;
0226 
0227     for ( /* void */ ; in; in = in->next) {
0228 
0229         if (ngx_buf_special(in->buf)) {
0230             continue;
0231         }
0232 
0233         len = in->buf->last - in->buf->pos;
0234 
0235         if (len > (size_t) (b->end - b->last)) {
0236             ngx_log_error(NGX_LOG_ERR, c->log, 0,
0237                           "too big subrequest response");
0238             return NGX_ERROR;
0239         }
0240 
0241         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
0242                        "http postpone filter in memory %uz bytes", len);
0243 
0244         b->last = ngx_cpymem(b->last, in->buf->pos, len);
0245         in->buf->pos = in->buf->last;
0246     }
0247 
0248     return NGX_OK;
0249 }
0250 
0251 
0252 static ngx_int_t
0253 ngx_http_postpone_filter_init(ngx_conf_t *cf)
0254 {
0255     ngx_http_next_body_filter = ngx_http_top_body_filter;
0256     ngx_http_top_body_filter = ngx_http_postpone_filter;
0257 
0258     return NGX_OK;
0259 }