Nginx学习之二-配置项解析及编程实现

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 在开发功能灵活的Nginx模块时,需要从配置文件中获取特定的信息。不过,我们并不需要再编写一套读取配置的系统,Nginx已经为用户提供了强大的配置项解析机制,同时还支持“-s reload”命令,可以在不重启服务的情况下可使配置生效。
在开发功能灵活的Nginx模块时,需要从配置文件中获取特定的信息。不过,我们并不需要再编写一套读取配置的系统,Nginx已经为用户提供了强大的配置项解析机制,同时还支持“-s reload”命令,可以在不重启服务的情况下可使配置生效。
 
一、Nginx配置文件简介
如果编译安装Nginx时使用默认路径,那么Nginx运行目录是/usr/local/nginx,其配置文件存放目录是/usr/local/nginx/conf/nginx.conf。其内容默认如下:
[cpp]  view plain copy print ?
 
  1. #user  nobody;  
  2. worker_processes  1;  
  3.   
  4. #error_log  logs/error.log;  
  5. #error_log  logs/error.log  notice;  
  6. #error_log  logs/error.log  info;  
  7.   
  8. #pid        logs/nginx.pid;  
  9.   
  10.   
  11. events {  
  12.     worker_connections  1024;  
  13. }  
  14.   
  15.   
  16. http {  
  17.     include       mime.types;  
  18.     default_type  application/octet-stream;  
  19.   
  20.     #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
  21.     #                  '$status $body_bytes_sent "$http_referer" '  
  22.     #                  '"$http_user_agent" "$http_x_forwarded_for"';  
  23.   
  24.     #access_log  logs/access.log  main;  
  25.   
  26.     sendfile        on;  
  27.     #tcp_nopush     on;  
  28.   
  29.     #keepalive_timeout  0;  
  30.     keepalive_timeout  65;  
  31.   
  32.     #gzip  on;  
  33.   
  34.     server {  
  35.         listen       80;  
  36.         server_name  localhost;  
  37.   
  38.         #charset koi8-r;  
  39.   
  40.         #access_log  logs/host.access.log  main;  
  41.   
  42.         location / {  
  43.             root   html;  
  44.             index  index.html index.htm;  
  45.         }  
  46.   
  47.         #error_page  404              /404.html;  
  48.   
  49.         # redirect server error pages to the static page /50x.html  
  50.         #  
  51.         error_page   500 502 503 504  /50x.html;  
  52.         location = /50x.html {  
  53.             root   html;  
  54.         }  
  55.   
  56.         # proxy the PHP scripts to Apache listening on 127.0.0.1:80  
  57.         #  
  58.         #location ~ \.php$ {  
  59.         #    proxy_pass   http://127.0.0.1;  
  60.         #}  
  61.   
  62.         # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000  
  63.         #  
  64.         #location ~ \.php$ {  
  65.         #    root           html;  
  66.         #    fastcgi_pass   127.0.0.1:9000;  
  67.         #    fastcgi_index  index.php;  
  68.         #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;  
  69.         #    include        fastcgi_params;  
  70.         #}  
  71.   
  72.         # deny access to .htaccess files, if Apache's document root  
  73.         # concurs with nginx's one  
  74.         #  
  75.         #location ~ /\.ht {  
  76.         #    deny  all;  
  77.         #}  
  78.     }  
  79.   
  80.   
  81.     # another virtual host using mix of IP-, name-, and port-based configuration  
  82.     #  
  83.     #server {  
  84.     #    listen       8000;  
  85.     #    listen       somename:8080;  
  86.     #    server_name  somename  alias  another.alias;  
  87.   
  88.     #    location / {  
  89.     #        root   html;  
  90.     #        index  index.html index.htm;  
  91.     #    }  
  92.     #}  
  93.   
  94.   
  95.     # HTTPS server  
  96.     #  
  97.     #server {  
  98.     #    listen       443;  
  99.     #    server_name  localhost;  
  100.   
  101.     #    ssl                  on;  
  102.     #    ssl_certificate      cert.pem;  
  103.     #    ssl_certificate_key  cert.key;  
  104.   
  105.     #    ssl_session_timeout  5m;  
  106.   
  107.     #    ssl_protocols  SSLv2 SSLv3 TLSv1;  
  108.     #    ssl_ciphers  HIGH:!aNULL:!MD5;  
  109.     #    ssl_prefer_server_ciphers   on;  
  110.   
  111.     #    location / {  
  112.     #        root   html;  
  113.     #        index  index.html index.htm;  
  114.     #    }  
  115.     #}  
  116.   
  117. }  

