【Nginx】如何处理HTTP配置

同一个配置项可以同时出现多个块内,例如HTTP块、server块、location块。一个配置项到底是取哪个块中的值完全有我们定义的模块决定。

处理HTTP配置项分以下4个步骤:

  1. 创建数据结构用于存储配置项对应的参数
  2. 设定配置项在配置文件中出现时的限制条件与回调方法
  3. 实现上述回调方法,或使用Nginx预设的14个回调方法
  4. 合并不同级别的同名配置项

1、分配用于保存配置参数的数据结构

创建一个结构体,用来保存感兴趣的参数。例如定义一个下面的结构体:

typedef struct
{
    ngx_str_t    my_str;
    ngx_int_t    my_num;
    ngx_flag_t   my_flag;
    size_t      my_size;
    ngx_array_t* my_str_array;
    ngx_array_t* my_keyval;
    off_t    my_off;
    ngx_msec_t   my_msec;
    time_t       my_sec;
    ngx_bufs_t   my_bufs;
    ngx_uint_t   my_enum_seq;
    ngx_uint_t  my_bitmask;
    ngx_uint_t   my_access;
    ngx_path_t* my_path;

    ngx_str_t    my_config_str;
    ngx_int_t    my_config_num;
} ngx_http_mytest_conf_t;

HTTP框架在解析配置文件nginx.conf时,只要遇到http{}、server{}、location{},就会分配一个保存参数的结构体。这些结构体由ngx_http_module_t接口中的回调方法生成:

typedef struct {
    ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);    // 解析配置文件前调用
    ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);   // 解析完配置文件后调用

    void       *(*create_main_conf)(ngx_conf_t *cf);    // 创建存储直属于http{}的配置项的结构体
    char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);  // 初始化main级别配置项

    void       *(*create_srv_conf)(ngx_conf_t *cf);     // 创建存储直属于srv{}的配置项的结构体
    char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);  // 合并main级别和srv级别的同名配置项

    void       *(*create_loc_conf)(ngx_conf_t *cf);     // 创建存储直属于loc{}的配置项的结构体
    char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);  // 合并srv级别和loc级别的同名配置项
} ngx_http_module_t;

具体过程如下:

  • 发现http{},调用create_main_conf、create_srv_conf、create_loc_conf
  • 发现server{},调用create_srv_conf、create_loc_conf
  • 发现location{},调用create_loc_conf

普通HTTP模块一般只实现create_loc_conf方法,用以匹配某个URL请求,定义方式如下:

static void* ngx_http_mytest_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_mytest_conf_t  *mycf;

    mycf = (ngx_http_mytest_conf_t  *)ngx_pcalloc(cf->pool, sizeof(ngx_http_mytest_conf_t));
    if (mycf == NULL)
        return NULL;

    mycf->my_flag = NGX_CONF_UNSET;
    mycf->my_num = NGX_CONF_UNSET;
    mycf->my_str_array = NGX_CONF_UNSET_PTR;
    mycf->my_keyval = NULL;
    mycf->my_off = NGX_CONF_UNSET;
    mycf->my_msec = NGX_CONF_UNSET_MSEC;
    mycf->my_sec = NGX_CONF_UNSET;
    mycf->my_size = NGX_CONF_UNSET_SIZE;

    return mycf;
}

2、设定配置项的解析方式

配置项的解析方式由ngx_command_t数组定义:

struct ngx_command_s {
    ngx_str_t             name;     // 配置项名称
    ngx_uint_t            type;     // 配置项类型,包括该配置项可以出现的位置和可以携带参数的个数

    // 出现name配置项后,调用此方法解析配置项参数
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;     // 配置文件中的偏移量,确定将该配置项放入哪个存储结构体中
    ngx_uint_t            offset;   // 将该配置项放在存储结构体的哪个字段
    void                 *post;      // 配置项读取后的处理方法
};

