Skip to content

Commit

Permalink
Added sources of eval module
Browse files Browse the repository at this point in the history
  • Loading branch information
Valery Kholodkov committed Apr 28, 2009
0 parents commit 3a3b15e
Show file tree
Hide file tree
Showing 3 changed files with 371 additions and 0 deletions.
24 changes: 24 additions & 0 deletions LICENCE
@@ -0,0 +1,24 @@
* Copyright (c) 2006, 2008, Valery Kholodkov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Valery Kholodkov nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY VALERY KHOLODKOV ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL VALERY KHOLODKOV BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3 changes: 3 additions & 0 deletions config
@@ -0,0 +1,3 @@
ngx_addon_name=ngx_http_eval_module
HTTP_MODULES="$HTTP_MODULES ngx_http_eval_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_eval_module.c"
344 changes: 344 additions & 0 deletions ngx_http_eval_module.c
@@ -0,0 +1,344 @@

/*
* Copyright (C) 2009 Valery Kholodkov
*/


#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

typedef struct {
ngx_int_t variable_index;
ngx_str_t eval_location;
unsigned int enabled;
} ngx_http_eval_loc_conf_t;

typedef struct {
ngx_http_variable_value_t *value;
unsigned int done;
} ngx_http_eval_ctx_t;

static ngx_int_t ngx_http_eval_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc);

static void *ngx_http_eval_create_loc_conf(ngx_conf_t *cf);
static char *ngx_http_eval_merge_loc_conf(ngx_conf_t *cf, void *parent,
void *child);

static char *ngx_http_eval_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);

static ngx_int_t ngx_http_eval_init(ngx_conf_t *cf);

static ngx_command_t ngx_http_eval_commands[] = {

{ ngx_string("eval"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1|NGX_CONF_BLOCK,
ngx_http_eval_block,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },

ngx_null_command
};

static ngx_http_module_t ngx_http_eval_module_ctx = {
NULL, /* preconfiguration */
ngx_http_eval_init, /* postconfiguration */

NULL, /* create main configuration */
NULL, /* init main configuration */

NULL, /* create server configuration */
NULL, /* merge server configuration */

ngx_http_eval_create_loc_conf, /* create location configuration */
ngx_http_eval_merge_loc_conf /* merge location configuration */
};

ngx_module_t ngx_http_eval_module = {
NGX_MODULE_V1,
&ngx_http_eval_module_ctx, /* module context */
ngx_http_eval_commands, /* module directives */
NGX_HTTP_MODULE, /* module type */
NULL, /* init master */
NULL, /* init module */
NULL, /* init process */
NULL, /* init thread */
NULL, /* exit thread */
NULL, /* exit process */
NULL, /* exit master */
NGX_MODULE_V1_PADDING
};

static ngx_int_t
ngx_http_eval_handler(ngx_http_request_t *r)
{
ngx_str_t args;
ngx_uint_t flags;
ngx_http_eval_loc_conf_t *ecf;
ngx_http_eval_ctx_t *ctx;
ngx_http_request_t *sr;
ngx_int_t rc;
ngx_http_post_subrequest_t *psr;

ecf = ngx_http_get_module_loc_conf(r, ngx_http_eval_module);

if(!ecf->enabled) {
return NGX_DECLINED;
}

ctx = ngx_http_get_module_ctx(r, ngx_http_eval_module);

if(ctx == NULL) {
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_eval_ctx_t));
if (ctx == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}

ngx_http_set_ctx(r, ctx, ngx_http_eval_module);
}

if(ctx->done) {
return NGX_DECLINED;
}

psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t));
if (psr == NULL) {
return NGX_ERROR;
}

ctx->value = r->variables + ecf->variable_index;

args.len = 0;
args.data = NULL;
flags = 0;

if (ngx_http_parse_unsafe_uri(r, &ecf->eval_location, &args, &flags) != NGX_OK) {
return NGX_ERROR;
}

psr->handler = ngx_http_eval_set_variable;
psr->data = ctx;

flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED;

rc = ngx_http_subrequest(r, &ecf->eval_location, &args, &sr, psr, flags);

if (rc == NGX_ERROR || rc == NGX_DONE) {
return rc;
}

/*
* Wait for subrequest to complete
*/
return NGX_AGAIN;
}