块配置项
配置文件中有很多块配置项。块配置项是由一个块配置项名和一对大括号组成。例如上面代码段中的http、server、event等等。也可以在块配置项名之后后大括号之前加上参数。
块配置项可以嵌套。内层块直接继承外层块。例如上例中server块里的任意配置都是基于http块里的已有配置的。当内外层中的配置发生冲突时,究竟是以内层块还是外层块的配置为准取决于解析这个配置项的模块。
 
配置项的语法
最基本的配置项语法格式:
配置项名 配置项值1 配置项值2 配置项值3 ... ;
行首是配置项名,这些配置项名必须是Nginx的某一个模块想要处理的,否则Nginx会认为配置文件出现了非法的配置项名。配置项名输入结束后以空格作为分隔符。
其次是配置项值,可以是数字或字符串。可以由一个或多个配置项值。中间以空格分隔。
最后,行尾是分号。
 
以“#”开始的是注释行。
 
二、怎样使用http配置
处理http配置项可以分为以下四个步骤:
(1)创建数据结构用于存储配置项对应的参数。
(2)设定配置项在nginx.conf中出现时的限制条件与回调方法。
(3)实现第二步中的回调方法,或者使用Nginx框架预设的14个回调方法。
(4)合并不同级别的配置块中出现的同名配置项。
 
在这里不得不提到的是两个非常重要的数据结构:ngx_http_module_t以及ngx_command_t,是HTTP模块时不可或缺的部分,它们把这四个步骤与Nginx有机地结合起来。
 
在本例中我们通过在配置文件中添加如下项来自己编写模块进行解析(添加到默认server块内):
[cpp]  view plain copy print ?
 
  1. #测试配置项2  
  2. location /test2 {  
  3.    test_str "hello my dear HUST!";  
  4.    test_flag on;  
  5.    test_num 10;  
  6.    test_size 1000;  
  7.    mytest;  
  8. }  
要实现的效果是,当在浏览器中输入 http://localhost/test2时,将所有包含参数的配置项名及其对应的参数输出。
 
分配用于保存配置参数的数据结构
这个数据结构依据需要保存的参数自定义即可。
一般情况下这个结构是(包含了各种类型的配置项,但是在本例中只实现了部分类型的配置项的解析):
 
[cpp]  view plain copy print ?
 
  1. //存储配置项参数的结构体  
  2. typedef struct{  
  3.         ngx_str_t arg_str;//保存一个字符串类型的参数  
  4.         ngx_int_t arg_num;  
  5.         ngx_flag_t arg_flag;  
  6.         size_t arg_size;  
  7.         ngx_array_t* arg_str_array;  
  8.         ngx_array_t* arg_keyval;  
  9.         off_t arg_off;  
  10.         ngx_msec_t arg_msec;  
  11.         time_t arg_sec;  
  12.         ngx_bufs_t arg_bufs;  
  13.         ngx_uint_t arg_enum_seq;  
  14.         ngx_uint_t arg_bitmask;  
  15.         ngx_uint_t arg_access;  
  16.         ngx_path_t* arg_path;  
  17. }ngx_http_mytest2_loc_conf_t;  
需要注意的是,这个结构会Nginx的内存中保存许多份。http框架在解析nginx.conf文件时,只要遇到http{}、server{}、或者location{}配置块就会立刻分配一个新的结构体。
 