成员含义如下:

  • name:配置项名称
  • type:决定配置项可以在哪些块中出现
  • set:解析配置项的回调方法
  • conf:告诉HTTP框架该配置项参数放在哪个结构体中,取值如下:
    • NGX_HTTP_MAIN_CONF_OFFSET:用create_main_conf产生的结构体存储配置项参数
    • NGX_HTTP_SRV_CONF_OFFSET:用create_srv_conf产生的结构体存储配置项参数
    • NGX_HTTP_LOC_CONF_OFFSET:用create_loc_conf产生的结构体存储配置项参数
    • 一般情况下,HTTP模块实现create_loc_conf回调方法,然后把conf设置为NGX_HTTP_LOC_CONF_OFFSET
  • offset:表示当前配置项在整个存储配置项的结构体中的偏移位置,由宏offsetof(struct, member)计算偏移量。Nginx的预设解析方法需要通过conf成员确定存储配置项参数结构体,然后通过offset成员确定存储配置项参数的成员。但自定义解析方法把这一项设为0即可,因为如何存储是由我们定义的。
  • post:多用途指针,一般不使用

3、解析配置项的14种预设方法

以ngx_conf_set_flag_slot为例,它用于解析带有on或off参数的配置项,对应的ngx_command_s结构如下:

{
    ngx_string("test_flag"),
    NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
    ngx_conf_set_flag_slot,
    NGX_HTTP_LOC_CONF_OFFSET,
    offsetof(ngx_http_mytest_conf_t, my_flag),
    NULL
},

上述成员中,NGX_CONF_FLAG表示配置项只有一个参数,且只能是on或off。offsetof(ngx_http_mytest_conf_t, my_flag)表示将配置项test_flag后的参数存放在ngx_http_mytest_conf_t结构体的my_flag成员中。

其余13个预设方法类似。

4、自定义配置项处理方法

该方法的目的就是把感兴趣的配置项参数存入预先分配好的结构体中:

static char* ngx_conf_set_myconfig(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    /* 参数conf就是http框架传给我们的,在ngx_http_mytest_create_loc_conf
     * 回调方法中分配的结构体ngx_http_mytest_conf_t
     */
    ngx_http_mytest_conf_t  *mycf = conf;

    /* cf->args是1个ngx_array_t队列,它的成员都是ngx_str_t结构。
     * 我们用value指向ngx_array_t的elts内容,其中value[1]就是第1
     * 个参数,同理value[2]是第2个参数
     */
    ngx_str_t* value = cf->args->elts;

    //ngx_array_t的nelts表示参数的个数
    if (cf->args->nelts > 1)
        mycf->my_config_str = value[1];

    if (cf->args->nelts > 2)
    {
        mycf->my_config_num = ngx_atoi(value[2].data, value[2].len);     /* 字符串转整型 */

        //如果字符串转化整型失败,将报"invalid number"错误,nginx启动失败
        if (mycf->my_config_num == NGX_ERROR)
            return "invalid number";
    }

    return NGX_CONF_OK; //返回成功
}

当存在如下ngx_command_s时:

{
    ngx_string("test_myconfig"),
    NGX_HTTP_LOC_CONF | NGX_CONF_TAKE12,
    ngx_conf_set_myconfig,
    NGX_HTTP_LOC_CONF_OFFSET,
    0,
    NULL
},

当在配置文件中出现test_myconfig配置项时,会调用我们自定义的ngx_conf_set_myconfig方法解析配置项,存储配置项参数。例如:

test_myconfig test 123

那么解析完之后:

mycf->my_config_str = test

mycf->my_config_num = 123

5、配置项合并

若ngx_http_module_t.merge_loc_conf为NULL,那么外层配置块http{]和server{}中同名配置项都不会生效。所以,如果需要合并同名配置项,则定义merge_loc_conf函数。merge_srv_conf函数原理相同。如何合并是自由的,例如merge_loc_conf可以如下定义:

static char * ngx_http_mytest_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    /* parent指向父配置块对应结构体,child指向子配置块对应结构体 */
    ngx_http_mytest_conf_t *prev = (ngx_http_mytest_conf_t *)parent;
    ngx_http_mytest_conf_t *conf = (ngx_http_mytest_conf_t *)child;

    /* conf = prev或"defaultstr" */
    ngx_conf_merge_str_value(conf->my_str, prev->my_str, "defaultstr");

    /* conf = prev或0 */
    ngx_conf_merge_value(conf->my_flag, prev->my_flag, 0);

    return NGX_CONF_OK;
}

有10种合并配置项的方法,ngx_conf_merge_str_value和ngx_conf_merge_value是其中的两个。

