Nginx内部变量是nginx内部定义的变量,可以表示请求的一些属性,极大的方便了模块的开发和使用配置。
本文使用内部变量,实现一个请求协议检查模块,符合指定协议版本的请求才能访问nginx.
配置:
location /hello {
default_type text/html;
check_version $server_protocol HTTP/1.0;
content_by_lua_block {
ngx.say("HelloWorld")
}
}
测试:
如果是请求是HTTP 1.1协议,则请求通过
如果请求是HTTP 1.0协议,则请求被禁止,返回403
源码:
扫描二维码关注公众号,回复:
3026534 查看本文章
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;
} 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_command_t ngx_http_check_version_commands[] =
{
{
ngx_string("check_version"),
NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2,
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 =
{
NULL,
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 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 != 3)
{
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];
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;
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;
}
ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0,
"request version: %.*s", request_version->len,
request_version->data);
if (request_version->len == conf->allow_version_value.len &&
0 == ngx_strncmp(conf->allow_version_value.data,
request_version->data, request_version->len))
{
return NGX_DECLINED;
}
return NGX_HTTP_FORBIDDEN;