Nginx如何管理我们自定义的存储配置的结构体呢?
是通过ngx_http_module_t中的8个回调方法(ngx_http_config.h):
[cpp]  view plain copy print ?
 
  1. 24 typedef struct {  
  2. 25     ngx_int_t   (*preconfiguration)(ngx_conf_t *cf);  
  3. 26     ngx_int_t   (*postconfiguration)(ngx_conf_t *cf);  
  4. 27   
  5. 28     void       *(*create_main_conf)(ngx_conf_t *cf);  
  6. 29     char       *(*init_main_conf)(ngx_conf_t *cf, void *conf);  
  7. 30   
  8. 31     void       *(*create_srv_conf)(ngx_conf_t *cf);  
  9. 32     char       *(*merge_srv_conf)(ngx_conf_t *cf, void *prev, void *conf);  
  10. 33   
  11. 34     void       *(*create_loc_conf)(ngx_conf_t *cf);  
  12. 35     char       *(*merge_loc_conf)(ngx_conf_t *cf, void *prev, void *conf);  
  13. 36 } ngx_http_module_t;  

其中以create开头的三个回调方法负责把我们分配的用于保存配置项的结构体传递给http框架。为什么会定义三个回调方法呢?
http框架定义了三个级别的配置main、srv、loc,分别表示直接出现在http{}、server{}、location{}、块内的配置。当nginx.conf中出现http{}时,http框架会接管配置文件中http{}块内的配置项解析。当遇到http{}配置块时,http框架会调用所有的http模块可能实现的create_main_conf、create_srv_conf、create_loc_conf方法生成存储main级别的配置参数的结构体;在遇到server{}配置块时,会再次调用所有的http模块可能实现的create_srv_conf、create_loc_conf方法生成存储srv级别的配置参数的结构体;在遇到location{}配置块时,会再次调用所有的http模块可能实现的create_loc_conf方法生成存储loc级别的配置参数的结构体。实现三个回调方法的意义是不同的。在一个模块中,http块内只会调用一次create_main_conf,但是create_loc_conf可能会被调用很多次,也就是有许多由create_loc_conf生成的结构体。
 
普通http请求往往只实现create_loc_conf回调方法,因为它们只关注匹配某种URL的请求。
 
设定配置项的解析方式
我们在ngx_command_t结构体中设定配置项的解析方式:
[cpp]  view plain copy print ?
 
  1. 78 struct ngx_command_s {  
  2. 79     ngx_str_t             name;//配置项名称  
  3. 80     ngx_uint_t            type;//决定这个配置项可以在哪些块中出现以及可以携带的参数类型和个数  
  4. 81     char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);//回调方法,可以自己实现也可以使用预设的14个方法  
  5. 82     ngx_uint_t            conf;//配置项所处内存的相对偏移量  
  6. 83     ngx_uint_t            offset;//当前配置项在整个存储配置项的结构体中的偏移位置  
  7. 84     void                 *post;//配置项的回调方法  
  8. 85 };  


在本例中,前四个配置项都用预设的方法进行解析,而最后一个配置项mytest用自定义的方法,并在这个方法中将前面各个配置项的参数组合成一个字符串返回给客户。
 
我们需要通过定义ngx_command_t数组来设置配置项的解析方式:
[cpp]  view plain copy print ?
 
  1. //设置配置项的解析方式  
  2. static ngx_command_t ngx_http_mytest2_commands[] = {  
  3.         {  
  4.                 //test_str配置项  
  5.                 ngx_string("test_str"),  
  6.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  7.         ngx_conf_set_str_slot,//预设的配置项解析方法  
  8.                 NGX_HTTP_LOC_CONF_OFFSET,  
  9.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_str),  
  10.                 NULL  
  11.         },  
  12.         {  
  13.                 //test_flag配置项  
  14.                 ngx_string("test_flag"),  
  15.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  16.                 ngx_conf_set_flag_slot,//预设的配置项解析方法  
  17.         NGX_HTTP_LOC_CONF_OFFSET,  
  18.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_flag),  
  19.                 NULL  
  20.         },  
  21.         {  
  22.                 //test_num配置项  
  23.                 ngx_string("test_num"),  
  24.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  25.                 ngx_conf_set_num_slot,//预设的配置项解析方法  
  26.         NGX_HTTP_LOC_CONF_OFFSET,  
  27.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_num),  
  28.                 NULL  
  29.         },  
  30.         {  
  31.                 //test_size配置项  
  32.                 ngx_string("test_size"),  
  33.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  34.                 ngx_conf_set_size_slot,//预设的配置项解析方法  
  35.         NGX_HTTP_LOC_CONF_OFFSET,  
  36.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_size),  
  37.                 NULL  
  38.         },  
  39.         {  
  40.                 //mytest配置项  
  41.                 ngx_string("mytest"),  
  42.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,  
  43.         ngx_http_mytest2,  
  44.                 NGX_HTTP_LOC_CONF_OFFSET,  
  45.                 0,  
  46.                 NULL  
  47.         },  
  48.     ngx_null_command  
  49. };  