参考:

《深入理解Nginx》 P115-P140.

【Nginx】如何处理HTTP配置,布布扣,bubuko.com

时间: 2024-08-02 11:42:23

【Nginx】如何处理HTTP配置的相关文章

Nginx是如何配置为 Web 服务器的【转载】

详解 Nginx是如何配置为 Web 服务器的 林涛 发表于:2016-11-29 23:23 分类:WebServer 标签:Nginx,web,web服务器 521次 抽象来说,将 Nginx 配置为 Web 服务器就是定义 处理哪些 URLS 和 如何处理这些 URLS 对应的请求 .具体来说,就是定义一些虚拟服务器(Virtual Servers),控制具有特定 IP 和域名的请求. 更具体的来说, Nginx 通过定义一系列 location s 来控制对 URIS 的选择.每一个 l

Nginx如何处理一个请求

看了下nginx的官方文档,其中nginx如何处理一个请求讲解的很好,现在贴出来分享下.Nginx首先选定由哪一个虚拟主机来处理请求.让我们从一个简单的配置(其中全部3个虚拟主机都在端口*:80上监听)开始: 1 server { 2 listen 80; 3 server_name example.org www.example.org; 4 ... 5 } 6 7 server { 8 listen 80; 9 server_name example.net www.example.net;

centos LNMP第二部分nginx、php配置 第二十四节课

centos  LNMP第二部分nginx.php配置  第二十四节课 上半节课 下半节课 f

Nginx(九)-- Nginx实际使用配置

1.由于在nginx中需要配置很多东西,就会使得nginx.conf配置文件过于臃肿,所以我们会将配置文件合理的切分.大体的配置依然在nginx.conf中,其他的配置会放在etc下面的目录中. 2.etc文件中一般是放置配置文件的,所以 在 etc 中新建目录 mkdir -p /etc/nginx/conf.d cd /etc/nginx/conf.d 创建一个文件:vim virtual.conf  ,创建一个虚拟主机配置文件 3.将nginx.conf中 注释掉的配置 全部删除掉,并将

Nginx反代配置

一.ngx_http_proxy_module模块     ngx_http_proxy_module模块可根据用户请求的uri传递至后端服务器,实现反向代理 命令: 1.proxy_pass 设置一个代理服务器的地址,协议,和一个可选的URI的位置应该映射.作为一个协议,"HTTP"或"https"可以指定.地址可以被指定为一个域名或IP地址,和一个可选的端口 语法:proxy_pass URL; 可用的上下文:location, if in location,

nginx代理websocket配置

nginx正常只能代理http请求,如果想实现代理websocket的需求,需在请求中加入"Upgrade"字段,使请求从http升级为websocket. 配置如下: http {     map $http_upgrade $connection_upgrade {         default upgrade;         ''      close;     }       server {         ...           location /chat/ {

nginx tomcat https配置方案

nginx目录下配置: ssl目录下 添加 证书和密码,如图 /etc/nginx/conf.d  下修改配置文件 ## Basic reverse proxy server #### Apache backend for www.zjydjf.com ##upstream zjydjf { server 127.0.0.1:8080; #Apache} ## Start www.zjydjf.cn ##server { listen 80; server_name zjydjf.com www

Nginx return 关键字配置小技巧

Nginx的return关键字属于HttpRewriteModule模块: 语法:return http状态码 默认值:无 上下文:server,location,if 该指令将结束执行直接返回http状态码到客户端. 支持的http状态码:200, 204, 400, 402-406, 408, 410, 411, 413, 416 , 500-504,还有非标准的444状态码. 使用方法: #不符合规则的返回403禁止访问 location /download/ {     rewrite 

Nginx环境下配置PHP使用的SSL认证(https)

最近一段时间发现好多网站都从http协议变成了加密的https协议,比如说百度.吾志等等.https看起来比http高端了好多,而且在不同的浏览器向上还会显示出不同于http的URL展示效果(比如说chrome 和QQ浏览器 使用https协议的网址就会变色). 于是自己就想着把自己的网站加一个ssl证书,使之变成https://iwenku.net 最开始我使用的是腾讯云的服务器,服务器系统是Windows,使用Windows虽然坏处挺多,但是也有好处,那就是Windows是图形化界面的,这样