Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

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 typedef struct {
0014     ngx_str_t     before_body;
0015     ngx_str_t     after_body;
0016 
0017     ngx_hash_t    types;
0018     ngx_array_t  *types_keys;
0019 } ngx_http_addition_conf_t;
0020 
0021 
0022 typedef struct {
0023     ngx_uint_t    before_body_sent;
0024 } ngx_http_addition_ctx_t;
0025 
0026 
0027 static void *ngx_http_addition_create_conf(ngx_conf_t *cf);
0028 static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent,
0029     void *child);
0030 static ngx_int_t ngx_http_addition_filter_init(ngx_conf_t *cf);
0031 
0032 
0033 static ngx_command_t  ngx_http_addition_commands[] = {
0034 
0035     { ngx_string("add_before_body"),
0036       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0037       ngx_conf_set_str_slot,
0038       NGX_HTTP_LOC_CONF_OFFSET,
0039       offsetof(ngx_http_addition_conf_t, before_body),
0040       NULL },
0041 
0042     { ngx_string("add_after_body"),
0043       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0044       ngx_conf_set_str_slot,
0045       NGX_HTTP_LOC_CONF_OFFSET,
0046       offsetof(ngx_http_addition_conf_t, after_body),
0047       NULL },
0048 
0049     { ngx_string("addition_types"),
0050       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
0051       ngx_http_types_slot,
0052       NGX_HTTP_LOC_CONF_OFFSET,
0053       offsetof(ngx_http_addition_conf_t, types_keys),
0054       &ngx_http_html_default_types[0] },
0055 
0056       ngx_null_command
0057 };
0058 
0059 
0060 static ngx_http_module_t  ngx_http_addition_filter_module_ctx = {
0061     NULL,                                  /* preconfiguration */
0062     ngx_http_addition_filter_init,         /* postconfiguration */
0063 
0064     NULL,                                  /* create main configuration */
0065     NULL,                                  /* init main configuration */
0066 
0067     NULL,                                  /* create server configuration */
0068     NULL,                                  /* merge server configuration */
0069 
0070     ngx_http_addition_create_conf,         /* create location configuration */
0071     ngx_http_addition_merge_conf           /* merge location configuration */
0072 };
0073 
0074 
0075 ngx_module_t  ngx_http_addition_filter_module = {
0076     NGX_MODULE_V1,
0077     &ngx_http_addition_filter_module_ctx,  /* module context */
0078     ngx_http_addition_commands,            /* module directives */
0079     NGX_HTTP_MODULE,                       /* module type */
0080     NULL,                                  /* init master */
0081     NULL,                                  /* init module */
0082     NULL,                                  /* init process */
0083     NULL,                                  /* init thread */
0084     NULL,                                  /* exit thread */
0085     NULL,                                  /* exit process */
0086     NULL,                                  /* exit master */
0087     NGX_MODULE_V1_PADDING
0088 };
0089 
0090 
0091 static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
0092 static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
0093 
0094 
0095 static ngx_int_t
0096 ngx_http_addition_header_filter(ngx_http_request_t *r)
0097 {
0098     ngx_http_addition_ctx_t   *ctx;
0099     ngx_http_addition_conf_t  *conf;
0100 
0101     if (r->headers_out.status != NGX_HTTP_OK || r != r->main) {
0102         return ngx_http_next_header_filter(r);
0103     }
0104 
0105     conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
0106 
0107     if (conf->before_body.len == 0 && conf->after_body.len == 0) {
0108         return ngx_http_next_header_filter(r);
0109     }
0110 
0111     if (ngx_http_test_content_type(r, &conf->types) == NULL) {
0112         return ngx_http_next_header_filter(r);
0113     }
0114 
0115     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t));
0116     if (ctx == NULL) {
0117         return NGX_ERROR;
0118     }
0119 
0120     ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module);
0121 
0122     ngx_http_clear_content_length(r);
0123     ngx_http_clear_accept_ranges(r);
0124     ngx_http_weak_etag(r);
0125 
0126     return ngx_http_next_header_filter(r);
0127 }
0128 
0129 
0130 static ngx_int_t
0131 ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
0132 {
0133     ngx_int_t                  rc;
0134     ngx_uint_t                 last;
0135     ngx_chain_t               *cl;
0136     ngx_http_request_t        *sr;
0137     ngx_http_addition_ctx_t   *ctx;
0138     ngx_http_addition_conf_t  *conf;
0139 
0140     if (in == NULL || r->header_only) {
0141         return ngx_http_next_body_filter(r, in);
0142     }
0143 
0144     ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module);
0145 
0146     if (ctx == NULL) {
0147         return ngx_http_next_body_filter(r, in);
0148     }
0149 
0150     conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
0151 
0152     if (!ctx->before_body_sent) {
0153         ctx->before_body_sent = 1;
0154 
0155         if (conf->before_body.len) {
0156             if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0)
0157                 != NGX_OK)
0158             {
0159                 return NGX_ERROR;
0160             }
0161         }
0162     }
0163 
0164     if (conf->after_body.len == 0) {
0165         ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
0166         return ngx_http_next_body_filter(r, in);
0167     }
0168 
0169     last = 0;
0170 
0171     for (cl = in; cl; cl = cl->next) {
0172         if (cl->buf->last_buf) {
0173             cl->buf->last_buf = 0;
0174             cl->buf->last_in_chain = 1;
0175             cl->buf->sync = 1;
0176             last = 1;
0177         }
0178     }
0179 
0180     rc = ngx_http_next_body_filter(r, in);
0181 
0182     if (rc == NGX_ERROR || !last || conf->after_body.len == 0) {
0183         return rc;
0184     }
0185 
0186     if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0)
0187         != NGX_OK)
0188     {
0189         return NGX_ERROR;
0190     }
0191 
0192     ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
0193 
0194     return ngx_http_send_special(r, NGX_HTTP_LAST);
0195 }
0196 
0197 
0198 static ngx_int_t
0199 ngx_http_addition_filter_init(ngx_conf_t *cf)
0200 {
0201     ngx_http_next_header_filter = ngx_http_top_header_filter;
0202     ngx_http_top_header_filter = ngx_http_addition_header_filter;
0203 
0204     ngx_http_next_body_filter = ngx_http_top_body_filter;
0205     ngx_http_top_body_filter = ngx_http_addition_body_filter;
0206 
0207     return NGX_OK;
0208 }
0209 
0210 
0211 static void *
0212 ngx_http_addition_create_conf(ngx_conf_t *cf)
0213 {
0214     ngx_http_addition_conf_t  *conf;
0215 
0216     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t));
0217     if (conf == NULL) {
0218         return NULL;
0219     }
0220 
0221     /*
0222      * set by ngx_pcalloc():
0223      *
0224      *     conf->before_body = { 0, NULL };
0225      *     conf->after_body = { 0, NULL };
0226      *     conf->types = { NULL };
0227      *     conf->types_keys = NULL;
0228      */
0229 
0230     return conf;
0231 }
0232 
0233 
0234 static char *
0235 ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
0236 {
0237     ngx_http_addition_conf_t *prev = parent;
0238     ngx_http_addition_conf_t *conf = child;
0239 
0240     ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
0241     ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
0242 
0243     if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
0244                              &prev->types_keys, &prev->types,
0245                              ngx_http_html_default_types)
0246         != NGX_OK)
0247     {
0248         return NGX_CONF_ERROR;
0249     }
0250 
0251     return NGX_CONF_OK;
0252 }