nginx配置项解析详解及代码实现
0回顾
在上一节,用nginx简单实现了一个hello world程序:当我们在浏览器中输入lochost/hello ,浏览器就返回:hello world。为什么会这样呢,简单一点说就是当我们请求访问hello这个服务,nginx就会看配置文件中是否有,如果有,根据具体的handler处理后把处理的结果返回给用户,没有就返回not found。
location /hello {
test_hello ;//无参数的配置
这其实是一个简单的配置。这节我们来看一个复杂的配置文件解析:
location /myconfig {
mystring smile_to_life;
mycounter 24;
myflag on;
mygrage better;
mybufs 2 4k;
}
这个配置几乎覆盖了nginx的基本类型,还有9种类型和这几种类型很相同,后面我们在详细讲。
先看一下存储配置参数的结构体:
typedef struct{
ngx_str_t arg_str;
ngx_int_t arg_counter;
ngx_flag_t arg_flag;
ngx_uint_t arg_enum_seq;
ngx_bufs_t arg_bufs;
}ngx_http_myconfig_loc_conf_t;
我们想实现的结果是:当我们在浏览器中输入myconfig时:浏览器输出:
mystring = smile_to_life, my_counter = 24, myflag = on, mygrage = better, buf.num = 2, buf.size = 4096;
1模块的基本结构
首先让我们看上一节出现的三个基本的数据结构。
1.1 模块配置指令 nginx_command_t
ngx_command_t的定义,位于src/core/ngx_conf_file.h中。
定义:
struct ngx_command_s {
ngx_str_t name;
ngx_uint_t type;
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
ngx_uint_t conf;
ngx_uint_t offset;
void *post;
};
name: 配置指令的名称。
type: 该配置的类型,其实更准确一点说,是该配置指令属性的集合。nginx提供了很多预定义的属性值(一些宏定义),通过逻辑或运算符可组合在一起,形成对这个配置指令的详细的说明。下面列出可在这里使用的预定义属性值及说明。
NGX_CONF_NOARGS:配置指令不接受任何参数。
NGX_CONF_TAKE1:配置指令接受1个参数。
NGX_CONF_TAKE2:配置指令接受2个参数。
NGX_CONF_TAKE3:配置指令接受3个参数。
NGX_CONF_TAKE4:配置指令接受4个参数。
NGX_CONF_TAKE5:配置指令接受5个参数。
NGX_CONF_TAKE6:配置指令接受6个参数。
NGX_CONF_TAKE7:配置指令接受7个参数。
可以组合多个属性,比如一个指令即可以不填参数,也可以接受1个或者2个参数。那么就是NGX_CONF_NOARGS|NGX_CONF_TAKE1|NGX_CONF_TAKE2。如果写上面三个属性在一起,你觉得麻烦,那么没有关系,nginx提供了一些定义,使用起来更简洁。
NGX_CONF_TAKE12:配置指令接受1个或者2个参数。
NGX_CONF_TAKE13:配置指令接受1个或者3个参数。
NGX_CONF_TAKE23:配置指令接受2个或者3个参数。
NGX_CONF_TAKE123:配置指令接受1个或者2个或者3参数。
NGX_CONF_TAKE1234:配置指令接受1个或者2个或者3个或者4个参数。
NGX_CONF_1MORE:配置指令接受至少一个参数。
NGX_CONF_2MORE:配置指令接受至少两个参数。
NGX_CONF_MULTI: 配置指令可以接受多个参数,即个数不定。
NGX_CONF_BLOCK:配置指令可以接受的值是一个配置信息块。也就是一对大括号括起来的内容。里面可以再包括很多的配置指令。比如常见的server指令就是这个属性的。
NGX_CONF_FLAG:配置指令可以接受的值是”on”或者”off”,最终会被转成bool值。
NGX_CONF_ANY:配置指令可以接受的任意的参数值。一个或者多个,或者”on”或者”off”,或者是配置块。
最后要说明的是,无论如何,nginx的配置指令的参数个数不可以超过NGX_CONF_MAX_ARGS个。目前这个值被定义为8,也就是不能超过8个参数值。
下面介绍一组说明配置指令可以出现的位置的属性。
NGX_DIRECT_CONF:可以出现在配置文件中最外层。例如已经提供的配置指令daemon,master_process等。
NGX_MAIN_CONF: http、mail、events、error_log等。
NGX_ANY_CONF: 该配置指令可以出现在任意配置级别上。
对于我们编写的大多数模块而言,都是在处理http相关的事情,也就是所谓的都是NGX_HTTP_MODULE,对于这样类型的模块,其配置可能出现的位置也是分为直接出现在http里面,以及其他位置。
NGX_HTTP_MAIN_CONF: 可以直接出现在http配置指令里。
NGX_HTTP_SRV_CONF: 可以出现在http里面的server配置指令里。
NGX_HTTP_LOC_CONF: 可以出现在http server块里面的location配置指令里。
NGX_HTTP_UPS_CONF: 可以出现在http里面的upstream配置指令里。
NGX_HTTP_SIF_CONF: 可以出现在http里面的server配置指令里的if语句所在的block中。
NGX_HTTP_LMT_CONF: 可以出现在http里面的limit_except指令的block中。
NGX_HTTP_LIF_CONF: 可以出现在http server块里面的location配置指令里的if语句所在的block中。
set: 这是一个函数指针,当nginx在解析配置的时候,如果遇到这个配置指令,将会把读取到的值传递给这个函数进行分解处理。因为具体每个配置指令的值如何处理,只有定义这个配置指令的人是最清楚的。来看一下这个函数指针要求的函数原型。
char *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void*conf);
先看该函数的返回值,处理成功时,返回NGX_OK,否则返回NGX_CONF_ERROR或者是一个自定义的错误信息的字符串。
再看一下这个函数被调用的时候,传入的三个参数。
cf: 该参数里面保存从配置文件读取到的原始字符串以及相关的一些信息。特别注意的是这个参数的args字段是一个ngx_str_t类型的数组,该数组的首个元素是这个配置指令本身,第二个元素是指令的第一个参数,第三个元素是第二个参数,依次类推。
cmd: 这个配置指令对应的ngx_command_t结构。
conf: 就是定义的存储这个配置值的结构体,比如在上面展示的那个ngx_http_myconfig_loc_conf_t。当解析这个arg_str变量的时候,传入的conf就指向一个ngx_http_myconfig_loc_conf_t类型的变量。用户在处理的时候可以使用类型转换,转换成自己知道的类型,再进行字段的赋值。
为了更加方便的实现对配置指令参数的读取,nginx已经默认提供了对一些标准类型的参数进行读取的函数,可以直接赋值给set字段使用。下面来看一下这些已经实现的set类型函数。
ngx_conf_set_flag_slot:读取NGX_CONF_FLAG类型的参数。
ngx_conf_set_str_slot:读取字符串类型的参数。
ngx_conf_set_str_array_slot: 读取字符串数组类型的参数。
ngx_conf_set_keyval_slot:读取键值对类型的参数。
ngx_conf_set_num_slot: 读取整数类型(有符号整数ngx_int_t)的参数。
ngx_conf_set_size_slot:读取size_t类型的参数,也就是无符号数。
ngx_conf_set_off_slot: 读取off_t类型的参数。
ngx_conf_set_msec_slot: 读取毫秒值类型的参数。</