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) Roman Arutyunyan
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_array_t  *mirror;
0015     ngx_flag_t    request_body;
0016 } ngx_http_mirror_loc_conf_t;
0017 
0018 
0019 typedef struct {
0020     ngx_int_t     status;
0021 } ngx_http_mirror_ctx_t;
0022 
0023 
0024 static ngx_int_t ngx_http_mirror_handler(ngx_http_request_t *r);
0025 static void ngx_http_mirror_body_handler(ngx_http_request_t *r);
0026 static ngx_int_t ngx_http_mirror_handler_internal(ngx_http_request_t *r);
0027 static void *ngx_http_mirror_create_loc_conf(ngx_conf_t *cf);
0028 static char *ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent,
0029     void *child);
0030 static char *ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
0031 static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf);
0032 
0033 
0034 static ngx_command_t  ngx_http_mirror_commands[] = {
0035 
0036     { ngx_string("mirror"),
0037       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
0038       ngx_http_mirror,
0039       NGX_HTTP_LOC_CONF_OFFSET,
0040       0,
0041       NULL },
0042 
0043     { ngx_string("mirror_request_body"),
0044       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
0045       ngx_conf_set_flag_slot,
0046       NGX_HTTP_LOC_CONF_OFFSET,
0047       offsetof(ngx_http_mirror_loc_conf_t, request_body),
0048       NULL },
0049 
0050       ngx_null_command
0051 };
0052 
0053 
0054 static ngx_http_module_t  ngx_http_mirror_module_ctx = {
0055     NULL,                                  /* preconfiguration */
0056     ngx_http_mirror_init,                  /* postconfiguration */
0057 
0058     NULL,                                  /* create main configuration */
0059     NULL,                                  /* init main configuration */
0060 
0061     NULL,                                  /* create server configuration */
0062     NULL,                                  /* merge server configuration */
0063 
0064     ngx_http_mirror_create_loc_conf,       /* create location configuration */
0065     ngx_http_mirror_merge_loc_conf         /* merge location configuration */
0066 };
0067 
0068 
0069 ngx_module_t  ngx_http_mirror_module = {
0070     NGX_MODULE_V1,
0071     &ngx_http_mirror_module_ctx,           /* module context */
0072     ngx_http_mirror_commands,              /* module directives */
0073     NGX_HTTP_MODULE,                       /* module type */
0074     NULL,                                  /* init master */
0075     NULL,                                  /* init module */
0076     NULL,                                  /* init process */
0077     NULL,                                  /* init thread */
0078     NULL,                                  /* exit thread */
0079     NULL,                                  /* exit process */
0080     NULL,                                  /* exit master */
0081     NGX_MODULE_V1_PADDING
0082 };
0083 
0084 
0085 static ngx_int_t
0086 ngx_http_mirror_handler(ngx_http_request_t *r)
0087 {
0088     ngx_int_t                    rc;
0089     ngx_http_mirror_ctx_t       *ctx;
0090     ngx_http_mirror_loc_conf_t  *mlcf;
0091 
0092     if (r != r->main) {
0093         return NGX_DECLINED;
0094     }
0095 
0096     mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);
0097 
0098     if (mlcf->mirror == NULL) {
0099         return NGX_DECLINED;
0100     }
0101 
0102     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler");
0103 
0104     if (mlcf->request_body) {
0105         ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);
0106 
0107         if (ctx) {
0108             return ctx->status;
0109         }
0110 
0111         ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_mirror_ctx_t));
0112         if (ctx == NULL) {
0113             return NGX_ERROR;
0114         }
0115 
0116         ctx->status = NGX_DONE;
0117 
0118         ngx_http_set_ctx(r, ctx, ngx_http_mirror_module);
0119 
0120         rc = ngx_http_read_client_request_body(r, ngx_http_mirror_body_handler);
0121         if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
0122             return rc;
0123         }
0124 
0125         ngx_http_finalize_request(r, NGX_DONE);
0126         return NGX_DONE;
0127     }
0128 
0129     return ngx_http_mirror_handler_internal(r);
0130 }
0131 
0132 
0133 static void
0134 ngx_http_mirror_body_handler(ngx_http_request_t *r)
0135 {
0136     ngx_http_mirror_ctx_t  *ctx;
0137 
0138     ctx = ngx_http_get_module_ctx(r, ngx_http_mirror_module);
0139 
0140     ctx->status = ngx_http_mirror_handler_internal(r);
0141 
0142     r->preserve_body = 1;
0143 
0144     r->write_event_handler = ngx_http_core_run_phases;
0145     ngx_http_core_run_phases(r);
0146 }
0147 
0148 
0149 static ngx_int_t
0150 ngx_http_mirror_handler_internal(ngx_http_request_t *r)
0151 {
0152     ngx_str_t                   *name;
0153     ngx_uint_t                   i;
0154     ngx_http_request_t          *sr;
0155     ngx_http_mirror_loc_conf_t  *mlcf;
0156 
0157     mlcf = ngx_http_get_module_loc_conf(r, ngx_http_mirror_module);
0158 
0159     name = mlcf->mirror->elts;
0160 
0161     for (i = 0; i < mlcf->mirror->nelts; i++) {
0162         if (ngx_http_subrequest(r, &name[i], &r->args, &sr, NULL,
0163                                 NGX_HTTP_SUBREQUEST_BACKGROUND)
0164             != NGX_OK)
0165         {
0166             return NGX_HTTP_INTERNAL_SERVER_ERROR;
0167         }
0168 
0169         sr->header_only = 1;
0170         sr->method = r->method;
0171         sr->method_name = r->method_name;
0172     }
0173 
0174     return NGX_DECLINED;
0175 }
0176 
0177 
0178 static void *
0179 ngx_http_mirror_create_loc_conf(ngx_conf_t *cf)
0180 {
0181     ngx_http_mirror_loc_conf_t  *mlcf;
0182 
0183     mlcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_mirror_loc_conf_t));
0184     if (mlcf == NULL) {
0185         return NULL;
0186     }
0187 
0188     mlcf->mirror = NGX_CONF_UNSET_PTR;
0189     mlcf->request_body = NGX_CONF_UNSET;
0190 
0191     return mlcf;
0192 }
0193 
0194 
0195 static char *
0196 ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
0197 {
0198     ngx_http_mirror_loc_conf_t *prev = parent;
0199     ngx_http_mirror_loc_conf_t *conf = child;
0200 
0201     ngx_conf_merge_ptr_value(conf->mirror, prev->mirror, NULL);
0202     ngx_conf_merge_value(conf->request_body, prev->request_body, 1);
0203 
0204     return NGX_CONF_OK;
0205 }
0206 
0207 
0208 static char *
0209 ngx_http_mirror(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
0210 {
0211     ngx_http_mirror_loc_conf_t *mlcf = conf;
0212 
0213     ngx_str_t  *value, *s;
0214 
0215     value = cf->args->elts;
0216 
0217     if (ngx_strcmp(value[1].data, "off") == 0) {
0218         if (mlcf->mirror != NGX_CONF_UNSET_PTR) {
0219             return "is duplicate";
0220         }
0221 
0222         mlcf->mirror = NULL;
0223         return NGX_CONF_OK;
0224     }
0225 
0226     if (mlcf->mirror == NULL) {
0227         return "is duplicate";
0228     }
0229 
0230     if (mlcf->mirror == NGX_CONF_UNSET_PTR) {
0231         mlcf->mirror = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
0232         if (mlcf->mirror == NULL) {
0233             return NGX_CONF_ERROR;
0234         }
0235     }
0236 
0237     s = ngx_array_push(mlcf->mirror);
0238     if (s == NULL) {
0239         return NGX_CONF_ERROR;
0240     }
0241 
0242     *s = value[1];
0243 
0244     return NGX_CONF_OK;
0245 }
0246 
0247 
0248 static ngx_int_t
0249 ngx_http_mirror_init(ngx_conf_t *cf)
0250 {
0251     ngx_http_handler_pt        *h;
0252     ngx_http_core_main_conf_t  *cmcf;
0253 
0254     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
0255 
0256     h = ngx_array_push(&cmcf->phases[NGX_HTTP_PRECONTENT_PHASE].handlers);
0257     if (h == NULL) {
0258         return NGX_ERROR;
0259     }
0260 
0261     *h = ngx_http_mirror_handler;
0262 
0263     return NGX_OK;
0264 }