Nginx学习--http配置项解析
【摘要】 Nginx学习--http配置项解析方法。
编写ngx_http_mytest_module.c,实现如下代码:
-c代码
001 #include
002 #include
003 #include
004
005 //create a structure
006 typedef struct{
007 ngx_str_t my_str;
008 ngx_int_t my_num;
009 ngx_flag_t my_flag;
010 size_t my_size;
011 ngx_array_t* my_str_array;
012 ngx_array_t* my_keyval;
013 off_t my_off;
014 ngx_msec_t my_msec;
015 time_t my_sec;
016 ngx_bufs_t my_bufs;
017 ngx_uint_t my_enum_seq;
018 ngx_uint_t my_bitmask;
019 ngx_uint_t my_access;
020 ngx_path_t* my_path;
021 ngx_str_t my_config_str;
022 ngx_int_t my_config_num;
023 } ngx_http_mytest_conf_t;
024
025 static char* ngx_conf_set_myconfig(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
026 static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t* r);
027
028 static void* ngx_http_mytest_create_loc_conf(ngx_conf_t* cf);
029 static char* ngx_http_mytest_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child);
030
031 static ngx_conf_enum_t test_enums[] = {
032 {ngx_string("apple"), 1},
033 {ngx_string("banana"), 2},
034 {ngx_string("orange"), 3},
035 {ngx_null_string, 0}
036 };
037
038 static ngx_conf_bitmask_t test_bitmasks[] = {
039 {ngx_string("good"), 0x0002},
040 {ngx_string("better"), 0x0004},
041 {ngx_string("best"), 0x0008},
042 {ngx_null_string, 0}
043 };
044
045 //set the resolution of configuration items
046 static ngx_command_t ngx_http_mytest_commands[] = {
047 {
048 /*
049 1.test_flag配置只能出现在location{...}块中,
050 当test_flag的配置项参数为on时,ngx_http_mytest_conf_t结构体
051 中的my_flag会设置为1,如果为off时,会设置为0
052 */
053 ngx_string("test_flag"),
054 NGX_HTTP_LOC_CONF | NGX_CONF_FLAG,
055 ngx_conf_set_flag_slot,
056 NGX_HTTP_LOC_CONF_OFFSET,
057 offsetof(ngx_http_mytest_conf_t, my_flag),
058 NULL
059 },
060 {
061 /*
062 2.test_str可以出现在http{..}、server{...}或者location{...}块内,
063 它携带的一个参数会保存在my_str中。
064 */
065 ngx_string("test_str"),
066 NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
067 ngx_conf_set_str_slot,
068 NGX_HTTP_LOC_CONF_OFFSET,
069 offsetof(ngx_http_mytest_conf_t, my_str),
070 NULL
071 },
072 {
073 /*3.*/
074 ngx_string("test_str_array"),
075 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
076 ngx_conf_set_str_array_slot,
077 NGX_HTTP_LOC_CONF_OFFSET,
078 offsetof(ngx_http_mytest_conf_t, my_str_array),
079 NULL
080 },
081 {
082 /*4.*/
083 ngx_string("test_keyval"),
084 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2,
085 ngx_conf_set_keyval_slot,
086 NGX_HTTP_LOC_CONF_OFFSET,
087 offsetof(ngx_http_mytest_conf_t, my_keyval),
088 NULL
089 },
090 {
091 /*5.*/
092 ngx_string("test_num"),
093 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
094 ngx_conf_set_num_slot,
095 NGX_HTTP_LOC_CONF_OFFSET,
096 offsetof(ngx_http_mytest_conf_t, my_num),
097 NULL
098 },
099 {
100 /*
101 6.如果在nginx.conf中配置了test_size 10k;,那么my_szie将会设置成10240。
102 如果配置为test_size 10m;,则my_szie将会设置成10485760。
103 */
104 ngx_string("test_size"),
105 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
106 ngx_conf_set_size_slot,
107 NGX_HTTP_LOC_CONF_OFFSET,
108 offsetof(ngx_http_mytest_conf_t, my_size),
109 NULL
110 },
111 {
112 /*7.*/
113 ngx_string("test_off"),
114 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
115 ngx_conf_set_off_slot,
116 NGX_HTTP_LOC_CONF_OFFSET,
117 offsetof(ngx_http_mytest_conf_t, my_off),
118 NULL
119 },
120 {
121 /*
122 8.如果在nginx.conf中配置了test_msec 1d;,那么my_msec会设置为一天的毫秒数。
123 */
124 ngx_string("test_msec"),
125 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
126 ngx_conf_set_msec_slot,
127 NGX_HTTP_LOC_CONF_OFFSET,
128 offsetof(ngx_http_mytest_conf_t, my_msec),
129 NULL
130 },
131 {
132 /*
133 9.如果在nginx.conf中配置了test_sec 1d;,那么my_msec会设置为一天的秒数。
134 */
135 ngx_string("test_sec"),
136 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
137 ngx_conf_set_sec_slot,
138 NGX_HTTP_LOC_CONF_OFFSET,
139 offsetof(ngx_http_mytest_conf_t, my_sec),
140 NULL
141 },
142 {
143 /*10.*/
144 ngx_string("test_bufs"),
145 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE2,
146 ngx_conf_set_bufs_slot,
147 NGX_HTTP_LOC_CONF_OFFSET,
148 offsetof(ngx_http_mytest_conf_t, my_bufs),
149 NULL
150 },
151 {
152 /*11.*/
153 ngx_string("test_enum"),
154 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
155 ngx_conf_set_enum_slot,
156 NGX_HTTP_LOC_CONF_OFFSET,
157 offsetof(ngx_http_mytest_conf_t, my_enum_seq),
158 test_enums
159 },
160 {
161 /*12.*/
162 ngx_string("test_bitmask"),
163 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1,
164 ngx_conf_set_bitmask_slot,
165 NGX_HTTP_LOC_CONF_OFFSET,
166 offsetof(ngx_http_mytest_conf_t, my_bitmask),
167 test_bitmasks
168 },
169 {
170 /*13.NGX_CONF_TAKE123,表示配置项后可以携带1~3个参数*/
171 ngx_string("test_access"),
172 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE123,
173 ngx_conf_set_access_slot,
174 NGX_HTTP_LOC_CONF_OFFSET,
175 offsetof(ngx_http_mytest_conf_t, my_access),
176 NULL
177 },
178 {
179 /*14.NGX_CONF_TAKE1234,表示配置项后可以携带1~4个参数*/
180 ngx_string("test_path"),
181 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE1234,
182 ngx_conf_set_path_slot,
183 NGX_HTTP_LOC_CONF_OFFSET,
184 offsetof(ngx_http_mytest_conf_t, my_path),
185 NULL
186 },
187 {
188 /*15.*/
189 ngx_string("test_myconfig"),
190 NGX_HTTP_LOC_CONF | NGX_CONF_TAKE12,
191 ngx_conf_set_myconfig,
192 NGX_HTTP_LOC_CONF_OFFSET,
193 0,
194 NULL
195 },
196
197 ngx_null_command
198 };
199 static ngx_http_module_t ngx_http_mytest_module_ctx = {
200 NULL,
201 NULL,
202 NULL,
203 NULL,
204 NULL,
205 NULL,
206 ngx_http_mytest_create_loc_conf, //create location configuration
207 ngx_http_mytest_merge_loc_conf //merge the loc configurations
208 };
209
210 ngx_module_t ngx_http_mytest_module = {
211 NGX_MODULE_V1,
212 &ngx_http_mytest_module_ctx,
213 ngx_http_mytest_commands,
214 NGX_HTTP_MODULE,
215 NULL,
16 NULL,
217 NULL,
218 NULL,
219 NULL,
220 NULL,
221 NULL,
222 NGX_MODULE_V1_PADDING
223 };
224
225 static char* ngx_conf_set_myconfig(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
226 {
227 /*注意,参数conf就是HTTP框架传给用户的在ngx_http_mytest_create_loc_conf回调方法中
228 分配的结构体ngx_http_mytest_conf_t*/
229 ngx_http_mytest_conf_t* mycf = conf;
230
231 ngx_str_t* value = cf->args->elts;
232
233 //nelts表示参数的个数
234 if (cf->args->nelts > 1) {
235 mycf->my_config_str = value[1];
236 }
237
238 if (cf->args->nelts > 2) {
239 mycf->my_config_num = ngx_atoi(value[2].data, value[2].len);
240 if (NGX_ERROR == mycf->my_config_num) {
241 return "invalid number";
242 }
243 }
244
245 ngx_http_core_loc_conf_t* clcf;
246 clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
247 clcf->handler = ngx_http_mytest_handler;
248
249 return NGX_CONF_OK;
250 }
251
252 static ngx_int_t ngx_http_mytest_handler(ngx_http_request_t* r)
253 {
254 //必须是GET或者HEAD方法
255 if(!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD)))
256 {
257 return NGX_HTTP_NOT_ALLOWED;
258 }
259
260 //丢弃请求中的包体
261 ngx_int_t rc = ngx_http_discard_request_body(r);
262 if(rc != NGX_OK){
263 return rc;
264 }
265
266 ngx_http_mytest_conf_t* my_conf;
267 my_conf = ngx_http_get_module_loc_conf(r, ngx_http_mytest_module);
268
269 ngx_str_t type = ngx_string("text/plain");
270
271 u_char nginx_str_mytest[1024] = {0};
272 ngx_sprintf(nginx_str_mytest,"test_str=%s,\ntest_flag=%i,\ntest_num=%i,\n"
273 "my_config_str=%s, my_config_num=%i,\n"
274 "test_enum is %ui,\ntest_sec is %T\n",
275 my_conf->my_str.data,my_conf->my_flag,my_conf->my_num,
276 my_conf->my_config_str.data, my_conf->my_config_num,
277 my_conf->my_enum_seq, my_conf->my_sec);
278
279 ngx_str_t response = ngx_string(nginx_str_mytest);
280 response.len = ngx_strlen(nginx_str_mytest);
281
282 r->headers_out.status = NGX_HTTP_OK;
283 r->headers_out.content_length_n = response.len;
284 r->headers_out.content_type = type;
285
286 //发送http头部
287 rc = ngx_http_send_header(r);
288 if(rc == NGX_ERROR || rc>NGX_OK || r->header_only) {
289 return rc;
290 }
291
292 ngx_buf_t* b;
293 b = ngx_create_temp_buf(r->pool, response.len);
294 if(b == NULL){
295 return NGX_HTTP_INTERNAL_SERVER_ERROR;
296 }
297
298 ngx_memcpy(b->pos, response.data, response.len);
299 b->last = b->pos + response.len;
300 b->last_buf = 1;
301
302 ngx_chain_t out;
303 out.buf = b;
304 out.next = NULL;
305
306 return ngx_http_output_filter(r, &out);
307 }
308
309 static void* ngx_http_mytest_create_loc_conf(ngx_conf_t* cf)
310 {
311 ngx_http_mytest_conf_t* myconf;
312 myconf = (ngx_http_mytest_conf_t*)ngx_pcalloc(cf->pool, sizeof(ngx_http_mytest_conf_t));
313 if(NULL == myconf){
314 return NULL;
315 }
316
317 myconf->my_flag = NGX_CONF_UNSET;
318 myconf->my_num = NGX_CONF_UNSET;
319 myconf->my_str_array = NGX_CONF_UNSET_PTR;
320 myconf->my_keyval = NULL;
321 myconf->my_off = NGX_CONF_UNSET;
322 myconf->my_msec = NGX_CONF_UNSET_MSEC;
323 myconf->my_sec = NGX_CONF_UNSET;
324 myconf->my_size = NGX_CONF_UNSET_SIZE;
325 myconf->my_config_num = NGX_CONF_UNSET;
326 myconf->my_enum_seq = NGX_CONF_UNSET;
327 return myconf;
328 }
329
330 static char* ngx_http_mytest_merge_loc_conf(ngx_conf_t* cf, void* parent, void* child)
331 {
332 ngx_http_mytest_conf_t* prev = (ngx_http_mytest_conf_t*)parent;
333 ngx_http_mytest_conf_t* conf = (ngx_http_mytest_conf_t*)child;
334 ngx_conf_merge_str_value(conf->my_str, prev->my_str,"defaultstr");
335
336 return NGX_CONF_OK;
337 }
相对helloworld小程序,这个程序增加了一些配置项解析的代码处理。按照《Nginx模块开发与架构解析》,使用了Nginx中预定义的14种解析方法对配置项进行解析。另外,使用自定义配置项方法,解析了test_myconfig配置项。
在nginx.conf中增加了如下配置项:
location /url1 {
test_flag on;
test_num 1111111;
test_enum apple;
test_sec 1d;
test_myconfig "hello world!" 666;
test_str "---------";
}
location /url2 {
test_flag off;
test_num 12345;
test_enum banana;
test_sec 100s;
test_myconfig "Bye!" 888;
test_str "*********";
}
采用与helloworld小程序同样的部署方法,编译和启动nginx,测试结果如下:
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)