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     r->preserve_body = 1;
0127 
0128     return ngx_http_next_header_filter(r);
0129 }
0130 
0131 
0132 static ngx_int_t
0133 ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
0134 {
0135     ngx_int_t                  rc;
0136     ngx_uint_t                 last;
0137     ngx_chain_t               *cl;
0138     ngx_http_request_t        *sr;
0139     ngx_http_addition_ctx_t   *ctx;
0140     ngx_http_addition_conf_t  *conf;
0141 
0142     if (in == NULL || r->header_only) {
0143         return ngx_http_next_body_filter(r, in);
0144     }
0145 
0146     ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module);
0147 
0148     if (ctx == NULL) {
0149         return ngx_http_next_body_filter(r, in);
0150     }
0151 
0152     conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
0153 
0154     if (!ctx->before_body_sent) {
0155         ctx->before_body_sent = 1;
0156 
0157         if (conf->before_body.len) {
0158             if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0)
0159                 != NGX_OK)
0160             {
0161                 return NGX_ERROR;
0162             }
0163         }
0164     }
0165 
0166     if (conf->after_body.len == 0) {
0167         ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
0168         return ngx_http_next_body_filter(r, in);
0169     }
0170 
0171     last = 0;
0172 
0173     for (cl = in; cl; cl = cl->next) {
0174         if (cl->buf->last_buf) {
0175             cl->buf->last_buf = 0;
0176             cl->buf->last_in_chain = 1;
0177             cl->buf->sync = 1;
0178             last = 1;
0179         }
0180     }
0181 
0182     rc = ngx_http_next_body_filter(r, in);
0183 
0184     if (rc == NGX_ERROR || !last || conf->after_body.len == 0) {
0185         return rc;
0186     }
0187 
0188     if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0)
0189         != NGX_OK)
0190     {
0191         return NGX_ERROR;
0192     }
0193 
0194     ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
0195 
0196     return ngx_http_send_special(r, NGX_HTTP_LAST);
0197 }
0198 
0199 
0200 static ngx_int_t
0201 ngx_http_addition_filter_init(ngx_conf_t *cf)
0202 {
0203     ngx_http_next_header_filter = ngx_http_top_header_filter;
0204     ngx_http_top_header_filter = ngx_http_addition_header_filter;
0205 
0206     ngx_http_next_body_filter = ngx_http_top_body_filter;
0207     ngx_http_top_body_filter = ngx_http_addition_body_filter;
0208 
0209     return NGX_OK;
0210 }
0211 
0212 
0213 static void *
0214 ngx_http_addition_create_conf(ngx_conf_t *cf)
0215 {
0216     ngx_http_addition_conf_t  *conf;
0217 
0218     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t));
0219     if (conf == NULL) {
0220         return NULL;
0221     }
0222 
0223     /*
0224      * set by ngx_pcalloc():
0225      *
0226      *     conf->before_body = { 0, NULL };
0227      *     conf->after_body = { 0, NULL };
0228      *     conf->types = { NULL };
0229      *     conf->types_keys = NULL;
0230      */
0231 
0232     return conf;
0233 }
0234 
0235 
0236 static char *
0237 ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
0238 {
0239     ngx_http_addition_conf_t *prev = parent;
0240     ngx_http_addition_conf_t *conf = child;
0241 
0242     ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
0243     ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");
0244 
0245     if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
0246                              &prev->types_keys, &prev->types,
0247                              ngx_http_html_default_types)
0248         != NGX_OK)
0249     {
0250         return NGX_CONF_ERROR;
0251     }
0252 
0253     return NGX_CONF_OK;
0254 }