其中自定义的配置项解析方法ngx_http_mytest2:
[cpp]  view plain copy print ?
 
  1. //模块的回调方法  
  2. static char *   
  3. ngx_http_mytest2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
  4. {  
  5.     ngx_http_core_loc_conf_t *clcf;  
  6.   
  7.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);  
  8.     clcf->handler = ngx_http_mytest2_handler;//每当遇到配置项mytest的时候会回调这个方法  
  9.   
  10.     return NGX_CONF_OK;  
  11. }  
真正完成处理工作的handler是 ngx_http_mytest2_handler:
[cpp]  view plain copy print ?
 
  1. //模块真正完成处理工作的handler  
  2. static ngx_int_t ngx_http_mytest2_handler(ngx_http_request_t *r)  
  3. {  
  4.         ngx_http_mytest2_loc_conf_t *elcf;//存储配置项参数的结构体  
  5.         elcf = ngx_http_get_module_loc_conf(r,ngx_http_mytest2_module);  
  6.   
  7.     if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD | NGX_HTTP_POST))) {  
  8.         return NGX_HTTP_NOT_ALLOWED;  
  9.     }  
  10.   
  11.     ngx_int_t rc = ngx_http_discard_request_body(r);  
  12.     if (rc != NGX_OK) {  
  13.         return rc;  
  14.     }  
  15.   
  16.     ngx_str_t type = ngx_string("text/plain");  
  17.         ngx_str_t str_format = ngx_string("test_str=%V,test_flag=%i,test_num=%i,test_size=%z");  
  18.         ngx_str_t test_str = elcf->arg_str;  
  19.         ngx_flag_t test_flag = elcf->arg_flag;  
  20.         ngx_int_t test_num = elcf->arg_num;  
  21.         size_t test_size = elcf->arg_size;  
  22.         int data_len = str_format.len + test_str.len + 1;  
  23.     r->headers_out.status = NGX_HTTP_OK;  
  24.     r->headers_out.content_length_n = data_len;//响应包包体内容长度  
  25.     r->headers_out.content_type = type;  
  26.   
  27.     rc = ngx_http_send_header(r);  
  28.     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {  
  29.         return rc;  
  30.     }  
  31.   
  32.     ngx_buf_t *b;  
  33.     b = ngx_create_temp_buf(r->pool,data_len);  
  34.         if (b == NULL) {  
  35.         return NGX_HTTP_INTERNAL_SERVER_ERROR;  
  36.     }  
  37.   
  38.         ngx_snprintf(b->pos,data_len,(char *)str_format.data,&test_str,test_flag,test_num,test_size);  
  39.         b->last = b->pos + data_len;  
  40.     b->last_buf = 1;  
  41.   
  42.     ngx_chain_t out;  
  43.     out.buf = b;  
  44.     out.next = NULL;  
  45.   
  46.     return ngx_http_output_filter(r, &out);  
  47. }  

三、新添加模块的编译
普通编译方式是:
[cpp]  view plain copy print ?
 
  1. ./configure --prefix=/usr/local/nginx --add-module=XX(新模块的config文件以及源码所存放的目录)  
  2. make  
  3. sudo make install  
但是这样的一个缺点是:每次都要编译所有的nginx源码,速度慢。如果自己编写的新模块中的源代码中有错误,调试起来很不方便。有一个方法是自己编写一个makefile文件,先单独编译新模块的代码,修正所有错误之后再将其编译进Nginx。
这是我编写的MakeFile文件:
[cpp]  view plain copy print ?
 
  1. #编译新模块的makefile文件  
  2.   
  3. ngx_http_mytest_module.o: ngx_http_mytest_module.c  
  4.     gcc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g   -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/core -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/event -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/event/modules -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/os/unix -I /home/xiajun/TEST/Nginx/nginx-1.4.1/objs -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/http -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/http/modules -I /home/xiajun/TEST/Nginx/nginx-1.4.1/src/mail -o ngx_http_mytest_module.o /home/xiajun/TEST/Nginx/nginx-1.4.1/mytest/ngx_http_mytest_module.c  