static ngx_int_t
ngx_http_eval_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc)
{
ngx_http_eval_ctx_t *ctx = data;

ctx->value->valid = 0;
ctx->value->not_found = 1;

if (r->upstream) {
ctx->value->len = r->upstream->buffer.last - r->upstream->buffer.pos;
ctx->value->data = r->upstream->buffer.pos;
ctx->value->valid = 1;
ctx->value->not_found = 0;
}

ctx->done = 1;

return NGX_OK;
}

static void *
ngx_http_eval_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_eval_loc_conf_t *conf;

conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_eval_loc_conf_t));

if (conf == NULL) {
return NGX_CONF_ERROR;
}

return conf;
}

static char *
ngx_http_eval_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
return NGX_CONF_OK;
}

static ngx_int_t
ngx_http_eval_variable(ngx_http_request_t *r,
ngx_http_variable_value_t *v, uintptr_t data)
{
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;

v->len = 0;
v->data = (u_char*)"";

return NGX_OK;
}

static char *
ngx_http_eval_add_variable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_eval_loc_conf_t *ecf = conf;

ngx_int_t index;
ngx_str_t *value;
ngx_http_variable_t *v;

value = cf->args->elts;

if (value[1].data[0] != '$') {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid variable name \"%V\"", &value[1]);
return NGX_CONF_ERROR;
}

value[1].len--;
value[1].data++;

v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
if (v == NULL) {
return NGX_CONF_ERROR;
}

index = ngx_http_get_variable_index(cf, &value[1]);
if (index == NGX_ERROR) {
return NGX_CONF_ERROR;
}

if (v->get_handler == NULL)
{
v->get_handler = ngx_http_eval_variable;
v->data = index;
}

ecf->variable_index = index;

return NGX_CONF_OK;
}

static char *
ngx_http_eval_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_http_eval_loc_conf_t *ecf, *pecf = conf;

char *rv;
void *mconf;
ngx_str_t name;
ngx_uint_t i;
ngx_conf_t save;
ngx_http_module_t *module;
ngx_http_conf_ctx_t *ctx, *pctx;
ngx_http_core_loc_conf_t *clcf, *pclcf, *rclcf;
ngx_http_core_srv_conf_t *cscf;

if(ngx_http_eval_add_variable(cf, cmd, conf) != NGX_CONF_OK) {
return NGX_CONF_ERROR;
}

ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
if (ctx == NULL) {
return NGX_CONF_ERROR;
}

pctx = cf->ctx;
ctx->main_conf = pctx->main_conf;
ctx->srv_conf = pctx->srv_conf;

ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
if (ctx->loc_conf == NULL) {
return NGX_CONF_ERROR;
}

for (i = 0; ngx_modules[i]; i++) {
if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
continue;
}

module = ngx_modules[i]->ctx;

if (module->create_loc_conf) {

mconf = module->create_loc_conf(cf);
if (mconf == NULL) {
return NGX_CONF_ERROR;
}

ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
}
}

ecf = ctx->loc_conf[ngx_http_eval_module.ctx_index];

pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];

clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];

name.len = sizeof("/eval_") - 1 + NGX_OFF_T_LEN;

name.data = ngx_palloc(cf->pool, name.len);

if(name.data == NULL) {
return NGX_CONF_ERROR;
}

name.len = ngx_sprintf(name.data, "/eval_%O", (off_t)(uintptr_t)clcf) - name.data;

clcf->loc_conf = ctx->loc_conf;
clcf->name = name;
clcf->exact_match = 1;
clcf->noname = 0;
clcf->internal = 1;
clcf->noregex = 1;

cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);

rclcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];

if (ngx_http_add_location(cf, &rclcf->locations, clcf) != NGX_OK) {
return NGX_CONF_ERROR;
}

pecf->eval_location = clcf->name;
pecf->enabled = 1;

save = *cf;
cf->ctx = ctx;
cf->cmd_type = NGX_HTTP_LOC_CONF;

rv = ngx_conf_parse(cf, NULL);

*cf = save;

return rv;
}

static ngx_int_t
ngx_http_eval_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h;
ngx_http_core_main_conf_t *cmcf;

cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
if (h == NULL) {
return NGX_ERROR;
}

*h = ngx_http_eval_handler;

return NGX_OK;
}

0 comments on commit 3a3b15e

Please sign in to comment.