Openresty學習(十):Nginx內部變數的增加和使用
阿新 • • 發佈:2019-02-02
在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; }