四、完整代码及结果演示
config文件:
ngx_addon_name=ngx_http_mytest2  
HTTP_MODULES="$HTTP_MODULES ngx_http_mytest2_module"  
NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_mytest2_module.c"
 
ngx_http_mytest2_module.c:
[cpp]  view plain copy print ?
 
  1. //Nginx自定义模块实现代码  
  2. //E-Mail:xiajunhust@gmail.com(江南烟雨)  
  3.   
  4. #include <ngx_config.h>  
  5. #include <ngx_core.h>  
  6. #include <ngx_http.h>  
  7.   
  8. static ngx_int_t   
  9. ngx_http_mytest2_handler(ngx_http_request_t *r);  
  10.   
  11. static char *   
  12. ngx_http_mytest2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);  
  13.   
  14. static void*  
  15. ngx_http_mytest2_create_loc_conf(ngx_conf_t *cf);  
  16.   
  17. static char*  
  18. ngx_http_mytest2_merge_loc_conf(ngx_conf_t *cf,void *parent,void *child);  
  19.   
  20. //存储配置项参数的结构体  
  21. typedef struct{  
  22.         ngx_str_t arg_str;//保存一个字符串类型的参数  
  23.         ngx_int_t arg_num;  
  24.         ngx_flag_t arg_flag;  
  25.         size_t arg_size;  
  26.         ngx_array_t* arg_str_array;  
  27.         ngx_array_t* arg_keyval;  
  28.         off_t arg_off;  
  29.         ngx_msec_t arg_msec;  
  30.         time_t arg_sec;  
  31.         ngx_bufs_t arg_bufs;  
  32.         ngx_uint_t arg_enum_seq;  
  33.         ngx_uint_t arg_bitmask;  
  34.         ngx_uint_t arg_access;  
  35.         ngx_path_t* arg_path;  
  36. }ngx_http_mytest2_loc_conf_t;  
  37.   
  38. //设置配置项的解析方式  
  39. static ngx_command_t ngx_http_mytest2_commands[] = {  
  40.         {  
  41.                 //test_str配置项  
  42.                 ngx_string("test_str"),  
  43.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  44.         ngx_conf_set_str_slot,//预设的配置项解析方法  
  45.                 NGX_HTTP_LOC_CONF_OFFSET,  
  46.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_str),  
  47.                 NULL  
  48.         },  
  49.         {  
  50.                 //test_flag配置项  
  51.                 ngx_string("test_flag"),  
  52.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  53.                 ngx_conf_set_flag_slot,//预设的配置项解析方法  
  54.         NGX_HTTP_LOC_CONF_OFFSET,  
  55.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_flag),  
  56.                 NULL  
  57.         },  
  58.         {  
  59.                 //test_num配置项  
  60.                 ngx_string("test_num"),  
  61.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  62.                 ngx_conf_set_num_slot,//预设的配置项解析方法  
  63.         NGX_HTTP_LOC_CONF_OFFSET,  
  64.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_num),  
  65.                 NULL  
  66.         },  
  67.         {  
  68.                 //test_size配置项  
  69.                 ngx_string("test_size"),  
  70.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_TAKE1,  
  71.                 ngx_conf_set_size_slot,//预设的配置项解析方法  
  72.         NGX_HTTP_LOC_CONF_OFFSET,  
  73.                 offsetof(ngx_http_mytest2_loc_conf_t,arg_size),  
  74.                 NULL  
  75.         },  
  76.         {  
  77.                 //mytest配置项  
  78.                 ngx_string("mytest"),  
  79.         NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF|NGX_CONF_NOARGS,  
  80.         ngx_http_mytest2,  
  81.                 NGX_HTTP_LOC_CONF_OFFSET,  
  82.                 0,  
  83.                 NULL  
  84.         },  
  85.     ngx_null_command  
  86. };  
  87.   
  88. //模块上下文定义  
  89. static ngx_http_module_t ngx_http_mytest2_module_ctx = {  
  90.     NULL,  
  91.     NULL,  
  92.     NULL,  
  93.     NULL,  
  94.     NULL,  
  95.     NULL,  
  96.     ngx_http_mytest2_create_loc_conf,//创建数据结构存储loc级别的配置项的回调方法  
  97.     ngx_http_mytest2_merge_loc_conf//合并loc级别的配置项  
  98. };  
  99.   
  100. //模块定义  
  101. ngx_module_t ngx_http_mytest2_module = {  
  102.     NGX_MODULE_V1,  
  103.     &ngx_http_mytest2_module_ctx,  
  104.     ngx_http_mytest2_commands,  
  105.     NGX_HTTP_MODULE,  
  106.     NULL,  
  107.     NULL,  
  108.     NULL,  
  109.     NULL,  
  110.     NULL,  
  111.     NULL,  
  112.         NULL,  
  113.     NGX_MODULE_V1_PADDING  
  114. };  
  115.   
  116. //模块的回调方法  
  117. static char *   
  118. ngx_http_mytest2(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)  
  119. {  
  120.     ngx_http_core_loc_conf_t *clcf;  
  121.   
  122.     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);  
  123.     clcf->handler = ngx_http_mytest2_handler;  
  124.         //ngx_conf_set_str_slot(cf,cmd,conf);//预设的配置项处理方法  
  125.   
  126.     return NGX_CONF_OK;  
  127. }  
  128.   
  129. //模块真正完成处理工作的handler  
  130. static ngx_int_t ngx_http_mytest2_handler(ngx_http_request_t *r)  
  131. {  
  132.         ngx_http_mytest2_loc_conf_t *elcf;//存储配置项参数的结构体  
  133.         elcf = ngx_http_get_module_loc_conf(r,ngx_http_mytest2_module);  
  134.   
  135.     if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD | NGX_HTTP_POST))) {  
  136.         return NGX_HTTP_NOT_ALLOWED;  
  137.     }  
  138.   
  139.     ngx_int_t rc = ngx_http_discard_request_body(r);  
  140.     if (rc != NGX_OK) {  
  141.         return rc;  
  142.     }  
  143.   
  144.     ngx_str_t type = ngx_string("text/plain");  
  145.         ngx_str_t str_format = ngx_string("test_str=%V,test_flag=%i,test_num=%i,test_size=%z");  
  146.         ngx_str_t test_str = elcf->arg_str;  
  147.         ngx_flag_t test_flag = elcf->arg_flag;  
  148.         ngx_int_t test_num = elcf->arg_num;  
  149.         size_t test_size = elcf->arg_size;  
  150.         int data_len = str_format.len + test_str.len + 1;  
  151.     r->headers_out.status = NGX_HTTP_OK;  
  152.     r->headers_out.content_length_n = data_len;//响应包包体内容长度  
  153.     r->headers_out.content_type = type;  
  154.   
  155.     rc = ngx_http_send_header(r);  
  156.     if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {  
  157.         return rc;  
  158.     }  
  159.   
  160.     ngx_buf_t *b;  
  161.     b = ngx_create_temp_buf(r->pool,data_len);  
  162.         if (b == NULL) {  
  163.         return NGX_HTTP_INTERNAL_SERVER_ERROR;  
  164.     }  
  165.   
  166.         ngx_snprintf(b->pos,data_len,(char *)str_format.data,&test_str,test_flag,test_num,test_size);  
  167.         b->last = b->pos + data_len;  
  168.     b->last_buf = 1;  
  169.   
  170.     ngx_chain_t out;  
  171.     out.buf = b;  
  172.     out.next = NULL;  
  173.   
  174.     return ngx_http_output_filter(r, &out);  
  175. }  
  176.   
  177. static void*  
  178. ngx_http_mytest2_create_loc_conf(ngx_conf_t *cf){  
  179.         ngx_http_mytest2_loc_conf_t *conf;  
  180.         conf = ngx_pcalloc(cf->pool,sizeof(ngx_http_mytest2_loc_conf_t));  
  181.         if(NULL == conf){  
  182.                 return NGX_CONF_ERROR;  
  183.         }  
  184.         conf->arg_str.len = 0;  
  185.         conf->arg_str.data = NULL;  
  186.   
  187.         //注意一下设定必不可少,否则会出错  
  188.         conf->arg_flag = NGX_CONF_UNSET;  
  189.         conf->arg_num = NGX_CONF_UNSET;  
  190.         conf->arg_str_array = NGX_CONF_UNSET_PTR;  
  191.         conf->arg_keyval = NULL;  
  192.         conf->arg_off = NGX_CONF_UNSET;  
  193.         conf->arg_msec = NGX_CONF_UNSET_MSEC;  
  194.         conf->arg_sec = NGX_CONF_UNSET;  
  195.         conf->arg_size = NGX_CONF_UNSET_SIZE;  
  196.   
  197.         return conf;  
  198. }  
  199.   
  200.   
  201. static char*  
  202. ngx_http_mytest2_merge_loc_conf(ngx_conf_t *cf,void *parent,void *child){  
  203.         ngx_http_mytest2_loc_conf_t *prev = parent;  
  204.         ngx_http_mytest2_loc_conf_t *conf = child;  
  205.         ngx_conf_merge_str_value(conf->arg_str,prev->arg_str,"");  
  206.   
  207.         return NGX_CONF_OK;  
  208. }  

