src/http/modules/ngx_http_addition_filter_module.c - nginx-1.7.10

Global variables defined

Data types defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_http.h>


  8. typedef struct {
  9.     ngx_str_t     before_body;
  10.     ngx_str_t     after_body;

  11.     ngx_hash_t    types;
  12.     ngx_array_t  *types_keys;
  13. } ngx_http_addition_conf_t;


  14. typedef struct {
  15.     ngx_uint_t    before_body_sent;
  16. } ngx_http_addition_ctx_t;


  17. static void *ngx_http_addition_create_conf(ngx_conf_t *cf);
  18. static char *ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent,
  19.     void *child);
  20. static ngx_int_t ngx_http_addition_filter_init(ngx_conf_t *cf);


  21. static ngx_command_t  ngx_http_addition_commands[] = {

  22.     { ngx_string("add_before_body"),
  23.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  24.       ngx_conf_set_str_slot,
  25.       NGX_HTTP_LOC_CONF_OFFSET,
  26.       offsetof(ngx_http_addition_conf_t, before_body),
  27.       NULL },

  28.     { ngx_string("add_after_body"),
  29.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
  30.       ngx_conf_set_str_slot,
  31.       NGX_HTTP_LOC_CONF_OFFSET,
  32.       offsetof(ngx_http_addition_conf_t, after_body),
  33.       NULL },

  34.     { ngx_string("addition_types"),
  35.       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
  36.       ngx_http_types_slot,
  37.       NGX_HTTP_LOC_CONF_OFFSET,
  38.       offsetof(ngx_http_addition_conf_t, types_keys),
  39.       &ngx_http_html_default_types[0] },

  40.       ngx_null_command
  41. };


  42. static ngx_http_module_t  ngx_http_addition_filter_module_ctx = {
  43.     NULL,                                  /* preconfiguration */
  44.     ngx_http_addition_filter_init,         /* postconfiguration */

  45.     NULL,                                  /* create main configuration */
  46.     NULL,                                  /* init main configuration */

  47.     NULL,                                  /* create server configuration */
  48.     NULL,                                  /* merge server configuration */

  49.     ngx_http_addition_create_conf,         /* create location configuration */
  50.     ngx_http_addition_merge_conf           /* merge location configuration */
  51. };


  52. ngx_module_t  ngx_http_addition_filter_module = {
  53.     NGX_MODULE_V1,
  54.     &ngx_http_addition_filter_module_ctx/* module context */
  55.     ngx_http_addition_commands,            /* module directives */
  56.     NGX_HTTP_MODULE,                       /* module type */
  57.     NULL,                                  /* init master */
  58.     NULL,                                  /* init module */
  59.     NULL,                                  /* init process */
  60.     NULL,                                  /* init thread */
  61.     NULL,                                  /* exit thread */
  62.     NULL,                                  /* exit process */
  63.     NULL,                                  /* exit master */
  64.     NGX_MODULE_V1_PADDING
  65. };


  66. static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
  67. static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;


  68. static ngx_int_t
  69. ngx_http_addition_header_filter(ngx_http_request_t *r)
  70. {
  71.     ngx_http_addition_ctx_t   *ctx;
  72.     ngx_http_addition_conf_t  *conf;

  73.     if (r->headers_out.status != NGX_HTTP_OK || r != r->main) {
  74.         return ngx_http_next_header_filter(r);
  75.     }

  76.     conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);

  77.     if (conf->before_body.len == 0 && conf->after_body.len == 0) {
  78.         return ngx_http_next_header_filter(r);
  79.     }

  80.     if (ngx_http_test_content_type(r, &conf->types) == NULL) {
  81.         return ngx_http_next_header_filter(r);
  82.     }

  83.     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t));
  84.     if (ctx == NULL) {
  85.         return NGX_ERROR;
  86.     }

  87.     ngx_http_set_ctx(r, ctx, ngx_http_addition_filter_module);

  88.     ngx_http_clear_content_length(r);
  89.     ngx_http_clear_accept_ranges(r);
  90.     ngx_http_weak_etag(r);

  91.     return ngx_http_next_header_filter(r);
  92. }


  93. static ngx_int_t
  94. ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
  95. {
  96.     ngx_int_t                  rc;
  97.     ngx_uint_t                 last;
  98.     ngx_chain_t               *cl;
  99.     ngx_http_request_t        *sr;
  100.     ngx_http_addition_ctx_t   *ctx;
  101.     ngx_http_addition_conf_t  *conf;

  102.     if (in == NULL || r->header_only) {
  103.         return ngx_http_next_body_filter(r, in);
  104.     }

  105.     ctx = ngx_http_get_module_ctx(r, ngx_http_addition_filter_module);

  106.     if (ctx == NULL) {
  107.         return ngx_http_next_body_filter(r, in);
  108.     }

  109.     conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);

  110.     if (!ctx->before_body_sent) {
  111.         ctx->before_body_sent = 1;

  112.         if (conf->before_body.len) {
  113.             if (ngx_http_subrequest(r, &conf->before_body, NULL, &sr, NULL, 0)
  114.                 != NGX_OK)
  115.             {
  116.                 return NGX_ERROR;
  117.             }
  118.         }
  119.     }

  120.     if (conf->after_body.len == 0) {
  121.         ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
  122.         return ngx_http_next_body_filter(r, in);
  123.     }

  124.     last = 0;

  125.     for (cl = in; cl; cl = cl->next) {
  126.         if (cl->buf->last_buf) {
  127.             cl->buf->last_buf = 0;
  128.             cl->buf->sync = 1;
  129.             last = 1;
  130.         }
  131.     }

  132.     rc = ngx_http_next_body_filter(r, in);

  133.     if (rc == NGX_ERROR || !last || conf->after_body.len == 0) {
  134.         return rc;
  135.     }

  136.     if (ngx_http_subrequest(r, &conf->after_body, NULL, &sr, NULL, 0)
  137.         != NGX_OK)
  138.     {
  139.         return NGX_ERROR;
  140.     }

  141.     ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);

  142.     return ngx_http_send_special(r, NGX_HTTP_LAST);
  143. }


  144. static ngx_int_t
  145. ngx_http_addition_filter_init(ngx_conf_t *cf)
  146. {
  147.     ngx_http_next_header_filter = ngx_http_top_header_filter;
  148.     ngx_http_top_header_filter = ngx_http_addition_header_filter;

  149.     ngx_http_next_body_filter = ngx_http_top_body_filter;
  150.     ngx_http_top_body_filter = ngx_http_addition_body_filter;

  151.     return NGX_OK;
  152. }


  153. static void *
  154. ngx_http_addition_create_conf(ngx_conf_t *cf)
  155. {
  156.     ngx_http_addition_conf_t  *conf;

  157.     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_addition_conf_t));
  158.     if (conf == NULL) {
  159.         return NULL;
  160.     }

  161.     /*
  162.      * set by ngx_pcalloc():
  163.      *
  164.      *     conf->before_body = { 0, NULL };
  165.      *     conf->after_body = { 0, NULL };
  166.      *     conf->types = { NULL };
  167.      *     conf->types_keys = NULL;
  168.      */

  169.     return conf;
  170. }


  171. static char *
  172. ngx_http_addition_merge_conf(ngx_conf_t *cf, void *parent, void *child)
  173. {
  174.     ngx_http_addition_conf_t *prev = parent;
  175.     ngx_http_addition_conf_t *conf = child;

  176.     ngx_conf_merge_str_value(conf->before_body, prev->before_body, "");
  177.     ngx_conf_merge_str_value(conf->after_body, prev->after_body, "");

  178.     if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types,
  179.                              &prev->types_keys, &prev->types,
  180.                              ngx_http_html_default_types)
  181.         != NGX_OK)
  182.     {
  183.         return NGX_CONF_ERROR;
  184.     }

  185.     return NGX_CONF_OK;
  186. }