Nginx学习--http配置项解析

举报
费德勒 发表于 2017/03/17 14:35:11 2017/03/17
【摘要】 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,测试结果如下:

作者 | 王凯

转载请注明出处:华为云博客 https://portal.hwclouds.com/blogs

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。