在Openresty学习(九)基础上,定义新的内部变量my_method(表示请求的方法),增加对请求方法的检查。
配置:
location /hello {
default_type text/html;
check_version $server_protocol HTTP/1.1 $my_method GET;
content_by_lua_block {
ngx.say("HelloWorld")
}
}
测试:
如果是请求是HTTP 1.1协议并且请求方法是GET,则请求通过
如果请求是不是HTTP 1.1协议或者方法不是GET,则请求被禁止,返回403
源码:
config:
ngx_addon_name=ngx_http_check_version_module
HTTP_MODULES="$HTTP_MODULES ngx_http_check_version_module"
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_check_version_module.c"
/private/ngx_http_check_version_module/ngx_http_check_version_module.c:
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>
typedef struct {
int variable_index;
ngx_str_t variable_name;
ngx_str_t allow_version_value;
int my_method_index;
ngx_str_t my_method_name;
ngx_str_t allow_method_value;
} ngx_http_check_version_loc_conf_t;
static ngx_int_t ngx_http_check_version_handler(ngx_http_request_t *r);
static char *ngx_http_check_version(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_check_version_init(ngx_conf_t *cf);
static void *ngx_http_check_version_create_loc_conf(ngx_conf_t *cf);
static ngx_int_t ngx_http_check_version_add_variable(ngx_conf_t *cf);
static ngx_command_t ngx_http_check_version_commands[] =
{
{
ngx_string("check_version"),
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE4,
ngx_http_check_version,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL
},
ngx_null_command
};
static ngx_http_module_t ngx_http_check_version_module_ctx =
{
ngx_http_check_version_add_variable,
ngx_http_check_version_init,
NULL,
NULL,
NULL,
NULL,
ngx_http_check_version_create_loc_conf,
NULL
};
ngx_module_t ngx_http_check_version_module =
{
NGX_MODULE_V1,
&ngx_http_check_version_module_ctx,
ngx_http_check_version_commands,
NGX_HTTP_MODULE,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NGX_MODULE_V1_PADDING
};
static ngx_str_t my_method = ngx_string("my_method");
static ngx_int_t ngx_http_my_method_get_handler(
ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data)
{
v->not_found = 0;
v->data = r->method_name.data;
v->len = r->method_name.len;
v->valid = 1;
return NGX_OK;
}
static ngx_int_t ngx_http_check_version_add_variable(ngx_conf_t *cf)
{
ngx_http_variable_t *v = NULL;
v = ngx_http_add_variable(cf, &my_method,NGX_HTTP_VAR_CHANGEABLE);
if (NULL == v)
{
return NGX_ERROR;
}
v->get_handler = ngx_http_my_method_get_handler;
v->data = 0;
return NGX_OK;
}
static void *ngx_http_check_version_create_loc_conf(ngx_conf_t *cf)
{
ngx_http_check_version_loc_conf_t *conf = NULL;
conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_check_version_loc_conf_t));
if (NULL == conf)
{
return NULL;
}
conf->variable_index = -1;
return conf;
}
static ngx_int_t ngx_http_check_version_init(ngx_conf_t *cf)
{
ngx_http_handler_pt *h = NULL;
ngx_http_core_main_conf_t *cmcf = NULL;
cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
if (NULL == h)
{
return NGX_ERROR;
}
*h = ngx_http_check_version_handler;
return NGX_OK;
}
static char *ngx_http_check_version(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_str_t *value = NULL;
ngx_http_check_version_loc_conf_t *hlcf = NULL;
hlcf = conf;
value = cf->args->elts;
if (cf->args->nelts != 5)
{
return NGX_CONF_ERROR;
}
if (value[1].data[0] == '$')
{
value[1].data++;
value[1].len--;
hlcf->variable_index = ngx_http_get_variable_index(cf, &value[1]);
if (hlcf->variable_index == NGX_ERROR)
{
return NGX_CONF_ERROR;
}
hlcf->variable_name = value[1];
}
else
{
return NGX_CONF_ERROR;
}
hlcf->allow_version_value = value[2];
if (value[3].data[0] == '$')
{
value[3].data++;
value[3].len--;
hlcf->my_method_index = ngx_http_get_variable_index(cf, &value[3]);
if (hlcf->my_method_index == NGX_ERROR)
{
return NGX_CONF_ERROR;
}
hlcf->my_method_name = value[3];
}
else
{
return NGX_CONF_ERROR;
}
hlcf->allow_method_value = value[4];
return NGX_CONF_OK;
}
static ngx_int_t ngx_http_check_version_handler(ngx_http_request_t *r)
{
ngx_http_check_version_loc_conf_t *conf = NULL;
ngx_http_variable_value_t *request_version = NULL;
ngx_http_variable_value_t *request_method = NULL;
conf = ngx_http_get_module_loc_conf(r, ngx_http_check_version_module);
if (NULL == conf)
{
return NGX_ERROR;
}
if (-1 == conf->variable_index)
{
return NGX_DECLINED;
}
request_version = ngx_http_get_indexed_variable(r, conf->variable_index);
if (NULL == request_version || request_version->not_found)
{
return NGX_HTTP_FORBIDDEN;
}
request_method = ngx_http_get_indexed_variable(r, conf->my_method_index);
if (NULL == request_method || request_method->not_found)
{
return NGX_HTTP_FORBIDDEN;
}
ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
"request version: %.*s, method: %.*s", request_version->len,
request_version->data, request_method->len, request_method->data);
if (request_version->len == conf->allow_version_value.len &&
0 == ngx_strncmp(conf->allow_version_value.data,
request_version->data, request_version->len) &&
request_method->len == conf->allow_method_value.len &&
0 == ngx_strncmp(conf->allow_method_value.data, request_method->data,
request_method->len))
{
return NGX_DECLINED;
}
return NGX_HTTP_FORBIDDEN;
}