Openresty学习(九):Nginx 基于内部变量的HTTP版本检查模块,openrestynginx


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

 

源码:

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;

 

相关内容

    暂无相关文章