结果演示:



五、参考资料:
from:http://blog.csdn.net/xiajun07061225/article/details/9147265
目录
相关文章
|
4月前
|
XML 监控 网络协议
云深处绝影四足机器人协议学习解析
本文详细介绍并解析了云深处绝影X20四足机器人的通信协议,包括TCP服务端端口号、基于Service的请求/响应通信机制、通信帧结构、消息类型、常见的通信示例如获取状态和导航请求,以及运动控制的参数和命令。文中还提出了对协议中某些未明确说明或可能存在的问题的疑惑。
48 0
云深处绝影四足机器人协议学习解析
|
2月前
|
缓存 负载均衡 应用服务中间件
Nginx 学习
【10月更文挑战第17天】Nginx 是一款非常强大的工具,掌握它的使用和配置对于构建高性能、可靠的 Web 应用至关重要。随着技术的不断发展,Nginx 也在不断更新和完善,为我们提供更好的服务和支持。
|
2月前
|
负载均衡 应用服务中间件 Linux
nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全
这篇博客文章详细介绍了Nginx的下载、安装、配置以及使用,包括正向代理、反向代理、负载均衡、动静分离等高级功能,并通过具体实例讲解了如何进行配置。
165 4
nginx学习,看这一篇就够了:下载、安装。使用:正向代理、反向代理、负载均衡。常用命令和配置文件,很全
|
2月前
|
Kubernetes 应用服务中间件 nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
|
2月前
|
Kubernetes 监控 测试技术
k8s学习--基于Ingress-nginx实现灰度发布系统
k8s学习--基于Ingress-nginx实现灰度发布系统
113 2
k8s学习--基于Ingress-nginx实现灰度发布系统
|
2月前
|
缓存 负载均衡 算法
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
Nginx 是一款高性能的 HTTP 和反向代理服务器,也是一个通用的 TCP/UDP 代理服务器,以及一个邮件代理服务器和通用的 HTTP 缓存服务器。
78 0
nginx学习:配置文件详解,负载均衡三种算法学习,上接nginx实操篇
|
2月前
|
Kubernetes 负载均衡 应用服务中间件
k8s学习--ingress详细解释与应用(nginx ingress controller))
k8s学习--ingress详细解释与应用(nginx ingress controller))
223 0
|
2月前
|
应用服务中间件 测试技术 nginx
Nginx入门 -- 解析Nginx中的基本概念:Keepalive
Nginx入门 -- 解析Nginx中的基本概念:Keepalive
112 0
|
3月前
|
开发框架 安全 应用服务中间件
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
【文件上传绕过】——解析漏洞_IIS7.0 | IIS7.5 | Nginx的解析漏洞
154 9
|
4月前
|
人工智能 算法
AI 0基础学习,数学名词解析
AI 0基础学习,数学名词解析
26 2