upstream nginx-0.7.34
[nginx.git] / nginx / src / http / ngx_http_core_module.c
1
2 /*
3  * Copyright (C) Igor Sysoev
4  */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_http.h>
10
11
12 typedef struct {
13     u_char    *name;
14     uint32_t   method;
15 } ngx_http_method_name_t;
16
17
18 #define NGX_HTTP_REQUEST_BODY_FILE_OFF    0
19 #define NGX_HTTP_REQUEST_BODY_FILE_ON     1
20 #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN  2
21
22
23 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
24 static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
25     ngx_http_location_tree_node_t *node);
26
27 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
28 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
29 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
30 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
31 static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf,
32     void *parent, void *child);
33 static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf);
34 static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
35     void *parent, void *child);
36
37 static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
38     void *dummy);
39 static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd,
40     void *dummy);
41 static ngx_int_t ngx_http_core_regex_location(ngx_conf_t *cf,
42     ngx_http_core_loc_conf_t *clcf, ngx_str_t *regex, ngx_uint_t caseless);
43
44 static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd,
45     void *conf);
46 static char *ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy,
47     void *conf);
48
49 static char *ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
50     void *conf);
51 static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
52     void *conf);
53 static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
54 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
55     void *conf);
56 static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
57     void *conf);
58 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
59     void *conf);
60 static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd,
61     void *conf);
62 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
63     void *conf);
64 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
65     void *conf);
66 static char *ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
67     void *conf);
68 static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
69     void *conf);
70 static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
71     void *conf);
72 #if (NGX_HTTP_GZIP)
73 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
74     void *conf);
75 #endif
76
77 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
78 static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data);
79
80 static ngx_conf_post_t  ngx_http_core_lowat_post =
81     { ngx_http_core_lowat_check };
82
83 static ngx_conf_post_handler_pt  ngx_http_core_pool_size_p =
84     ngx_http_core_pool_size;
85
86 static ngx_conf_deprecated_t  ngx_conf_deprecated_optimize_server_names = {
87     ngx_conf_deprecated, "optimize_server_names", "server_name_in_redirect"
88 };
89
90 static ngx_conf_deprecated_t  ngx_conf_deprecated_open_file_cache_retest = {
91     ngx_conf_deprecated, "open_file_cache_retest", "open_file_cache_valid"
92 };
93
94 static ngx_conf_deprecated_t  ngx_conf_deprecated_satisfy_any = {
95     ngx_conf_deprecated, "satisfy_any", "satisfy"
96 };
97
98
99 static ngx_conf_enum_t  ngx_http_core_request_body_in_file[] = {
100     { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF },
101     { ngx_string("on"), NGX_HTTP_REQUEST_BODY_FILE_ON },
102     { ngx_string("clean"), NGX_HTTP_REQUEST_BODY_FILE_CLEAN },
103     { ngx_null_string, 0 }
104 };
105
106
107 static ngx_conf_enum_t  ngx_http_core_satisfy[] = {
108     { ngx_string("all"), NGX_HTTP_SATISFY_ALL },
109     { ngx_string("any"), NGX_HTTP_SATISFY_ANY },
110     { ngx_null_string, 0 }
111 };
112
113
114 static ngx_conf_enum_t  ngx_http_core_if_modified_since[] = {
115     { ngx_string("off"), NGX_HTTP_IMS_OFF },
116     { ngx_string("exact"), NGX_HTTP_IMS_EXACT },
117     { ngx_string("before"), NGX_HTTP_IMS_BEFORE },
118     { ngx_null_string, 0 }
119 };
120
121
122 #if (NGX_HTTP_GZIP)
123
124 static ngx_conf_enum_t  ngx_http_gzip_http_version[] = {
125     { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
126     { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
127     { ngx_null_string, 0 }
128 };
129
130
131 static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
132     { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
133     { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
134     { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
135     { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
136     { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
137     { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
138     { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
139     { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
140     { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
141     { ngx_null_string, 0 }
142 };
143
144
145 static ngx_str_t  ngx_http_gzip_no_cache = ngx_string("no-cache");
146 static ngx_str_t  ngx_http_gzip_no_store = ngx_string("no-store");
147 static ngx_str_t  ngx_http_gzip_private = ngx_string("private");
148
149 #endif
150
151
152 static ngx_command_t  ngx_http_core_commands[] = {
153
154     { ngx_string("variables_hash_max_size"),
155       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
156       ngx_conf_set_num_slot,
157       NGX_HTTP_MAIN_CONF_OFFSET,
158       offsetof(ngx_http_core_main_conf_t, variables_hash_max_size),
159       NULL },
160
161     { ngx_string("variables_hash_bucket_size"),
162       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
163       ngx_conf_set_num_slot,
164       NGX_HTTP_MAIN_CONF_OFFSET,
165       offsetof(ngx_http_core_main_conf_t, variables_hash_bucket_size),
166       NULL },
167
168     { ngx_string("server_names_hash_max_size"),
169       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
170       ngx_conf_set_num_slot,
171       NGX_HTTP_MAIN_CONF_OFFSET,
172       offsetof(ngx_http_core_main_conf_t, server_names_hash_max_size),
173       NULL },
174
175     { ngx_string("server_names_hash_bucket_size"),
176       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
177       ngx_conf_set_num_slot,
178       NGX_HTTP_MAIN_CONF_OFFSET,
179       offsetof(ngx_http_core_main_conf_t, server_names_hash_bucket_size),
180       NULL },
181
182     { ngx_string("server"),
183       NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_MULTI|NGX_CONF_NOARGS,
184       ngx_http_core_server,
185       0,
186       0,
187       NULL },
188
189     { ngx_string("connection_pool_size"),
190       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
191       ngx_conf_set_size_slot,
192       NGX_HTTP_SRV_CONF_OFFSET,
193       offsetof(ngx_http_core_srv_conf_t, connection_pool_size),
194       &ngx_http_core_pool_size_p },
195
196     { ngx_string("request_pool_size"),
197       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
198       ngx_conf_set_size_slot,
199       NGX_HTTP_SRV_CONF_OFFSET,
200       offsetof(ngx_http_core_srv_conf_t, request_pool_size),
201       &ngx_http_core_pool_size_p },
202
203     { ngx_string("client_header_timeout"),
204       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
205       ngx_conf_set_msec_slot,
206       NGX_HTTP_SRV_CONF_OFFSET,
207       offsetof(ngx_http_core_srv_conf_t, client_header_timeout),
208       NULL },
209
210     { ngx_string("client_header_buffer_size"),
211       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
212       ngx_conf_set_size_slot,
213       NGX_HTTP_SRV_CONF_OFFSET,
214       offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size),
215       NULL },
216
217     { ngx_string("large_client_header_buffers"),
218       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
219       ngx_conf_set_bufs_slot,
220       NGX_HTTP_SRV_CONF_OFFSET,
221       offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
222       NULL },
223
224     { ngx_string("optimize_server_names"),
225       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
226       ngx_conf_set_flag_slot,
227       NGX_HTTP_LOC_CONF_OFFSET,
228       offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
229       &ngx_conf_deprecated_optimize_server_names },
230
231     { ngx_string("ignore_invalid_headers"),
232       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
233       ngx_conf_set_flag_slot,
234       NGX_HTTP_SRV_CONF_OFFSET,
235       offsetof(ngx_http_core_srv_conf_t, ignore_invalid_headers),
236       NULL },
237
238     { ngx_string("merge_slashes"),
239       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
240       ngx_conf_set_flag_slot,
241       NGX_HTTP_SRV_CONF_OFFSET,
242       offsetof(ngx_http_core_srv_conf_t, merge_slashes),
243       NULL },
244
245     { ngx_string("underscores_in_headers"),
246       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
247       ngx_conf_set_flag_slot,
248       NGX_HTTP_SRV_CONF_OFFSET,
249       offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
250       NULL },
251
252     { ngx_string("location"),
253       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
254       ngx_http_core_location,
255       NGX_HTTP_SRV_CONF_OFFSET,
256       0,
257       NULL },
258
259     { ngx_string("listen"),
260       NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
261       ngx_http_core_listen,
262       NGX_HTTP_SRV_CONF_OFFSET,
263       0,
264       NULL },
265
266     { ngx_string("server_name"),
267       NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
268       ngx_http_core_server_name,
269       NGX_HTTP_SRV_CONF_OFFSET,
270       0,
271       NULL },
272
273     { ngx_string("types_hash_max_size"),
274       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
275       ngx_conf_set_num_slot,
276       NGX_HTTP_LOC_CONF_OFFSET,
277       offsetof(ngx_http_core_loc_conf_t, types_hash_max_size),
278       NULL },
279
280     { ngx_string("types_hash_bucket_size"),
281       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
282       ngx_conf_set_num_slot,
283       NGX_HTTP_LOC_CONF_OFFSET,
284       offsetof(ngx_http_core_loc_conf_t, types_hash_bucket_size),
285       NULL },
286
287     { ngx_string("types"),
288       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
289                                           |NGX_CONF_BLOCK|NGX_CONF_NOARGS,
290       ngx_http_core_types,
291       NGX_HTTP_LOC_CONF_OFFSET,
292       0,
293       NULL },
294
295     { ngx_string("default_type"),
296       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
297       ngx_conf_set_str_slot,
298       NGX_HTTP_LOC_CONF_OFFSET,
299       offsetof(ngx_http_core_loc_conf_t, default_type),
300       NULL },
301
302     { ngx_string("root"),
303       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
304                         |NGX_CONF_TAKE1,
305       ngx_http_core_root,
306       NGX_HTTP_LOC_CONF_OFFSET,
307       0,
308       NULL },
309
310     { ngx_string("alias"),
311       NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
312       ngx_http_core_root,
313       NGX_HTTP_LOC_CONF_OFFSET,
314       0,
315       NULL },
316
317     { ngx_string("limit_except"),
318       NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
319       ngx_http_core_limit_except,
320       NGX_HTTP_LOC_CONF_OFFSET,
321       0,
322       NULL },
323
324     { ngx_string("client_max_body_size"),
325       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
326       ngx_conf_set_off_slot,
327       NGX_HTTP_LOC_CONF_OFFSET,
328       offsetof(ngx_http_core_loc_conf_t, client_max_body_size),
329       NULL },
330
331     { ngx_string("client_body_buffer_size"),
332       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
333       ngx_conf_set_size_slot,
334       NGX_HTTP_LOC_CONF_OFFSET,
335       offsetof(ngx_http_core_loc_conf_t, client_body_buffer_size),
336       NULL },
337
338     { ngx_string("client_body_timeout"),
339       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
340       ngx_conf_set_msec_slot,
341       NGX_HTTP_LOC_CONF_OFFSET,
342       offsetof(ngx_http_core_loc_conf_t, client_body_timeout),
343       NULL },
344
345     { ngx_string("client_body_temp_path"),
346       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
347       ngx_conf_set_path_slot,
348       NGX_HTTP_LOC_CONF_OFFSET,
349       offsetof(ngx_http_core_loc_conf_t, client_body_temp_path),
350       (void *) ngx_garbage_collector_temp_handler },
351
352     { ngx_string("client_body_in_file_only"),
353       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
354       ngx_conf_set_enum_slot,
355       NGX_HTTP_LOC_CONF_OFFSET,
356       offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only),
357       &ngx_http_core_request_body_in_file },
358
359     { ngx_string("sendfile"),
360       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
361                         |NGX_CONF_TAKE1,
362       ngx_conf_set_flag_slot,
363       NGX_HTTP_LOC_CONF_OFFSET,
364       offsetof(ngx_http_core_loc_conf_t, sendfile),
365       NULL },
366
367     { ngx_string("sendfile_max_chunk"),
368       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
369       ngx_conf_set_size_slot,
370       NGX_HTTP_LOC_CONF_OFFSET,
371       offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk),
372       NULL },
373
374     { ngx_string("directio"),
375       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
376       ngx_http_core_directio,
377       NGX_HTTP_LOC_CONF_OFFSET,
378       0,
379       NULL },
380
381     { ngx_string("tcp_nopush"),
382       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
383       ngx_conf_set_flag_slot,
384       NGX_HTTP_LOC_CONF_OFFSET,
385       offsetof(ngx_http_core_loc_conf_t, tcp_nopush),
386       NULL },
387
388     { ngx_string("tcp_nodelay"),
389       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
390       ngx_conf_set_flag_slot,
391       NGX_HTTP_LOC_CONF_OFFSET,
392       offsetof(ngx_http_core_loc_conf_t, tcp_nodelay),
393       NULL },
394
395     { ngx_string("send_timeout"),
396       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
397       ngx_conf_set_msec_slot,
398       NGX_HTTP_LOC_CONF_OFFSET,
399       offsetof(ngx_http_core_loc_conf_t, send_timeout),
400       NULL },
401
402     { ngx_string("send_lowat"),
403       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
404       ngx_conf_set_size_slot,
405       NGX_HTTP_LOC_CONF_OFFSET,
406       offsetof(ngx_http_core_loc_conf_t, send_lowat),
407       &ngx_http_core_lowat_post },
408
409     { ngx_string("postpone_output"),
410       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
411       ngx_conf_set_size_slot,
412       NGX_HTTP_LOC_CONF_OFFSET,
413       offsetof(ngx_http_core_loc_conf_t, postpone_output),
414       NULL },
415
416     { ngx_string("limit_rate"),
417       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
418                         |NGX_CONF_TAKE1,
419       ngx_conf_set_size_slot,
420       NGX_HTTP_LOC_CONF_OFFSET,
421       offsetof(ngx_http_core_loc_conf_t, limit_rate),
422       NULL },
423
424     { ngx_string("keepalive_timeout"),
425       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
426       ngx_http_core_keepalive,
427       NGX_HTTP_LOC_CONF_OFFSET,
428       0,
429       NULL },
430
431     { ngx_string("satisfy"),
432       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
433       ngx_conf_set_enum_slot,
434       NGX_HTTP_LOC_CONF_OFFSET,
435       offsetof(ngx_http_core_loc_conf_t, satisfy),
436       &ngx_http_core_satisfy },
437
438     { ngx_string("satisfy_any"),
439       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
440       ngx_conf_set_flag_slot,
441       NGX_HTTP_LOC_CONF_OFFSET,
442       offsetof(ngx_http_core_loc_conf_t, satisfy),
443       &ngx_conf_deprecated_satisfy_any },
444
445     { ngx_string("internal"),
446       NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
447       ngx_http_core_internal,
448       NGX_HTTP_LOC_CONF_OFFSET,
449       0,
450       NULL },
451
452     { ngx_string("lingering_time"),
453       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
454       ngx_conf_set_msec_slot,
455       NGX_HTTP_LOC_CONF_OFFSET,
456       offsetof(ngx_http_core_loc_conf_t, lingering_time),
457       NULL },
458
459     { ngx_string("lingering_timeout"),
460       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
461       ngx_conf_set_msec_slot,
462       NGX_HTTP_LOC_CONF_OFFSET,
463       offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
464       NULL },
465
466     { ngx_string("reset_timedout_connection"),
467       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
468       ngx_conf_set_flag_slot,
469       NGX_HTTP_LOC_CONF_OFFSET,
470       offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
471       NULL },
472
473     { ngx_string("server_name_in_redirect"),
474       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
475       ngx_conf_set_flag_slot,
476       NGX_HTTP_LOC_CONF_OFFSET,
477       offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
478       NULL },
479
480     { ngx_string("port_in_redirect"),
481       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
482       ngx_conf_set_flag_slot,
483       NGX_HTTP_LOC_CONF_OFFSET,
484       offsetof(ngx_http_core_loc_conf_t, port_in_redirect),
485       NULL },
486
487     { ngx_string("msie_padding"),
488       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
489       ngx_conf_set_flag_slot,
490       NGX_HTTP_LOC_CONF_OFFSET,
491       offsetof(ngx_http_core_loc_conf_t, msie_padding),
492       NULL },
493
494     { ngx_string("msie_refresh"),
495       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
496       ngx_conf_set_flag_slot,
497       NGX_HTTP_LOC_CONF_OFFSET,
498       offsetof(ngx_http_core_loc_conf_t, msie_refresh),
499       NULL },
500
501     { ngx_string("log_not_found"),
502       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
503       ngx_conf_set_flag_slot,
504       NGX_HTTP_LOC_CONF_OFFSET,
505       offsetof(ngx_http_core_loc_conf_t, log_not_found),
506       NULL },
507
508     { ngx_string("log_subrequest"),
509       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
510       ngx_conf_set_flag_slot,
511       NGX_HTTP_LOC_CONF_OFFSET,
512       offsetof(ngx_http_core_loc_conf_t, log_subrequest),
513       NULL },
514
515     { ngx_string("recursive_error_pages"),
516       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
517       ngx_conf_set_flag_slot,
518       NGX_HTTP_LOC_CONF_OFFSET,
519       offsetof(ngx_http_core_loc_conf_t, recursive_error_pages),
520       NULL },
521
522     { ngx_string("server_tokens"),
523       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
524       ngx_conf_set_flag_slot,
525       NGX_HTTP_LOC_CONF_OFFSET,
526       offsetof(ngx_http_core_loc_conf_t, server_tokens),
527       NULL },
528
529     { ngx_string("if_modified_since"),
530       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
531       ngx_conf_set_enum_slot,
532       NGX_HTTP_LOC_CONF_OFFSET,
533       offsetof(ngx_http_core_loc_conf_t, if_modified_since),
534       &ngx_http_core_if_modified_since },
535
536     { ngx_string("error_page"),
537       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
538                         |NGX_CONF_2MORE,
539       ngx_http_core_error_page,
540       NGX_HTTP_LOC_CONF_OFFSET,
541       0,
542       NULL },
543
544     { ngx_string("try_files"),
545       NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
546       ngx_http_core_try_files,
547       NGX_HTTP_LOC_CONF_OFFSET,
548       0,
549       NULL },
550
551     { ngx_string("post_action"),
552       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
553                         |NGX_CONF_TAKE1,
554       ngx_conf_set_str_slot,
555       NGX_HTTP_LOC_CONF_OFFSET,
556       offsetof(ngx_http_core_loc_conf_t, post_action),
557       NULL },
558
559     { ngx_string("error_log"),
560       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
561       ngx_http_core_error_log,
562       NGX_HTTP_LOC_CONF_OFFSET,
563       0,
564       NULL },
565
566     { ngx_string("open_file_cache"),
567       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
568       ngx_http_core_open_file_cache,
569       NGX_HTTP_LOC_CONF_OFFSET,
570       offsetof(ngx_http_core_loc_conf_t, open_file_cache),
571       NULL },
572
573     { ngx_string("open_file_cache_valid"),
574       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
575       ngx_conf_set_sec_slot,
576       NGX_HTTP_LOC_CONF_OFFSET,
577       offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid),
578       NULL },
579
580     { ngx_string("open_file_cache_retest"),
581       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
582       ngx_conf_set_sec_slot,
583       NGX_HTTP_LOC_CONF_OFFSET,
584       offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid),
585       &ngx_conf_deprecated_open_file_cache_retest },
586
587     { ngx_string("open_file_cache_min_uses"),
588       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
589       ngx_conf_set_num_slot,
590       NGX_HTTP_LOC_CONF_OFFSET,
591       offsetof(ngx_http_core_loc_conf_t, open_file_cache_min_uses),
592       NULL },
593
594     { ngx_string("open_file_cache_errors"),
595       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
596       ngx_conf_set_flag_slot,
597       NGX_HTTP_LOC_CONF_OFFSET,
598       offsetof(ngx_http_core_loc_conf_t, open_file_cache_errors),
599       NULL },
600
601     { ngx_string("open_file_cache_events"),
602       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
603       ngx_conf_set_flag_slot,
604       NGX_HTTP_LOC_CONF_OFFSET,
605       offsetof(ngx_http_core_loc_conf_t, open_file_cache_events),
606       NULL },
607
608     { ngx_string("resolver"),
609       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
610       ngx_http_core_resolver,
611       NGX_HTTP_LOC_CONF_OFFSET,
612       0,
613       NULL },
614
615     { ngx_string("resolver_timeout"),
616       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
617       ngx_conf_set_msec_slot,
618       NGX_HTTP_LOC_CONF_OFFSET,
619       offsetof(ngx_http_core_loc_conf_t, resolver_timeout),
620       NULL },
621
622 #if (NGX_HTTP_GZIP)
623
624     { ngx_string("gzip_vary"),
625       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
626       ngx_conf_set_flag_slot,
627       NGX_HTTP_LOC_CONF_OFFSET,
628       offsetof(ngx_http_core_loc_conf_t, gzip_vary),
629       NULL },
630
631     { ngx_string("gzip_http_version"),
632       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
633       ngx_conf_set_enum_slot,
634       NGX_HTTP_LOC_CONF_OFFSET,
635       offsetof(ngx_http_core_loc_conf_t, gzip_http_version),
636       &ngx_http_gzip_http_version },
637
638     { ngx_string("gzip_proxied"),
639       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
640       ngx_conf_set_bitmask_slot,
641       NGX_HTTP_LOC_CONF_OFFSET,
642       offsetof(ngx_http_core_loc_conf_t, gzip_proxied),
643       &ngx_http_gzip_proxied_mask },
644
645     { ngx_string("gzip_disable"),
646       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
647       ngx_http_gzip_disable,
648       NGX_HTTP_LOC_CONF_OFFSET,
649       0,
650       NULL },
651
652 #endif
653
654       ngx_null_command
655 };
656
657
658 static ngx_http_module_t  ngx_http_core_module_ctx = {
659     ngx_http_core_preconfiguration,        /* preconfiguration */
660     NULL,                                  /* postconfiguration */
661
662     ngx_http_core_create_main_conf,        /* create main configuration */
663     ngx_http_core_init_main_conf,          /* init main configuration */
664
665     ngx_http_core_create_srv_conf,         /* create server configuration */
666     ngx_http_core_merge_srv_conf,          /* merge server configuration */
667
668     ngx_http_core_create_loc_conf,         /* create location configuration */
669     ngx_http_core_merge_loc_conf           /* merge location configuration */
670 };
671
672
673 ngx_module_t  ngx_http_core_module = {
674     NGX_MODULE_V1,
675     &ngx_http_core_module_ctx,             /* module context */
676     ngx_http_core_commands,                /* module directives */
677     NGX_HTTP_MODULE,                       /* module type */
678     NULL,                                  /* init master */
679     NULL,                                  /* init module */
680     NULL,                                  /* init process */
681     NULL,                                  /* init thread */
682     NULL,                                  /* exit thread */
683     NULL,                                  /* exit process */
684     NULL,                                  /* exit master */
685     NGX_MODULE_V1_PADDING
686 };
687
688
689 static ngx_str_t  ngx_http_core_get_method = { 3, (u_char *) "GET " };
690
691
692 void
693 ngx_http_handler(ngx_http_request_t *r)
694 {
695     ngx_http_core_main_conf_t  *cmcf;
696
697     r->connection->log->action = NULL;
698
699     r->connection->unexpected_eof = 0;
700
701     if (!r->internal) {
702         switch (r->headers_in.connection_type) {
703         case 0:
704             if (r->http_version > NGX_HTTP_VERSION_10) {
705                 r->keepalive = 1;
706             } else {
707                 r->keepalive = 0;
708             }
709             break;
710
711         case NGX_HTTP_CONNECTION_CLOSE:
712             r->keepalive = 0;
713             break;
714
715         case NGX_HTTP_CONNECTION_KEEP_ALIVE:
716             r->keepalive = 1;
717             break;
718         }
719
720         if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
721
722             /*
723              * MSIE may wait for some time if an response for
724              * a POST request was sent over a keepalive connection
725              */
726
727             r->keepalive = 0;
728         }
729
730         if (r->headers_in.content_length_n > 0) {
731             r->lingering_close = 1;
732
733         } else {
734             r->lingering_close = 0;
735         }
736
737         r->phase_handler = 0;
738
739     } else {
740         cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
741         r->phase_handler = cmcf->phase_engine.server_rewrite_index;
742     }
743
744     if (r->unparsed_uri.len) {
745         r->valid_unparsed_uri = 1;
746     }
747
748     r->valid_location = 1;
749     r->gzip = 0;
750
751     r->write_event_handler = ngx_http_core_run_phases;
752     ngx_http_core_run_phases(r);
753 }
754
755
756 void
757 ngx_http_core_run_phases(ngx_http_request_t *r)
758 {
759     ngx_int_t                   rc;
760     ngx_http_phase_handler_t   *ph;
761     ngx_http_core_main_conf_t  *cmcf;
762
763     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
764
765     ph = cmcf->phase_engine.handlers;
766
767     while (ph[r->phase_handler].checker) {
768
769         rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
770
771         if (rc == NGX_OK) {
772             return;
773         }
774     }
775 }
776
777
778 ngx_int_t
779 ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
780 {
781     ngx_int_t  rc;
782
783     /*
784      * generic phase checker,
785      * used by the post read, server rewrite, rewrite, and pre-access phases
786      */
787
788     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
789                    "generic phase: %ui", r->phase_handler);
790
791     rc = ph->handler(r);
792
793     if (rc == NGX_OK) {
794         r->phase_handler = ph->next;
795         return NGX_AGAIN;
796     }
797
798     if (rc == NGX_DECLINED) {
799         r->phase_handler++;
800         return NGX_AGAIN;
801     }
802
803     if (rc == NGX_AGAIN || rc == NGX_DONE) {
804         return NGX_OK;
805     }
806
807     /* rc == NGX_ERROR || rc == NGX_HTTP_...  */
808
809     ngx_http_finalize_request(r, rc);
810
811     return NGX_OK;
812 }
813
814
815 ngx_int_t
816 ngx_http_core_find_config_phase(ngx_http_request_t *r,
817     ngx_http_phase_handler_t *ph)
818 {
819     u_char                    *p;
820     size_t                     len;
821     ngx_int_t                  rc;
822     ngx_http_core_loc_conf_t  *clcf;
823
824     r->content_handler = NULL;
825     r->uri_changed = 0;
826
827     rc = ngx_http_core_find_location(r);
828
829     if (rc == NGX_ERROR) {
830         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
831         return NGX_OK;
832     }
833
834     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
835
836     if (!r->internal && clcf->internal) {
837         ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
838         return NGX_OK;
839     }
840
841     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
842                    "using configuration \"%s%V\"",
843                    (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")),
844                    &clcf->name);
845
846     ngx_http_update_location_config(r);
847
848     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
849                    "http cl:%O max:%O",
850                    r->headers_in.content_length_n, clcf->client_max_body_size);
851
852     if (r->headers_in.content_length_n != -1
853         && !r->discard_body
854         && clcf->client_max_body_size
855         && clcf->client_max_body_size < r->headers_in.content_length_n)
856     {
857         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
858                       "client intended to send too large body: %O bytes",
859                       r->headers_in.content_length_n);
860
861         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
862         return NGX_OK;
863     }
864
865     if (rc == NGX_DONE) {
866         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
867         if (r->headers_out.location == NULL) {
868             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
869             return NGX_OK;
870         }
871
872         /*
873          * we do not need to set the r->headers_out.location->hash and
874          * r->headers_out.location->key fields
875          */
876
877         if (r->args.len == 0) {
878             r->headers_out.location->value = clcf->name;
879
880         } else {
881             len = clcf->name.len + 1 + r->args.len;
882             p = ngx_pnalloc(r->pool, len);
883
884             if (p == NULL) {
885                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
886                 return NGX_OK;
887             }
888
889             r->headers_out.location->value.len = len;
890             r->headers_out.location->value.data = p;
891
892             p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
893             *p++ = '?';
894             ngx_memcpy(p, r->args.data, r->args.len);
895         }
896
897         ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
898         return NGX_OK;
899     }
900
901     r->phase_handler++;
902     return NGX_AGAIN;
903 }
904
905
906 ngx_int_t
907 ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
908     ngx_http_phase_handler_t *ph)
909 {
910     ngx_http_core_srv_conf_t  *cscf;
911
912     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
913                    "post rewrite phase: %ui", r->phase_handler);
914
915     if (!r->uri_changed) {
916         r->phase_handler++;
917         return NGX_AGAIN;
918     }
919
920     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
921                    "uri changes: %d", r->uri_changes);
922
923     /*
924      * gcc before 3.3 compiles the broken code for
925      *     if (r->uri_changes-- == 0)
926      * if the r->uri_changes is defined as
927      *     unsigned  uri_changes:4
928      */
929
930     r->uri_changes--;
931
932     if (r->uri_changes == 0) {
933         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
934                       "rewrite or internal redirection cycle "
935                       "while processing \"%V\"", &r->uri);
936
937         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
938         return NGX_OK;
939     }
940
941     r->phase_handler = ph->next;
942
943     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
944     r->loc_conf = cscf->ctx->loc_conf;
945
946     return NGX_AGAIN;
947 }
948
949
950 ngx_int_t
951 ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
952 {
953     ngx_int_t                  rc;
954     ngx_http_core_loc_conf_t  *clcf;
955
956     if (r != r->main) {
957         r->phase_handler = ph->next;
958         return NGX_AGAIN;
959     }
960
961     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
962                    "access phase: %ui", r->phase_handler);
963
964     rc = ph->handler(r);
965
966     if (rc == NGX_DECLINED) {
967         r->phase_handler++;
968         return NGX_AGAIN;
969     }
970
971     if (rc == NGX_AGAIN || rc == NGX_DONE) {
972         return NGX_OK;
973     }
974
975     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
976
977     if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
978
979         if (rc == NGX_OK) {
980             r->phase_handler++;
981             return NGX_AGAIN;
982         }
983
984     } else {
985         if (rc == NGX_OK) {
986             r->access_code = 0;
987
988             if (r->headers_out.www_authenticate) {
989                 r->headers_out.www_authenticate->hash = 0;
990             }
991
992             r->phase_handler = ph->next;
993             return NGX_AGAIN;
994         }
995
996         if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
997             r->access_code = rc;
998
999             r->phase_handler++;
1000             return NGX_AGAIN;
1001         }
1002     }
1003
1004     /* rc == NGX_ERROR || rc == NGX_HTTP_...  */
1005
1006     ngx_http_finalize_request(r, rc);
1007     return NGX_OK;
1008 }
1009
1010
1011 ngx_int_t
1012 ngx_http_core_post_access_phase(ngx_http_request_t *r,
1013     ngx_http_phase_handler_t *ph)
1014 {
1015     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1016                    "post access phase: %ui", r->phase_handler);
1017
1018     if (r->access_code) {
1019
1020         if (r->access_code == NGX_HTTP_FORBIDDEN) {
1021             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1022                           "access forbidden by rule");
1023         }
1024
1025         ngx_http_finalize_request(r, r->access_code);
1026         return NGX_OK;
1027     }
1028
1029     r->phase_handler++;
1030     return NGX_AGAIN;
1031 }
1032
1033
1034 ngx_int_t
1035 ngx_http_core_try_files_phase(ngx_http_request_t *r,
1036     ngx_http_phase_handler_t *ph)
1037 {
1038     size_t                        len, root, alias, reserve, allocated;
1039     u_char                       *p, *name;
1040     ngx_str_t                     path;
1041     ngx_uint_t                    test_dir;
1042     ngx_http_try_file_t          *tf;
1043     ngx_open_file_info_t          of;
1044     ngx_http_script_code_pt       code;
1045     ngx_http_script_engine_t      e;
1046     ngx_http_core_loc_conf_t     *clcf;
1047     ngx_http_script_len_code_pt   lcode;
1048
1049     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1050                    "try files phase: %ui", r->phase_handler);
1051
1052     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1053
1054     if (clcf->try_files == NULL) {
1055         r->phase_handler++;
1056         return NGX_AGAIN;
1057     }
1058
1059     allocated = 0;
1060     root = 0;
1061     name = NULL;
1062     /* suppress MSVC warning */
1063     path.data = NULL;
1064
1065     tf = clcf->try_files;
1066
1067     alias = clcf->alias ? clcf->name.len : 0;
1068
1069     for ( ;; ) {
1070
1071         if (tf->lengths) {
1072             ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1073
1074             e.ip = tf->lengths->elts;
1075             e.request = r;
1076
1077             /* 1 is for terminating '\0' as in static names */
1078             len = 1;
1079
1080             while (*(uintptr_t *) e.ip) {
1081                 lcode = *(ngx_http_script_len_code_pt *) e.ip;
1082                 len += lcode(&e);
1083             }
1084
1085         } else {
1086             len = tf->name.len;
1087         }
1088
1089         reserve = len - r->uri.len;
1090
1091         /* 16 bytes are preallocation */
1092         reserve = reserve < 16 ? 16 : reserve + 16;
1093
1094         reserve += alias;
1095
1096         if (reserve > allocated) {
1097
1098             /* we just need to allocate path and to copy a root */
1099
1100             if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) {
1101                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1102                 return NGX_OK;
1103             }
1104
1105             name = path.data + root;
1106             allocated = path.len - root - (r->uri.len - alias);
1107          }
1108
1109         if (tf->values == NULL) {
1110
1111             /* tf->name.len includes the terminating '\0' */
1112
1113             ngx_memcpy(name, tf->name.data, tf->name.len);
1114
1115             path.len = (name + tf->name.len - 1) - path.data;
1116
1117         } else {
1118             e.ip = tf->values->elts;
1119             e.pos = name;
1120             e.flushed = 1;
1121
1122             while (*(uintptr_t *) e.ip) {
1123                 code = *(ngx_http_script_code_pt *) e.ip;
1124                 code((ngx_http_script_engine_t *) &e);
1125             }
1126
1127             path.len = e.pos - path.data;
1128
1129             *e.pos++ = '\0';
1130
1131             if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
1132                 ngx_memcpy(name, name + alias, len - alias);
1133                 path.len -= alias;
1134             }
1135         }
1136
1137         test_dir = tf->test_dir;
1138
1139         tf++;
1140
1141         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1142                        "try to use file: \"%s\"", name);
1143
1144         if (tf->lengths == NULL && tf->name.len == 0) {
1145
1146             path.len -= root;
1147             path.data += root;
1148
1149             if (path.data[0] == '@') {
1150                 (void) ngx_http_named_location(r, &path);
1151
1152             } else {
1153                 (void) ngx_http_internal_redirect(r, &path, NULL);
1154             }
1155
1156             return NGX_OK;
1157         }
1158
1159         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1160
1161         of.directio = clcf->directio;
1162         of.valid = clcf->open_file_cache_valid;
1163         of.min_uses = clcf->open_file_cache_min_uses;
1164         of.errors = clcf->open_file_cache_errors;
1165         of.events = clcf->open_file_cache_events;
1166
1167         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1168             != NGX_OK)
1169         {
1170             if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
1171                 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1172                               ngx_open_file_n " \"%s\" failed", path.data);
1173             }
1174
1175             continue;
1176         }
1177
1178         if (of.is_dir && !test_dir) {
1179             continue;
1180         }
1181
1182         path.len -= root;
1183         path.data += root;
1184
1185         if (!alias) {
1186             r->uri = path;
1187
1188         } else {
1189             r->uri.len = alias + path.len;
1190             r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1191             if (r->uri.data == NULL) {
1192                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1193                 return NGX_OK;
1194             }
1195
1196             p = ngx_copy(r->uri.data, clcf->name.data, alias);
1197             ngx_memcpy(p, name, path.len);
1198         }
1199
1200         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1201                        "try file uri: \"%V\"", &r->uri);
1202
1203         r->phase_handler++;
1204         return NGX_AGAIN;
1205     }
1206
1207     /* not reached */
1208 }
1209
1210
1211 ngx_int_t
1212 ngx_http_core_content_phase(ngx_http_request_t *r,
1213     ngx_http_phase_handler_t *ph)
1214 {
1215     size_t     root;
1216     ngx_int_t  rc;
1217     ngx_str_t  path;
1218
1219     if (r->content_handler) {
1220         r->write_event_handler = ngx_http_request_empty_handler;
1221         ngx_http_finalize_request(r, r->content_handler(r));
1222         return NGX_OK;
1223     }
1224
1225     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1226                    "content phase: %ui", r->phase_handler);
1227
1228     rc = ph->handler(r);
1229
1230     if (rc == NGX_DONE) {
1231         return NGX_OK;
1232     }
1233
1234     if (rc != NGX_DECLINED) {
1235         ngx_http_finalize_request(r, rc);
1236         return NGX_OK;
1237     }
1238
1239     /* rc == NGX_DECLINED */
1240
1241     ph++;
1242
1243     if (ph->checker) {
1244         r->phase_handler++;
1245         return NGX_AGAIN;
1246     }
1247
1248     /* no content handler was found */
1249
1250     if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
1251
1252         if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
1253             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1254                           "directory index of \"%s\" is forbidden", path.data);
1255         }
1256
1257         ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
1258         return NGX_OK;
1259     }
1260
1261     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
1262
1263     ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1264     return NGX_OK;
1265 }
1266
1267
1268 void
1269 ngx_http_update_location_config(ngx_http_request_t *r)
1270 {
1271     ngx_http_core_loc_conf_t  *clcf;
1272
1273     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1274
1275     if (r->method & clcf->limit_except) {
1276         r->loc_conf = clcf->limit_except_loc_conf;
1277         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1278     }
1279
1280     if (r == r->main) {
1281         r->connection->log->file = clcf->err_log->file;
1282
1283         if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1284             r->connection->log->log_level = clcf->err_log->log_level;
1285         }
1286     }
1287
1288     if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
1289         r->connection->sendfile = 1;
1290
1291     } else {
1292         r->connection->sendfile = 0;
1293     }
1294
1295     if (clcf->client_body_in_file_only) {
1296         r->request_body_in_file_only = 1;
1297         r->request_body_in_persistent_file = 1;
1298         r->request_body_in_clean_file =
1299             clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
1300         r->request_body_file_log_level = NGX_LOG_NOTICE;
1301
1302     } else {
1303         r->request_body_file_log_level = NGX_LOG_WARN;
1304     }
1305
1306     if (r->keepalive && clcf->keepalive_timeout == 0) {
1307         r->keepalive = 0;
1308     }
1309
1310     if (!clcf->tcp_nopush) {
1311         /* disable TCP_NOPUSH/TCP_CORK use */
1312         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
1313     }
1314
1315     if (r->limit_rate == 0) {
1316         r->limit_rate = clcf->limit_rate;
1317     }
1318
1319     if (clcf->handler) {
1320         r->content_handler = clcf->handler;
1321     }
1322 }
1323
1324
1325 /*
1326  * NGX_OK       - exact or regex match
1327  * NGX_DONE     - auto redirect
1328  * NGX_AGAIN    - inclusive match
1329  * NGX_ERROR    - regex error
1330  * NGX_DECLINED - no match
1331  */
1332
1333 static ngx_int_t
1334 ngx_http_core_find_location(ngx_http_request_t *r)
1335 {
1336     ngx_int_t                  rc;
1337     ngx_http_core_loc_conf_t  *pclcf;
1338 #if (NGX_PCRE)
1339     ngx_int_t                  n;
1340     ngx_uint_t                 noregex;
1341     ngx_http_core_loc_conf_t  *clcf, **clcfp;
1342
1343     noregex = 0;
1344 #endif
1345
1346     pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1347
1348     rc = ngx_http_core_find_static_location(r, pclcf->static_locations);
1349
1350     if (rc == NGX_AGAIN) {
1351
1352 #if (NGX_PCRE)
1353         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1354
1355         noregex = clcf->noregex;
1356 #endif
1357
1358         /* look up nested locations */
1359
1360         rc = ngx_http_core_find_location(r);
1361     }
1362
1363     if (rc == NGX_OK || rc == NGX_DONE) {
1364         return rc;
1365     }
1366
1367     /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */
1368
1369 #if (NGX_PCRE)
1370
1371     if (noregex == 0 && pclcf->regex_locations) {
1372
1373         for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
1374
1375             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1376                            "test location: ~ \"%V\"", &(*clcfp)->name);
1377
1378             n = ngx_regex_exec((*clcfp)->regex, &r->uri, NULL, 0);
1379
1380             if (n == NGX_REGEX_NO_MATCHED) {
1381                 continue;
1382             }
1383
1384             if (n < 0) {
1385                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1386                               ngx_regex_exec_n
1387                               " failed: %d on \"%V\" using \"%V\"",
1388                               n, &r->uri, &(*clcfp)->name);
1389                 return NGX_ERROR;
1390             }
1391
1392             /* match */
1393
1394             r->loc_conf = (*clcfp)->loc_conf;
1395
1396             /* look up nested locations */
1397
1398             rc = ngx_http_core_find_location(r);
1399
1400             return (rc == NGX_ERROR) ? rc : NGX_OK;
1401         }
1402     }
1403 #endif
1404
1405     return rc;
1406 }
1407
1408
1409 /*
1410  * NGX_OK       - exact match
1411  * NGX_DONE     - auto redirect
1412  * NGX_AGAIN    - inclusive match
1413  * NGX_DECLINED - no match
1414  */
1415
1416 static ngx_int_t
1417 ngx_http_core_find_static_location(ngx_http_request_t *r,
1418     ngx_http_location_tree_node_t *node)
1419 {
1420     u_char     *uri;
1421     size_t      len, n;
1422     ngx_int_t   rc, rv;
1423
1424     len = r->uri.len;
1425     uri = r->uri.data;
1426
1427     rv = NGX_DECLINED;
1428
1429     for ( ;; ) {
1430
1431         if (node == NULL) {
1432             return rv;
1433         }
1434
1435         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1436                        "test location: \"%*s\"", node->len, node->name);
1437
1438         n = (len <= (size_t) node->len) ? len : node->len;
1439
1440         rc = ngx_filename_cmp(uri, node->name, n);
1441
1442         if (rc != 0) {
1443             node = (rc < 0) ? node->left : node->right;
1444
1445             continue;
1446         }
1447
1448         if (len > (size_t) node->len) {
1449
1450             if (node->inclusive) {
1451
1452                 r->loc_conf = node->inclusive->loc_conf;
1453                 rv = NGX_AGAIN;
1454
1455                 node = node->tree;
1456                 uri += n;
1457                 len -= n;
1458
1459                 continue;
1460             }
1461
1462             /* exact only */
1463
1464             node = node->right;
1465
1466             continue;
1467         }
1468
1469         if (len == (size_t) node->len) {
1470
1471             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1472                                           node->inclusive->loc_conf;
1473             return NGX_OK;
1474         }
1475
1476         /* len < node->len */
1477
1478         if (len + 1 == (size_t) node->len && node->auto_redirect) {
1479
1480             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1481                                           node->inclusive->loc_conf;
1482             rv = NGX_DONE;
1483         }
1484
1485         node = node->left;
1486     }
1487 }
1488
1489
1490 void *
1491 ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
1492 {
1493     u_char       c, *p;
1494     ngx_uint_t   i, hash;
1495
1496     if (r->headers_out.content_type.len == 0) {
1497         return NULL;
1498     }
1499
1500     if (r->headers_out.content_type_lowcase == NULL) {
1501
1502         p = ngx_pnalloc(r->pool, r->headers_out.content_type_len);
1503
1504         if (p == NULL) {
1505             return NULL;
1506         }
1507
1508         r->headers_out.content_type_lowcase = p;
1509
1510         hash = 0;
1511
1512         for (i = 0; i < r->headers_out.content_type_len; i++) {
1513             c = ngx_tolower(r->headers_out.content_type.data[i]);
1514             hash = ngx_hash(hash, c);
1515             *p++ = c;
1516         }
1517
1518         r->headers_out.content_type_hash = hash;
1519     }
1520
1521     return ngx_hash_find(types_hash,
1522                          r->headers_out.content_type_hash,
1523                          r->headers_out.content_type_lowcase,
1524                          r->headers_out.content_type_len);
1525 }
1526
1527
1528 ngx_int_t
1529 ngx_http_set_content_type(ngx_http_request_t *r)
1530 {
1531     u_char                     c, *exten;
1532     ngx_str_t                 *type;
1533     ngx_uint_t                 i, hash;
1534     ngx_http_core_loc_conf_t  *clcf;
1535
1536     if (r->headers_out.content_type.len) {
1537         return NGX_OK;
1538     }
1539
1540     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1541
1542     if (r->exten.len) {
1543
1544         hash = 0;
1545
1546         for (i = 0; i < r->exten.len; i++) {
1547             c = r->exten.data[i];
1548
1549             if (c >= 'A' && c <= 'Z') {
1550
1551                 exten = ngx_pnalloc(r->pool, r->exten.len);
1552                 if (exten == NULL) {
1553                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
1554                 }
1555
1556                 hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);
1557
1558                 r->exten.data = exten;
1559
1560                 break;
1561             }
1562
1563             hash = ngx_hash(hash, c);
1564         }
1565
1566         type = ngx_hash_find(&clcf->types_hash, hash,
1567                              r->exten.data, r->exten.len);
1568
1569         if (type) {
1570             r->headers_out.content_type_len = type->len;
1571             r->headers_out.content_type = *type;
1572
1573             return NGX_OK;
1574         }
1575     }
1576
1577     r->headers_out.content_type_len = clcf->default_type.len;
1578     r->headers_out.content_type = clcf->default_type;
1579
1580     return NGX_OK;
1581 }
1582
1583
1584 ngx_int_t
1585 ngx_http_set_exten(ngx_http_request_t *r)
1586 {
1587     ngx_int_t  i;
1588
1589     r->exten.len = 0;
1590     r->exten.data = NULL;
1591
1592     for (i = r->uri.len - 1; i > 1; i--) {
1593         if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
1594
1595             r->exten.len = r->uri.len - i - 1;
1596             r->exten.data = &r->uri.data[i + 1];
1597
1598             break;
1599
1600         } else if (r->uri.data[i] == '/') {
1601             break;
1602         }
1603     }
1604
1605     return NGX_OK;
1606 }
1607
1608
1609 ngx_int_t
1610 ngx_http_send_header(ngx_http_request_t *r)
1611 {
1612     if (r->err_status) {
1613         r->headers_out.status = r->err_status;
1614         r->headers_out.status_line.len = 0;
1615     }
1616
1617     return ngx_http_top_header_filter(r);
1618 }
1619
1620
1621 ngx_int_t
1622 ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
1623 {
1624     ngx_int_t  rc;
1625
1626     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1627                    "http output filter \"%V?%V\"", &r->uri, &r->args);
1628
1629     rc = ngx_http_top_body_filter(r, in);
1630
1631     if (rc == NGX_ERROR) {
1632         /* NGX_ERROR may be returned by any filter */
1633         r->connection->error = 1;
1634     }
1635
1636     return rc;
1637 }
1638
1639
1640 u_char *
1641 ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
1642     size_t *root_length, size_t reserved)
1643 {
1644     u_char                    *last;
1645     size_t                     alias;
1646     ngx_http_core_loc_conf_t  *clcf;
1647
1648     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1649
1650     alias = clcf->alias ? clcf->name.len : 0;
1651
1652     if (alias && !r->valid_location) {
1653         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1654                       "\"alias\" could not be used in location \"%V\" "
1655                       "where URI was rewritten", &clcf->name);
1656         return NULL;
1657     }
1658
1659     reserved += r->uri.len - alias + 1;
1660
1661     if (clcf->root_lengths == NULL) {
1662
1663         *root_length = clcf->root.len;
1664
1665         path->len = clcf->root.len + reserved;
1666
1667         path->data = ngx_pnalloc(r->pool, path->len);
1668         if (path->data == NULL) {
1669             return NULL;
1670         }
1671
1672         last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
1673
1674     } else {
1675         if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
1676                                 clcf->root_values->elts)
1677             == NULL)
1678         {
1679             return NULL;
1680         }
1681
1682         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0)== NGX_ERROR)
1683         {
1684             return NULL;
1685         }
1686
1687         *root_length = path->len - reserved;
1688         last = path->data + *root_length;
1689     }
1690
1691     last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
1692
1693     return last;
1694 }
1695
1696
1697 ngx_int_t
1698 ngx_http_auth_basic_user(ngx_http_request_t *r)
1699 {
1700     ngx_str_t   auth, encoded;
1701     ngx_uint_t  len;
1702
1703     if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
1704         return NGX_DECLINED;
1705     }
1706
1707     if (r->headers_in.authorization == NULL) {
1708         r->headers_in.user.data = (u_char *) "";
1709         return NGX_DECLINED;
1710     }
1711
1712     encoded = r->headers_in.authorization->value;
1713
1714     if (encoded.len < sizeof("Basic ") - 1
1715         || ngx_strncasecmp(encoded.data, (u_char *) "Basic ",
1716                            sizeof("Basic ") - 1)
1717            != 0)
1718     {
1719         r->headers_in.user.data = (u_char *) "";
1720         return NGX_DECLINED;
1721     }
1722
1723     encoded.len -= sizeof("Basic ") - 1;
1724     encoded.data += sizeof("Basic ") - 1;
1725
1726     while (encoded.len && encoded.data[0] == ' ') {
1727         encoded.len--;
1728         encoded.data++;
1729     }
1730
1731     if (encoded.len == 0) {
1732         r->headers_in.user.data = (u_char *) "";
1733         return NGX_DECLINED;
1734     }
1735
1736     auth.len = ngx_base64_decoded_length(encoded.len);
1737     auth.data = ngx_pnalloc(r->pool, auth.len + 1);
1738     if (auth.data == NULL) {
1739         return NGX_ERROR;
1740     }
1741
1742     if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
1743         r->headers_in.user.data = (u_char *) "";
1744         return NGX_DECLINED;
1745     }
1746
1747     auth.data[auth.len] = '\0';
1748
1749     for (len = 0; len < auth.len; len++) {
1750         if (auth.data[len] == ':') {
1751             break;
1752         }
1753     }
1754
1755     if (len == 0 || len == auth.len) {
1756         r->headers_in.user.data = (u_char *) "";
1757         return NGX_DECLINED;
1758     }
1759
1760     r->headers_in.user.len = len;
1761     r->headers_in.user.data = auth.data;
1762     r->headers_in.passwd.len = auth.len - len - 1;
1763     r->headers_in.passwd.data = &auth.data[len + 1];
1764
1765     return NGX_OK;
1766 }
1767
1768
1769 ngx_int_t
1770 ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
1771 {
1772     socklen_t            len;
1773     ngx_connection_t    *c;
1774     struct sockaddr_in   sin;
1775
1776     /* AF_INET only */
1777
1778     c = r->connection;
1779
1780     if (r->in_addr == 0) {
1781         len = sizeof(struct sockaddr_in);
1782         if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
1783             ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1784             return NGX_ERROR;
1785         }
1786
1787         r->in_addr = sin.sin_addr.s_addr;
1788
1789     } else {
1790         sin.sin_family = c->sockaddr->sa_family;
1791         sin.sin_addr.s_addr = r->in_addr;
1792     }
1793
1794     if (s == NULL) {
1795         return NGX_OK;
1796     }
1797
1798     s->len = ngx_sock_ntop((struct sockaddr *) &sin, s->data,
1799                            NGX_INET_ADDRSTRLEN);
1800
1801     return NGX_OK;
1802 }
1803
1804
1805 #if (NGX_HTTP_GZIP)
1806
1807 ngx_int_t
1808 ngx_http_gzip_ok(ngx_http_request_t *r)
1809 {
1810     time_t                     date, expires;
1811     ngx_uint_t                 p;
1812     ngx_array_t               *cc;
1813     ngx_table_elt_t           *e, *d;
1814     ngx_http_core_loc_conf_t  *clcf;
1815
1816     if (r->gzip == 1) {
1817         return NGX_OK;
1818     }
1819
1820     if (r->gzip == 2) {
1821         return NGX_DECLINED;
1822     }
1823
1824     r->gzip = 2;
1825
1826     if (r != r->main
1827         || r->headers_in.accept_encoding == NULL
1828         || ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
1829                            "gzip", 4 - 1)
1830            == NULL
1831
1832         /*
1833          * if the URL (without the "http://" prefix) is longer than 253 bytes,
1834          * then MSIE 4.x can not handle the compressed stream - it waits
1835          * too long, hangs up or crashes
1836          */
1837
1838         || (r->headers_in.msie4 && r->unparsed_uri.len > 200))
1839     {
1840         return NGX_DECLINED;
1841     }
1842
1843     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1844
1845     if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
1846         return NGX_DECLINED;
1847     }
1848
1849     if (r->http_version < clcf->gzip_http_version) {
1850         return NGX_DECLINED;
1851     }
1852
1853     if (r->headers_in.via == NULL) {
1854         goto ok;
1855     }
1856
1857     p = clcf->gzip_proxied;
1858
1859     if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
1860         return NGX_DECLINED;
1861     }
1862
1863     if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
1864         goto ok;
1865     }
1866
1867     if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
1868         goto ok;
1869     }
1870
1871     e = r->headers_out.expires;
1872
1873     if (e) {
1874
1875         if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
1876             return NGX_DECLINED;
1877         }
1878
1879         expires = ngx_http_parse_time(e->value.data, e->value.len);
1880         if (expires == NGX_ERROR) {
1881             return NGX_DECLINED;
1882         }
1883
1884         d = r->headers_out.date;
1885
1886         if (d) {
1887             date = ngx_http_parse_time(d->value.data, d->value.len);
1888             if (date == NGX_ERROR) {
1889                 return NGX_DECLINED;
1890             }
1891
1892         } else {
1893             date = ngx_time();
1894         }
1895
1896         if (expires < date) {
1897             goto ok;
1898         }
1899
1900         return NGX_DECLINED;
1901     }
1902
1903     cc = &r->headers_out.cache_control;
1904
1905     if (cc->elts) {
1906
1907         if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
1908             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
1909                                                  NULL)
1910                >= 0)
1911         {
1912             goto ok;
1913         }
1914
1915         if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
1916             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
1917                                                  NULL)
1918                >= 0)
1919         {
1920             goto ok;
1921         }
1922
1923         if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
1924             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
1925                                                  NULL)
1926                >= 0)
1927         {
1928             goto ok;
1929         }
1930
1931         return NGX_DECLINED;
1932     }
1933
1934     if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
1935         return NGX_DECLINED;
1936     }
1937
1938     if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
1939         return NGX_DECLINED;
1940     }
1941
1942 ok:
1943
1944 #if (NGX_PCRE)
1945
1946     if (clcf->gzip_disable && r->headers_in.user_agent) {
1947
1948         if (ngx_regex_exec_array(clcf->gzip_disable,
1949                                  &r->headers_in.user_agent->value,
1950                                  r->connection->log)
1951             != NGX_DECLINED)
1952         {
1953             return NGX_DECLINED;
1954         }
1955     }
1956
1957 #endif
1958
1959     r->gzip = 1;
1960
1961     return NGX_OK;
1962 }
1963
1964 #endif
1965
1966
1967 ngx_int_t
1968 ngx_http_subrequest(ngx_http_request_t *r,
1969     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
1970     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
1971 {
1972     ngx_connection_t              *c;
1973     ngx_http_request_t            *sr;
1974     ngx_http_core_srv_conf_t      *cscf;
1975     ngx_http_postponed_request_t  *pr, *p;
1976
1977     r->main->subrequests--;
1978
1979     if (r->main->subrequests == 0) {
1980         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1981                       "subrequests cycle while processing \"%V\"", uri);
1982         r->main->subrequests = 1;
1983         return NGX_ERROR;
1984     }
1985
1986     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
1987     if (sr == NULL) {
1988         return NGX_ERROR;
1989     }
1990
1991     sr->signature = NGX_HTTP_MODULE;
1992
1993     c = r->connection;
1994     sr->connection = c;
1995
1996     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
1997     if (sr->ctx == NULL) {
1998         return NGX_ERROR;
1999     }
2000
2001     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
2002                       sizeof(ngx_table_elt_t))
2003         == NGX_ERROR)
2004     {
2005         return NGX_ERROR;
2006     }
2007
2008     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2009     sr->main_conf = cscf->ctx->main_conf;
2010     sr->srv_conf = cscf->ctx->srv_conf;
2011     sr->loc_conf = cscf->ctx->loc_conf;
2012
2013     sr->pool = r->pool;
2014
2015     sr->headers_in = r->headers_in;
2016
2017     ngx_http_clear_content_length(sr);
2018     ngx_http_clear_accept_ranges(sr);
2019     ngx_http_clear_last_modified(sr);
2020
2021     sr->request_body = r->request_body;
2022
2023     sr->method = NGX_HTTP_GET;
2024     sr->http_version = r->http_version;
2025
2026     sr->request_line = r->request_line;
2027     sr->uri = *uri;
2028
2029     if (args) {
2030         sr->args = *args;
2031     }
2032
2033     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2034                    "http subrequest \"%V?%V\"", uri, &sr->args);
2035
2036     sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
2037     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
2038     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
2039
2040     sr->unparsed_uri = r->unparsed_uri;
2041     sr->method_name = ngx_http_core_get_method;
2042     sr->http_protocol = r->http_protocol;
2043
2044     if (ngx_http_set_exten(sr) != NGX_OK) {
2045         return NGX_ERROR;
2046     }
2047
2048     sr->main = r->main;
2049     sr->parent = r;
2050     sr->post_subrequest = ps;
2051     sr->read_event_handler = ngx_http_request_empty_handler;
2052     sr->write_event_handler = ngx_http_handler;
2053
2054     if (c->data == r && r->postponed == NULL) {
2055         c->data = sr;
2056     }
2057
2058     sr->in_addr = r->in_addr;
2059     sr->port = r->port;
2060     sr->port_text = r->port_text;
2061
2062     sr->variables = r->variables;
2063
2064     sr->log_handler = r->log_handler;
2065
2066     pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
2067     if (pr == NULL) {
2068         return NGX_ERROR;
2069     }
2070
2071     pr->request = sr;
2072     pr->out = NULL;
2073     pr->next = NULL;
2074
2075     if (r->postponed) {
2076         for (p = r->postponed; p->next; p = p->next) { /* void */ }
2077         p->next = pr;
2078
2079     } else {
2080         r->postponed = pr;
2081     }
2082
2083     sr->internal = 1;
2084
2085     sr->discard_body = r->discard_body;
2086     sr->expect_tested = 1;
2087     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
2088
2089     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
2090
2091     r->main->subrequests++;
2092
2093     *psr = sr;
2094
2095     return ngx_http_post_request(sr);
2096 }
2097
2098
2099 ngx_int_t
2100 ngx_http_internal_redirect(ngx_http_request_t *r,
2101     ngx_str_t *uri, ngx_str_t *args)
2102 {
2103     ngx_http_core_srv_conf_t  *cscf;
2104
2105     r->uri_changes--;
2106
2107     if (r->uri_changes == 0) {
2108         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2109                       "rewrite or internal redirection cycle "
2110                       "while internal redirect to \"%V\"", uri);
2111
2112         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2113         return NGX_DONE;
2114     }
2115
2116     r->uri = *uri;
2117
2118     if (args) {
2119         r->args = *args;
2120
2121     } else {
2122         r->args.len = 0;
2123         r->args.data = NULL;
2124     }
2125
2126     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2127                    "internal redirect: \"%V?%V\"", uri, &r->args);
2128
2129     if (ngx_http_set_exten(r) != NGX_OK) {
2130         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2131         return NGX_DONE;
2132     }
2133
2134     /* clear the modules contexts */
2135     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2136
2137     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2138     r->loc_conf = cscf->ctx->loc_conf;
2139
2140     ngx_http_update_location_config(r);
2141
2142     r->internal = 1;
2143
2144     ngx_http_handler(r);
2145
2146     return NGX_DONE;
2147 }
2148
2149
2150 ngx_int_t
2151 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
2152 {
2153     ngx_http_core_srv_conf_t    *cscf;
2154     ngx_http_core_loc_conf_t   **clcfp;
2155     ngx_http_core_main_conf_t   *cmcf;
2156
2157     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2158
2159     if (cscf->named_locations) {
2160
2161         for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
2162
2163             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2164                            "test location: \"%V\"", &(*clcfp)->name);
2165
2166             if (name->len != (*clcfp)->name.len
2167                 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
2168             {
2169                 continue;
2170             }
2171
2172             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2173                            "using location: %V \"%V?%V\"",
2174                            name, &r->uri, &r->args);
2175
2176             r->internal = 1;
2177             r->content_handler = NULL;
2178             r->loc_conf = (*clcfp)->loc_conf;
2179
2180             ngx_http_update_location_config(r);
2181
2182             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2183
2184             r->phase_handler = cmcf->phase_engine.location_rewrite_index;
2185
2186             ngx_http_core_run_phases(r);
2187
2188             return NGX_DONE;
2189         }
2190     }
2191
2192     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2193                   "could not find named location \"%V\"", name);
2194
2195     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2196
2197     return NGX_DONE;
2198 }
2199
2200
2201 ngx_http_cleanup_t *
2202 ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
2203 {
2204     ngx_http_cleanup_t  *cln;
2205
2206     r = r->main;
2207
2208     cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
2209     if (cln == NULL) {
2210         return NULL;
2211     }
2212
2213     if (size) {
2214         cln->data = ngx_palloc(r->pool, size);
2215         if (cln->data == NULL) {
2216             return NULL;
2217         }
2218
2219     } else {
2220         cln->data = NULL;
2221     }
2222
2223     cln->handler = NULL;
2224     cln->next = r->cleanup;
2225
2226     r->cleanup = cln;
2227
2228     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2229                    "http cleanup add: %p", cln);
2230
2231     return cln;
2232 }
2233
2234
2235 static char *
2236 ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2237 {
2238     char                        *rv;
2239     void                        *mconf;
2240     ngx_uint_t                   i;
2241     ngx_conf_t                   pcf;
2242     ngx_http_module_t           *module;
2243     ngx_http_conf_ctx_t         *ctx, *http_ctx;
2244     ngx_http_core_srv_conf_t    *cscf, **cscfp;
2245     ngx_http_core_main_conf_t   *cmcf;
2246
2247     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2248     if (ctx == NULL) {
2249         return NGX_CONF_ERROR;
2250     }
2251
2252     http_ctx = cf->ctx;
2253     ctx->main_conf = http_ctx->main_conf;
2254
2255     /* the server{}'s srv_conf */
2256
2257     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2258     if (ctx->srv_conf == NULL) {
2259         return NGX_CONF_ERROR;
2260     }
2261
2262     /* the server{}'s loc_conf */
2263
2264     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2265     if (ctx->loc_conf == NULL) {
2266         return NGX_CONF_ERROR;
2267     }
2268
2269     for (i = 0; ngx_modules[i]; i++) {
2270         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2271             continue;
2272         }
2273
2274         module = ngx_modules[i]->ctx;
2275
2276         if (module->create_srv_conf) {
2277             mconf = module->create_srv_conf(cf);
2278             if (mconf == NULL) {
2279                 return NGX_CONF_ERROR;
2280             }
2281
2282             ctx->srv_conf[ngx_modules[i]->ctx_index] = mconf;
2283         }
2284
2285         if (module->create_loc_conf) {
2286             mconf = module->create_loc_conf(cf);
2287             if (mconf == NULL) {
2288                 return NGX_CONF_ERROR;
2289             }
2290
2291             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
2292         }
2293     }
2294
2295
2296     /* the server configuration context */
2297
2298     cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
2299     cscf->ctx = ctx;
2300
2301
2302     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
2303
2304     cscfp = ngx_array_push(&cmcf->servers);
2305     if (cscfp == NULL) {
2306         return NGX_CONF_ERROR;
2307     }
2308
2309     *cscfp = cscf;
2310
2311
2312     /* parse inside server{} */
2313
2314     pcf = *cf;
2315     cf->ctx = ctx;
2316     cf->cmd_type = NGX_HTTP_SRV_CONF;
2317
2318     rv = ngx_conf_parse(cf, NULL);
2319
2320     *cf = pcf;
2321
2322     return rv;
2323 }
2324
2325
2326 static char *
2327 ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2328 {
2329     char                      *rv;
2330     u_char                    *mod;
2331     size_t                     len;
2332     ngx_str_t                 *value, *name;
2333     ngx_uint_t                 i;
2334     ngx_conf_t                 save;
2335     ngx_http_module_t         *module;
2336     ngx_http_conf_ctx_t       *ctx, *pctx;
2337     ngx_http_core_loc_conf_t  *clcf, *pclcf;
2338
2339     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2340     if (ctx == NULL) {
2341         return NGX_CONF_ERROR;
2342     }
2343
2344     pctx = cf->ctx;
2345     ctx->main_conf = pctx->main_conf;
2346     ctx->srv_conf = pctx->srv_conf;
2347
2348     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2349     if (ctx->loc_conf == NULL) {
2350         return NGX_CONF_ERROR;
2351     }
2352
2353     for (i = 0; ngx_modules[i]; i++) {
2354         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2355             continue;
2356         }
2357
2358         module = ngx_modules[i]->ctx;
2359
2360         if (module->create_loc_conf) {
2361             ctx->loc_conf[ngx_modules[i]->ctx_index] =
2362                                                    module->create_loc_conf(cf);
2363             if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) {
2364                  return NGX_CONF_ERROR;
2365             }
2366         }
2367     }
2368
2369     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
2370     clcf->loc_conf = ctx->loc_conf;
2371
2372     value = cf->args->elts;
2373
2374     if (cf->args->nelts == 3) {
2375
2376         len = value[1].len;
2377         mod = value[1].data;
2378         name = &value[2];
2379
2380         if (len == 1 && mod[0] == '=') {
2381
2382             clcf->name = *name;
2383             clcf->exact_match = 1;
2384
2385         } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
2386
2387             clcf->name = *name;
2388             clcf->noregex = 1;
2389
2390         } else if (len == 1 && mod[0] == '~') {
2391
2392             if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2393                 return NGX_CONF_ERROR;
2394             }
2395
2396         } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
2397
2398             if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2399                 return NGX_CONF_ERROR;
2400             }
2401
2402         } else {
2403             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2404                                "invalid location modifier \"%V\"", &value[1]);
2405             return NGX_CONF_ERROR;
2406         }
2407
2408     } else {
2409
2410         name = &value[1];
2411
2412         if (name->data[0] == '=') {
2413
2414             clcf->name.len = name->len - 1;
2415             clcf->name.data = name->data + 1;
2416             clcf->exact_match = 1;
2417
2418         } else if (name->data[0] == '^' && name->data[1] == '~') {
2419
2420             clcf->name.len = name->len - 2;
2421             clcf->name.data = name->data + 2;
2422             clcf->noregex = 1;
2423
2424         } else if (name->data[0] == '~') {
2425
2426             name->len--;
2427             name->data++;
2428
2429             if (name->data[0] == '*') {
2430
2431                 name->len--;
2432                 name->data++;
2433
2434                 if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2435                     return NGX_CONF_ERROR;
2436                 }
2437
2438             } else {
2439                 if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2440                     return NGX_CONF_ERROR;
2441                 }
2442             }
2443
2444         } else {
2445
2446             clcf->name = *name;
2447
2448             if (name->data[0] == '@') {
2449                 clcf->named = 1;
2450             }
2451         }
2452     }
2453
2454     pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
2455
2456     if (pclcf->name.len) {
2457
2458         /* nested location */
2459
2460 #if 0
2461         clcf->prev_location = pclcf;
2462 #endif
2463
2464         if (pclcf->exact_match) {
2465             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2466                                "location \"%V\" could not be inside "
2467                                "the exact location \"%V\"",
2468                                &clcf->name, &pclcf->name);
2469             return NGX_CONF_ERROR;
2470         }
2471
2472         if (pclcf->named) {
2473             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2474                                "location \"%V\" could not be inside "
2475                                "the named location \"%V\"",
2476                                &clcf->name, &pclcf->name);
2477             return NGX_CONF_ERROR;
2478         }
2479
2480         if (clcf->named) {
2481             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2482                                "named location \"%V\" must be "
2483                                "on server level only",
2484                                &clcf->name);
2485             return NGX_CONF_ERROR;
2486         }
2487
2488         len = pclcf->name.len;
2489
2490 #if (NGX_PCRE)
2491         if (clcf->regex == NULL
2492             && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2493 #else
2494         if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2495 #endif
2496         {
2497             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2498                                "location \"%V\" is outside location \"%V\"",
2499                                &clcf->name, &pclcf->name);
2500             return NGX_CONF_ERROR;
2501         }
2502     }
2503
2504     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
2505         return NGX_CONF_ERROR;
2506     }
2507
2508     save = *cf;
2509     cf->ctx = ctx;
2510     cf->cmd_type = NGX_HTTP_LOC_CONF;
2511
2512     rv = ngx_conf_parse(cf, NULL);
2513
2514     *cf = save;
2515
2516     return rv;
2517 }
2518
2519
2520 static ngx_int_t
2521 ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
2522     ngx_str_t *regex, ngx_uint_t caseless)
2523 {
2524 #if (NGX_PCRE)
2525     ngx_str_t  err;
2526     u_char     errstr[NGX_MAX_CONF_ERRSTR];
2527
2528     err.len = NGX_MAX_CONF_ERRSTR;
2529     err.data = errstr;
2530
2531     clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
2532                                     cf->pool, &err);
2533
2534     if (clcf->regex == NULL) {
2535         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
2536         return NGX_ERROR;
2537     }
2538
2539     clcf->name = *regex;
2540
2541     return NGX_OK;
2542
2543 #else
2544
2545     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2546                        "the using of the regex \"%V\" requires PCRE library",
2547                        regex);
2548     return NGX_ERROR;
2549
2550 #endif
2551 }
2552
2553
2554 static char *
2555 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2556 {
2557     ngx_http_core_loc_conf_t *lcf = conf;
2558
2559     char        *rv;
2560     ngx_conf_t   save;
2561
2562     if (lcf->types == NULL) {
2563         lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
2564         if (lcf->types == NULL) {
2565             return NGX_CONF_ERROR;
2566         }
2567     }
2568
2569     save = *cf;
2570     cf->handler = ngx_http_core_type;
2571     cf->handler_conf = conf;
2572
2573     rv = ngx_conf_parse(cf, NULL);
2574
2575     *cf = save;
2576
2577     return rv;
2578 }
2579
2580
2581 static char *
2582 ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
2583 {
2584     ngx_http_core_loc_conf_t *lcf = conf;
2585
2586     ngx_str_t       *value, *content_type, *old, file;
2587     ngx_uint_t       i, n, hash;
2588     ngx_hash_key_t  *type;
2589
2590     value = cf->args->elts;
2591
2592     if (ngx_strcmp(value[0].data, "include") == 0) {
2593         file = value[1];
2594
2595         if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){
2596             return NGX_CONF_ERROR;
2597         }
2598
2599         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
2600
2601         return ngx_conf_parse(cf, &file);
2602     }
2603
2604     content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
2605     if (content_type == NULL) {
2606         return NGX_CONF_ERROR;
2607     }
2608
2609     *content_type = value[0];
2610
2611     for (i = 1; i < cf->args->nelts; i++) {
2612
2613         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
2614
2615         type = lcf->types->elts;
2616         for (n = 0; n < lcf->types->nelts; n++) {
2617             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
2618                 old = type[n].value;
2619                 type[n].value = content_type;
2620
2621                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2622                                    "duplicate extention \"%V\", "
2623                                    "content type: \"%V\", "
2624                                    "old content type: \"%V\"",
2625                                    &value[i], content_type, old);
2626                 continue;
2627             }
2628         }
2629
2630
2631         type = ngx_array_push(lcf->types);
2632         if (type == NULL) {
2633             return NGX_CONF_ERROR;
2634         }
2635
2636         type->key = value[i];
2637         type->key_hash = hash;
2638         type->value = content_type;
2639     }
2640
2641     return NGX_CONF_OK;
2642 }
2643
2644
2645 static ngx_int_t
2646 ngx_http_core_preconfiguration(ngx_conf_t *cf)
2647 {
2648     return ngx_http_variables_add_core_vars(cf);
2649 }
2650
2651
2652 static void *
2653 ngx_http_core_create_main_conf(ngx_conf_t *cf)
2654 {
2655     ngx_http_core_main_conf_t  *cmcf;
2656
2657     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
2658     if (cmcf == NULL) {
2659         return NGX_CONF_ERROR;
2660     }
2661
2662     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
2663                        sizeof(ngx_http_core_srv_conf_t *))
2664         != NGX_OK)
2665     {
2666         return NGX_CONF_ERROR;
2667     }
2668
2669     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
2670     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
2671
2672     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
2673     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
2674
2675     return cmcf;
2676 }
2677
2678
2679 static char *
2680 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
2681 {
2682     ngx_http_core_main_conf_t *cmcf = conf;
2683
2684     if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
2685         cmcf->server_names_hash_max_size = 512;
2686     }
2687
2688     if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2689         cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
2690     }
2691
2692     cmcf->server_names_hash_bucket_size =
2693             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
2694
2695
2696     if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
2697         cmcf->variables_hash_max_size = 512;
2698     }
2699
2700     if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2701         cmcf->variables_hash_bucket_size = 64;
2702     }
2703
2704     cmcf->variables_hash_bucket_size =
2705                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
2706
2707     return NGX_CONF_OK;
2708 }
2709
2710
2711 static void *
2712 ngx_http_core_create_srv_conf(ngx_conf_t *cf)
2713 {
2714     ngx_http_core_srv_conf_t  *cscf;
2715
2716     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
2717     if (cscf == NULL) {
2718         return NGX_CONF_ERROR;
2719     }
2720
2721     /*
2722      * set by ngx_pcalloc():
2723      *
2724      *     conf->client_large_buffers.num = 0;
2725      */
2726
2727     if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t))
2728         == NGX_ERROR)
2729     {
2730         return NGX_CONF_ERROR;
2731     }
2732
2733     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
2734                        sizeof(ngx_http_server_name_t))
2735         == NGX_ERROR)
2736     {
2737         return NGX_CONF_ERROR;
2738     }
2739
2740     cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
2741     cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
2742     cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
2743     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
2744     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
2745     cscf->merge_slashes = NGX_CONF_UNSET;
2746     cscf->underscores_in_headers = NGX_CONF_UNSET;
2747
2748     return cscf;
2749 }
2750
2751
2752 static char *
2753 ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
2754 {
2755     ngx_http_core_srv_conf_t *prev = parent;
2756     ngx_http_core_srv_conf_t *conf = child;
2757
2758     ngx_http_listen_t       *ls;
2759     ngx_http_server_name_t  *sn;
2760
2761     /* TODO: it does not merge, it inits only */
2762
2763     if (conf->listen.nelts == 0) {
2764         ls = ngx_array_push(&conf->listen);
2765         if (ls == NULL) {
2766             return NGX_CONF_ERROR;
2767         }
2768
2769         ngx_memzero(ls, sizeof(ngx_http_listen_t));
2770
2771         ls->addr = INADDR_ANY;
2772 #if (NGX_WIN32)
2773         ls->port = 80;
2774 #else
2775         /* STUB: getuid() should be cached */
2776         ls->port = (getuid() == 0) ? 80 : 8000;
2777 #endif
2778         ls->family = AF_INET;
2779
2780         ls->conf.backlog = NGX_LISTEN_BACKLOG;
2781         ls->conf.rcvbuf = -1;
2782         ls->conf.sndbuf = -1;
2783     }
2784
2785     if (conf->server_name.data == NULL) {
2786         conf->server_name = cf->cycle->hostname;
2787
2788         sn = ngx_array_push(&conf->server_names);
2789         if (sn == NULL) {
2790             return NGX_CONF_ERROR;
2791         }
2792
2793 #if (NGX_PCRE)
2794         sn->regex = NULL;
2795 #endif
2796         sn->core_srv_conf = conf;
2797         sn->name.len = conf->server_name.len;
2798         sn->name.data = conf->server_name.data;
2799     }
2800
2801     ngx_conf_merge_size_value(conf->connection_pool_size,
2802                               prev->connection_pool_size, 256);
2803     ngx_conf_merge_size_value(conf->request_pool_size,
2804                               prev->request_pool_size, 4096);
2805     ngx_conf_merge_msec_value(conf->client_header_timeout,
2806                               prev->client_header_timeout, 60000);
2807     ngx_conf_merge_size_value(conf->client_header_buffer_size,
2808                               prev->client_header_buffer_size, 1024);
2809     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
2810                               prev->large_client_header_buffers,
2811                               4, ngx_pagesize);
2812
2813     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
2814         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2815                            "the \"large_client_header_buffers\" size must be "
2816                            "equal to or bigger than \"connection_pool_size\"");
2817         return NGX_CONF_ERROR;
2818     }
2819
2820     ngx_conf_merge_value(conf->ignore_invalid_headers,
2821                               prev->ignore_invalid_headers, 1);
2822
2823     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
2824
2825     ngx_conf_merge_value(conf->underscores_in_headers,
2826                               prev->underscores_in_headers, 0);
2827
2828     return NGX_CONF_OK;
2829 }
2830
2831
2832 static void *
2833 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
2834 {
2835     ngx_http_core_loc_conf_t  *lcf;
2836
2837     lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
2838     if (lcf == NULL) {
2839         return NGX_CONF_ERROR;
2840     }
2841
2842     /*
2843      * set by ngx_pcalloc():
2844      *
2845      *     lcf->root = { 0, NULL };
2846      *     lcf->limit_except = 0;
2847      *     lcf->post_action = { 0, NULL };
2848      *     lcf->types = NULL;
2849      *     lcf->default_type = { 0, NULL };
2850      *     lcf->err_log = NULL;
2851      *     lcf->error_pages = NULL;
2852      *     lcf->try_files = NULL;
2853      *     lcf->client_body_path = NULL;
2854      *     lcf->regex = NULL;
2855      *     lcf->exact_match = 0;
2856      *     lcf->auto_redirect = 0;
2857      *     lcf->alias = 0;
2858      *     lcf->gzip_proxied = 0;
2859      */
2860
2861     lcf->client_max_body_size = NGX_CONF_UNSET;
2862     lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
2863     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
2864     lcf->satisfy = NGX_CONF_UNSET_UINT;
2865     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
2866     lcf->internal = NGX_CONF_UNSET;
2867     lcf->client_body_in_file_only = NGX_CONF_UNSET;
2868     lcf->sendfile = NGX_CONF_UNSET;
2869     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
2870     lcf->directio = NGX_CONF_UNSET;
2871     lcf->tcp_nopush = NGX_CONF_UNSET;
2872     lcf->tcp_nodelay = NGX_CONF_UNSET;
2873     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
2874     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
2875     lcf->postpone_output = NGX_CONF_UNSET_SIZE;
2876     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
2877     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
2878     lcf->keepalive_header = NGX_CONF_UNSET;
2879     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
2880     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
2881     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
2882     lcf->reset_timedout_connection = NGX_CONF_UNSET;
2883     lcf->server_name_in_redirect = NGX_CONF_UNSET;
2884     lcf->port_in_redirect = NGX_CONF_UNSET;
2885     lcf->msie_padding = NGX_CONF_UNSET;
2886     lcf->msie_refresh = NGX_CONF_UNSET;
2887     lcf->log_not_found = NGX_CONF_UNSET;
2888     lcf->log_subrequest = NGX_CONF_UNSET;
2889     lcf->recursive_error_pages = NGX_CONF_UNSET;
2890     lcf->server_tokens = NGX_CONF_UNSET;
2891     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
2892     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
2893
2894     lcf->open_file_cache = NGX_CONF_UNSET_PTR;
2895     lcf->open_file_cache_valid = NGX_CONF_UNSET;
2896     lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
2897     lcf->open_file_cache_errors = NGX_CONF_UNSET;
2898     lcf->open_file_cache_events = NGX_CONF_UNSET;
2899
2900 #if (NGX_HTTP_GZIP)
2901     lcf->gzip_vary = NGX_CONF_UNSET;
2902     lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
2903 #if (NGX_PCRE)
2904     lcf->gzip_disable = NGX_CONF_UNSET_PTR;
2905     lcf->gzip_disable_msie6 = 3;
2906 #endif
2907 #endif
2908
2909     return lcf;
2910 }
2911
2912
2913 static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
2914 static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
2915 static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
2916
2917 static ngx_hash_key_t  ngx_http_core_default_types[] = {
2918     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
2919     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
2920     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
2921     { ngx_null_string, 0, NULL }
2922 };
2923
2924
2925 static char *
2926 ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2927 {
2928     ngx_http_core_loc_conf_t *prev = parent;
2929     ngx_http_core_loc_conf_t *conf = child;
2930
2931     ngx_uint_t        i;
2932     ngx_hash_key_t   *type;
2933     ngx_hash_init_t   types_hash;
2934
2935     if (conf->root.data == NULL) {
2936
2937         conf->alias = prev->alias;
2938         conf->root = prev->root;
2939         conf->root_lengths = prev->root_lengths;
2940         conf->root_values = prev->root_values;
2941
2942         if (prev->root.data == NULL) {
2943             conf->root.len = sizeof("html") - 1;
2944             conf->root.data = (u_char *) "html";
2945
2946             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) {
2947                 return NGX_CONF_ERROR;
2948             }
2949         }
2950     }
2951
2952     if (conf->post_action.data == NULL) {
2953         conf->post_action = prev->post_action;
2954     }
2955
2956     ngx_conf_merge_uint_value(conf->types_hash_max_size,
2957                               prev->types_hash_max_size, 1024);
2958
2959     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
2960                               prev->types_hash_bucket_size,
2961                               ngx_cacheline_size);
2962
2963     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
2964                                              ngx_cacheline_size);
2965
2966     /*
2967      * the special handling the "types" directive in the "http" section
2968      * to inherit the http's conf->types_hash to all servers
2969      */
2970
2971     if (prev->types && prev->types_hash.buckets == NULL) {
2972
2973         types_hash.hash = &prev->types_hash;
2974         types_hash.key = ngx_hash_key_lc;
2975         types_hash.max_size = conf->types_hash_max_size;
2976         types_hash.bucket_size = conf->types_hash_bucket_size;
2977         types_hash.name = "types_hash";
2978         types_hash.pool = cf->pool;
2979         types_hash.temp_pool = NULL;
2980
2981         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
2982             != NGX_OK)
2983         {
2984             return NGX_CONF_ERROR;
2985         }
2986     }
2987
2988     if (conf->types == NULL) {
2989         conf->types = prev->types;
2990         conf->types_hash = prev->types_hash;
2991     }
2992
2993     if (conf->types == NULL) {
2994         conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
2995         if (conf->types == NULL) {
2996             return NGX_CONF_ERROR;
2997         }
2998
2999         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
3000             type = ngx_array_push(conf->types);
3001             if (type == NULL) {
3002                 return NGX_CONF_ERROR;
3003             }
3004
3005             type->key = ngx_http_core_default_types[i].key;
3006             type->key_hash =
3007                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3008                                        ngx_http_core_default_types[i].key.len);
3009             type->value = ngx_http_core_default_types[i].value;
3010         }
3011     }
3012
3013     if (conf->types_hash.buckets == NULL) {
3014
3015         types_hash.hash = &conf->types_hash;
3016         types_hash.key = ngx_hash_key_lc;
3017         types_hash.max_size = conf->types_hash_max_size;
3018         types_hash.bucket_size = conf->types_hash_bucket_size;
3019         types_hash.name = "mime_types_hash";
3020         types_hash.pool = cf->pool;
3021         types_hash.temp_pool = NULL;
3022
3023         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3024             != NGX_OK)
3025         {
3026             return NGX_CONF_ERROR;
3027         }
3028     }
3029
3030     if (conf->err_log == NULL) {
3031         if (prev->err_log) {
3032             conf->err_log = prev->err_log;
3033         } else {
3034             conf->err_log = cf->cycle->new_log;
3035         }
3036     }
3037
3038     if (conf->error_pages == NULL && prev->error_pages) {
3039         conf->error_pages = prev->error_pages;
3040     }
3041
3042     ngx_conf_merge_str_value(conf->default_type,
3043                               prev->default_type, "text/plain");
3044
3045     ngx_conf_merge_off_value(conf->client_max_body_size,
3046                               prev->client_max_body_size, 1 * 1024 * 1024);
3047     ngx_conf_merge_size_value(conf->client_body_buffer_size,
3048                               prev->client_body_buffer_size,
3049                               (size_t) 2 * ngx_pagesize);
3050     ngx_conf_merge_msec_value(conf->client_body_timeout,
3051                               prev->client_body_timeout, 60000);
3052
3053     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3054                               NGX_HTTP_SATISFY_ALL);
3055     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3056                               NGX_HTTP_IMS_EXACT);
3057     ngx_conf_merge_value(conf->internal, prev->internal, 0);
3058     ngx_conf_merge_value(conf->client_body_in_file_only,
3059                               prev->client_body_in_file_only, 0);
3060     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3061     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3062                               prev->sendfile_max_chunk, 0);
3063     ngx_conf_merge_off_value(conf->directio, prev->directio,
3064                               NGX_MAX_OFF_T_VALUE);
3065     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3066     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3067
3068     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3069     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3070     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3071                               1460);
3072     ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3073     ngx_conf_merge_msec_value(conf->keepalive_timeout,
3074                               prev->keepalive_timeout, 75000);
3075     ngx_conf_merge_sec_value(conf->keepalive_header,
3076                               prev->keepalive_header, 0);
3077     ngx_conf_merge_msec_value(conf->lingering_time,
3078                               prev->lingering_time, 30000);
3079     ngx_conf_merge_msec_value(conf->lingering_timeout,
3080                               prev->lingering_timeout, 5000);
3081     ngx_conf_merge_msec_value(conf->resolver_timeout,
3082                               prev->resolver_timeout, 30000);
3083
3084     if (conf->resolver == NULL) {
3085
3086         if (prev->resolver == NULL) {
3087
3088             /*
3089              * create dummy resolver in http {} context
3090              * to inherit it in all servers
3091              */
3092
3093             prev->resolver = ngx_resolver_create(cf, NULL);
3094             if (prev->resolver == NULL) {
3095                 return NGX_CONF_ERROR;
3096             }
3097         }
3098
3099         conf->resolver = prev->resolver;
3100     }
3101
3102     ngx_conf_merge_path_value(conf->client_body_temp_path,
3103                               prev->client_body_temp_path,
3104                               NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
3105                               ngx_garbage_collector_temp_handler, cf);
3106
3107     ngx_conf_merge_value(conf->reset_timedout_connection,
3108                               prev->reset_timedout_connection, 0);
3109     ngx_conf_merge_value(conf->server_name_in_redirect,
3110                               prev->server_name_in_redirect, 1);
3111     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3112     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3113     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3114     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3115     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3116     ngx_conf_merge_value(conf->recursive_error_pages,
3117                               prev->recursive_error_pages, 0);
3118     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
3119
3120     ngx_conf_merge_ptr_value(conf->open_file_cache,
3121                               prev->open_file_cache, NULL);
3122
3123     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3124                               prev->open_file_cache_valid, 60);
3125
3126     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3127                               prev->open_file_cache_min_uses, 1);
3128
3129     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3130                               prev->open_file_cache_errors, 0);
3131
3132     ngx_conf_merge_sec_value(conf->open_file_cache_events,
3133                               prev->open_file_cache_events, 0);
3134 #if (NGX_HTTP_GZIP)
3135
3136     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3137     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3138                               NGX_HTTP_VERSION_11);
3139     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3140                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3141
3142 #if (NGX_PCRE)
3143     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3144 #endif
3145
3146     if (conf->gzip_disable_msie6 == 3) {
3147         conf->gzip_disable_msie6 =
3148             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3149     }
3150
3151 #endif
3152
3153     return NGX_CONF_OK;
3154 }
3155
3156
3157 /* AF_INET only */
3158
3159 static char *
3160 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3161 {
3162     ngx_http_core_srv_conf_t *scf = conf;
3163
3164     ngx_str_t          *value, size;
3165     ngx_url_t           u;
3166     ngx_uint_t          n;
3167     ngx_http_listen_t  *ls;
3168
3169     /*
3170      * TODO: check duplicate 'listen' directives,
3171      *       add resolved name to server names ???
3172      */
3173
3174     value = cf->args->elts;
3175
3176     ngx_memzero(&u, sizeof(ngx_url_t));
3177
3178     u.url = value[1];
3179     u.listen = 1;
3180     u.default_port = 80;
3181
3182     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3183         if (u.err) {
3184             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3185                                "%s in \"%V\" of the \"listen\" directive",
3186                                u.err, &u.url);
3187         }
3188
3189         return NGX_CONF_ERROR;
3190     }
3191
3192     ls = ngx_array_push(&scf->listen);
3193     if (ls == NULL) {
3194         return NGX_CONF_ERROR;
3195     }
3196
3197     ngx_memzero(ls, sizeof(ngx_http_listen_t));
3198
3199     ls->family = u.family;
3200     ls->addr = u.addr.in_addr;
3201     ls->port = u.port;
3202     ls->file_name = cf->conf_file->file.name.data;
3203     ls->line = cf->conf_file->line;
3204     ls->conf.backlog = NGX_LISTEN_BACKLOG;
3205     ls->conf.rcvbuf = -1;
3206     ls->conf.sndbuf = -1;
3207
3208     n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, NGX_INET_ADDRSTRLEN);
3209     ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port);
3210
3211     if (cf->args->nelts == 2) {
3212         return NGX_CONF_OK;
3213     }
3214
3215     if (ngx_strcmp(value[2].data, "default") == 0) {
3216         ls->conf.default_server = 1;
3217         n = 3;
3218
3219     } else {
3220         n = 2;
3221     }
3222
3223     for ( /* void */ ; n < cf->args->nelts; n++) {
3224
3225         if (ls->conf.default_server == 0) {
3226             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3227                                "\"%V\" parameter can be specified for "
3228                                "the default \"listen\" directive only",
3229                                &value[n]);
3230             return NGX_CONF_ERROR;
3231         }
3232
3233         if (ngx_strcmp(value[n].data, "bind") == 0) {
3234             ls->conf.bind = 1;
3235             continue;
3236         }
3237
3238         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
3239             ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
3240             ls->conf.bind = 1;
3241
3242             if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
3243                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3244                                    "invalid backlog \"%V\"", &value[n]);
3245                 return NGX_CONF_ERROR;
3246             }
3247
3248             continue;
3249         }
3250
3251         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
3252             size.len = value[n].len - 7;
3253             size.data = value[n].data + 7;
3254
3255             ls->conf.rcvbuf = ngx_parse_size(&size);
3256             ls->conf.bind = 1;
3257
3258             if (ls->conf.rcvbuf == NGX_ERROR) {
3259                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3260                                    "invalid rcvbuf \"%V\"", &value[n]);
3261                 return NGX_CONF_ERROR;
3262             }
3263
3264             continue;
3265         }
3266
3267         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
3268             size.len = value[n].len - 7;
3269             size.data = value[n].data + 7;
3270
3271             ls->conf.sndbuf = ngx_parse_size(&size);
3272             ls->conf.bind = 1;
3273
3274             if (ls->conf.sndbuf == NGX_ERROR) {
3275                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3276                                    "invalid sndbuf \"%V\"", &value[n]);
3277                 return NGX_CONF_ERROR;
3278             }
3279
3280             continue;
3281         }
3282
3283         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
3284 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
3285             ls->conf.accept_filter = (char *) &value[n].data[14];
3286             ls->conf.bind = 1;
3287 #else
3288             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3289                                "accept filters \"%V\" are not supported "
3290                                "on this platform, ignored",
3291                                &value[n]);
3292 #endif
3293             continue;
3294         }
3295
3296         if (ngx_strcmp(value[n].data, "deferred") == 0) {
3297 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
3298             ls->conf.deferred_accept = 1;
3299             ls->conf.bind = 1;
3300 #else
3301             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3302                                "the deferred accept is not supported "
3303                                "on this platform, ignored");
3304 #endif
3305             continue;
3306         }
3307
3308         if (ngx_strcmp(value[n].data, "ssl") == 0) {
3309 #if (NGX_HTTP_SSL)
3310             ls->conf.ssl = 1;
3311             continue;
3312 #else
3313             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3314                                "the \"ssl\" parameter requires "
3315                                "ngx_http_ssl_module");
3316             return NGX_CONF_ERROR;
3317 #endif
3318         }
3319
3320         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3321                            "the invalid \"%V\" parameter", &value[n]);
3322         return NGX_CONF_ERROR;
3323     }
3324
3325     return NGX_CONF_OK;
3326 }
3327
3328
3329 static char *
3330 ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3331 {
3332     ngx_http_core_srv_conf_t *cscf = conf;
3333
3334     u_char                   ch;
3335     ngx_str_t               *value, name;
3336     ngx_uint_t               i;
3337     ngx_http_server_name_t  *sn;
3338
3339     value = cf->args->elts;
3340
3341     ch = value[1].data[0];
3342
3343     if (cscf->server_name.data == NULL) {
3344         if (value[1].len) {
3345             name = value[1];
3346
3347             if (ch == '.') {
3348                 name.len--;
3349                 name.data++;
3350             }
3351
3352             cscf->server_name.len = name.len;
3353             cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
3354             if (cscf->server_name.data == NULL) {
3355                 return NGX_CONF_ERROR;
3356             }
3357
3358         } else {
3359             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3360                                "the first server name must not be empty");
3361             return NGX_CONF_ERROR;
3362         }
3363     }
3364
3365     for (i = 1; i < cf->args->nelts; i++) {
3366
3367         ch = value[i].data[0];
3368
3369         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
3370             || (ch == '.' && value[i].len < 2))
3371         {
3372             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3373                                "server name \"%V\" is invalid", &value[i]);
3374             return NGX_CONF_ERROR;
3375         }
3376
3377         if (ngx_strchr(value[i].data, '/')) {
3378             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3379                                "server name \"%V\" has strange symbols",
3380                                &value[i]);
3381         }
3382
3383         if (value[i].len == 1 && ch == '*') {
3384             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3385                                "\"server_name *\" is unsupported, use "
3386                                "\"server_name_in_redirect off\" instead");
3387             return NGX_CONF_ERROR;
3388         }
3389
3390         sn = ngx_array_push(&cscf->server_names);
3391         if (sn == NULL) {
3392             return NGX_CONF_ERROR;
3393         }
3394
3395 #if (NGX_PCRE)
3396         sn->regex = NULL;
3397 #endif
3398         sn->core_srv_conf = cscf;
3399         sn->name = value[i];
3400
3401         if (value[i].data[0] != '~') {
3402             continue;
3403         }
3404
3405 #if (NGX_PCRE)
3406         {
3407         ngx_str_t  err;
3408         u_char     errstr[NGX_MAX_CONF_ERRSTR];
3409
3410         err.len = NGX_MAX_CONF_ERRSTR;
3411         err.data = errstr;
3412
3413         value[i].len--;
3414         value[i].data++;
3415
3416         sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
3417
3418         if (sn->regex == NULL) {
3419             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
3420             return NGX_CONF_ERROR;
3421         }
3422
3423         sn->name = value[i];
3424         }
3425 #else
3426         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3427                            "the using of the regex \"%V\" "
3428                            "requires PCRE library", &value[i]);
3429
3430         return NGX_CONF_ERROR;
3431 #endif
3432     }
3433
3434     return NGX_CONF_OK;
3435 }
3436
3437
3438 static char *
3439 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3440 {
3441     ngx_http_core_loc_conf_t *lcf = conf;
3442
3443     ngx_str_t                  *value;
3444     ngx_uint_t                  alias, n;
3445     ngx_http_script_compile_t   sc;
3446
3447     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
3448
3449     if (lcf->root.data) {
3450
3451         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
3452
3453         if ((ngx_uint_t) lcf->alias == alias) {
3454             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3455                                "\"%V\" directive is duplicate",
3456                                &cmd->name);
3457         } else {
3458             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3459                                "\"%V\" directive is duplicate, "
3460                                "\"%s\" directive is specified before",
3461                                &cmd->name, lcf->alias ? "alias" : "root");
3462         }
3463
3464         return NGX_CONF_ERROR;
3465     }
3466
3467     if (lcf->named && alias) {
3468         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3469                            "the \"alias\" directive may not be used "
3470                            "inside named location");
3471
3472         return NGX_CONF_ERROR;
3473     }
3474
3475 #if (NGX_PCRE)
3476
3477     if (lcf->regex && alias) {
3478         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3479                            "the \"alias\" directive may not be used "
3480                            "inside location given by regular expression");
3481
3482         return NGX_CONF_ERROR;
3483     }
3484
3485 #endif
3486
3487     value = cf->args->elts;
3488
3489     if (ngx_strstr(value[1].data, "$document_root")
3490         || ngx_strstr(value[1].data, "${document_root}"))
3491     {
3492         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3493                            "the $document_root variable may not be used "
3494                            "in the \"%V\" directive",
3495                            &cmd->name);
3496
3497         return NGX_CONF_ERROR;
3498     }
3499
3500     if (ngx_strstr(value[1].data, "$realpath_root")
3501         || ngx_strstr(value[1].data, "${realpath_root}"))
3502     {
3503         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3504                            "the $realpath_root variable may not be used "
3505                            "in the \"%V\" directive",
3506                            &cmd->name);
3507
3508         return NGX_CONF_ERROR;
3509     }
3510
3511     lcf->alias = alias;
3512     lcf->root = value[1];
3513
3514     if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
3515         lcf->root.len--;
3516     }
3517
3518     if (lcf->root.data[0] != '$') {
3519         if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) {
3520             return NGX_CONF_ERROR;
3521         }
3522     }
3523
3524     n = ngx_http_script_variables_count(&lcf->root);
3525
3526     if (n == 0) {
3527         return NGX_CONF_OK;
3528     }
3529
3530     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3531
3532     sc.cf = cf;
3533     sc.source = &lcf->root;
3534     sc.lengths = &lcf->root_lengths;
3535     sc.values = &lcf->root_values;
3536     sc.variables = n;
3537     sc.complete_lengths = 1;
3538     sc.complete_values = 1;
3539
3540     if (ngx_http_script_compile(&sc) != NGX_OK) {
3541         return NGX_CONF_ERROR;
3542     }
3543
3544     return NGX_CONF_OK;
3545 }
3546
3547
3548 static ngx_http_method_name_t  ngx_methods_names[] = {
3549    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
3550    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
3551    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
3552    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
3553    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
3554    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
3555    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
3556    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
3557    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
3558    { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
3559    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
3560    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
3561    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
3562    { NULL, 0 }
3563 };
3564
3565
3566 static char *
3567 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3568 {
3569     ngx_http_core_loc_conf_t *pclcf = conf;
3570
3571     char                      *rv;
3572     void                      *mconf;
3573     ngx_str_t                 *value;
3574     ngx_uint_t                 i;
3575     ngx_conf_t                 save;
3576     ngx_http_module_t         *module;
3577     ngx_http_conf_ctx_t       *ctx, *pctx;
3578     ngx_http_method_name_t    *name;
3579     ngx_http_core_loc_conf_t  *clcf;
3580
3581     if (pclcf->limit_except) {
3582         return "duplicate";
3583     }
3584
3585     pclcf->limit_except = 0xffffffff;
3586
3587     value = cf->args->elts;
3588
3589     for (i = 1; i < cf->args->nelts; i++) {
3590         for (name = ngx_methods_names; name->name; name++) {
3591
3592             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
3593                 pclcf->limit_except &= name->method;
3594                 goto next;
3595             }
3596         }
3597
3598         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3599                            "invalid method \"%V\"", &value[i]);
3600         return NGX_CONF_ERROR;
3601
3602     next:
3603         continue;
3604     }
3605
3606     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
3607         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
3608     }
3609
3610     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3611     if (ctx == NULL) {
3612         return NGX_CONF_ERROR;
3613     }
3614
3615     pctx = cf->ctx;
3616     ctx->main_conf = pctx->main_conf;
3617     ctx->srv_conf = pctx->srv_conf;
3618
3619     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
3620     if (ctx->loc_conf == NULL) {
3621         return NGX_CONF_ERROR;
3622     }
3623
3624     for (i = 0; ngx_modules[i]; i++) {
3625         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
3626             continue;
3627         }
3628
3629         module = ngx_modules[i]->ctx;
3630
3631         if (module->create_loc_conf) {
3632
3633             mconf = module->create_loc_conf(cf);
3634             if (mconf == NULL) {
3635                  return NGX_CONF_ERROR;
3636             }
3637
3638             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
3639         }
3640     }
3641
3642
3643     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
3644     pclcf->limit_except_loc_conf = ctx->loc_conf;
3645     clcf->loc_conf = ctx->loc_conf;
3646     clcf->name = pclcf->name;
3647     clcf->noname = 1;
3648
3649     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
3650         return NGX_CONF_ERROR;
3651     }
3652
3653     save = *cf;
3654     cf->ctx = ctx;
3655     cf->cmd_type = NGX_HTTP_LMT_CONF;
3656
3657     rv = ngx_conf_parse(cf, NULL);
3658
3659     *cf = save;
3660
3661     return rv;
3662 }
3663
3664
3665 static char *
3666 ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3667 {
3668     ngx_http_core_loc_conf_t *clcf = conf;
3669
3670     ngx_str_t  *value;
3671
3672     if (clcf->directio != NGX_CONF_UNSET) {
3673         return "is duplicate";
3674     }
3675
3676     value = cf->args->elts;
3677
3678     if (ngx_strcmp(value[1].data, "off") == 0) {
3679         clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
3680         return NGX_CONF_OK;
3681     }
3682
3683     clcf->directio = ngx_parse_offset(&value[1]);
3684     if (clcf->directio == (off_t) NGX_ERROR) {
3685         return "invalid value";
3686     }
3687
3688     return NGX_CONF_OK;
3689 }
3690
3691
3692 static char *
3693 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3694 {
3695     ngx_http_core_loc_conf_t *lcf = conf;
3696
3697     u_char                     *args;
3698     ngx_int_t                   overwrite;
3699     ngx_str_t                  *value, uri;
3700     ngx_uint_t                  i, n, nvar;
3701     ngx_array_t                *uri_lengths, *uri_values;
3702     ngx_http_err_page_t        *err;
3703     ngx_http_script_compile_t   sc;
3704
3705     if (lcf->error_pages == NULL) {
3706         lcf->error_pages = ngx_array_create(cf->pool, 4,
3707                                             sizeof(ngx_http_err_page_t));
3708         if (lcf->error_pages == NULL) {
3709             return NGX_CONF_ERROR;
3710         }
3711     }
3712
3713     value = cf->args->elts;
3714
3715     i = cf->args->nelts - 2;
3716
3717     if (value[i].data[0] == '=') {
3718         if (i == 1) {
3719             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3720                                "invalid value \"%V\"", &value[i]);
3721             return NGX_CONF_ERROR;
3722         }
3723
3724         if (value[i].len > 1) {
3725             overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
3726
3727             if (overwrite == NGX_ERROR) {
3728                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3729                                    "invalid value \"%V\"", &value[i]);
3730                 return NGX_CONF_ERROR;
3731             }
3732
3733         } else {
3734             overwrite = 0;
3735         }
3736
3737         n = 2;
3738
3739     } else {
3740         overwrite = -1;
3741         n = 1;
3742     }
3743
3744     uri = value[cf->args->nelts - 1];
3745     uri_lengths = NULL;
3746     uri_values = NULL;
3747
3748     nvar = ngx_http_script_variables_count(&uri);
3749
3750     if (nvar) {
3751         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3752
3753         sc.cf = cf;
3754         sc.source = &uri;
3755         sc.lengths = &uri_lengths;
3756         sc.values = &uri_values;
3757         sc.variables = nvar;
3758         sc.complete_lengths = 1;
3759         sc.complete_values = 1;
3760
3761         if (ngx_http_script_compile(&sc) != NGX_OK) {
3762             return NGX_CONF_ERROR;
3763         }
3764     }
3765
3766     args = (u_char *) ngx_strchr(uri.data, '?');
3767
3768     for (i = 1; i < cf->args->nelts - n; i++) {
3769         err = ngx_array_push(lcf->error_pages);
3770         if (err == NULL) {
3771             return NGX_CONF_ERROR;
3772         }
3773
3774         err->status = ngx_atoi(value[i].data, value[i].len);
3775
3776         if (err->status == NGX_ERROR || err->status == 499) {
3777             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3778                                "invalid value \"%V\"", &value[i]);
3779             return NGX_CONF_ERROR;
3780         }
3781
3782         if (err->status < 400 || err->status > 599) {
3783             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3784                                "value \"%V\" must be between 400 and 599",
3785                                &value[i]);
3786             return NGX_CONF_ERROR;
3787         }
3788
3789         if (overwrite >= 0) {
3790             err->overwrite = overwrite;
3791
3792         } else {
3793             switch (err->status) {
3794                 case NGX_HTTP_TO_HTTPS:
3795                 case NGX_HTTPS_CERT_ERROR:
3796                 case NGX_HTTPS_NO_CERT:
3797                     err->overwrite = NGX_HTTP_BAD_REQUEST;
3798                     break;
3799
3800                 default:
3801                     err->overwrite = err->status;
3802                     break;
3803             }
3804         }
3805
3806         if (args) {
3807             err->uri.len = args - uri.data;
3808             err->uri.data = uri.data;
3809             args++;
3810             err->args.len = (uri.data + uri.len) - args;
3811             err->args.data = args;
3812
3813         } else {
3814             err->uri = uri;
3815             err->args.len = 0;
3816             err->args.data = NULL;
3817         }
3818
3819         err->uri_lengths = uri_lengths;
3820         err->uri_values = uri_values;
3821     }
3822
3823     return NGX_CONF_OK;
3824 }
3825
3826
3827 static char *
3828 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3829 {
3830     ngx_http_core_loc_conf_t *clcf = conf;
3831
3832     ngx_str_t                  *value;
3833     ngx_uint_t                  i, n;
3834     ngx_http_try_file_t        *tf;
3835     ngx_http_script_compile_t   sc;
3836     ngx_http_core_main_conf_t  *cmcf;
3837
3838     if (clcf->try_files) {
3839         return "is duplicate";
3840     }
3841
3842     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
3843
3844     cmcf->try_files = 1;
3845
3846     tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
3847     if (tf == NULL) {
3848         return NGX_CONF_ERROR;
3849     }
3850
3851     clcf->try_files = tf;
3852
3853     value = cf->args->elts;
3854
3855     for (i = 0; i < cf->args->nelts - 1; i++) {
3856
3857         tf[i].name = value[i + 1];
3858
3859         if (tf[i].name.data[tf[i].name.len - 1] == '/') {
3860             tf[i].test_dir = 1;
3861             tf[i].name.len--;
3862         }
3863
3864         n = ngx_http_script_variables_count(&tf[i].name);
3865
3866         if (n) {
3867             ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3868
3869             sc.cf = cf;
3870             sc.source = &tf[i].name;
3871             sc.lengths = &tf[i].lengths;
3872             sc.values = &tf[i].values;
3873             sc.variables = n;
3874             sc.complete_lengths = 1;
3875             sc.complete_values = 1;
3876
3877             if (ngx_http_script_compile(&sc) != NGX_OK) {
3878                 return NGX_CONF_ERROR;
3879             }
3880
3881         } else {
3882             /* add trailing '\0' to length */
3883             tf[i].name.len++;
3884         }
3885     }
3886
3887     return NGX_CONF_OK;
3888 }
3889
3890
3891 static char *
3892 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3893 {
3894     ngx_http_core_loc_conf_t *lcf = conf;
3895
3896     time_t       inactive;
3897     ngx_str_t   *value, s;
3898     ngx_int_t    max;
3899     ngx_uint_t   i;
3900
3901     if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) {
3902         return "is duplicate";
3903     }
3904
3905     value = cf->args->elts;
3906
3907     max = 0;
3908     inactive = 60;
3909
3910     for (i = 1; i < cf->args->nelts; i++) {
3911
3912         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
3913
3914             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
3915             if (max == NGX_ERROR) {
3916                 goto failed;
3917             }
3918
3919             continue;
3920         }
3921
3922         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
3923
3924             s.len = value[i].len - 9;
3925             s.data = value[i].data + 9;
3926
3927             inactive = ngx_parse_time(&s, 1);
3928             if (inactive < 0) {
3929                 goto failed;
3930             }
3931
3932             continue;
3933         }
3934
3935         if (ngx_strcmp(value[i].data, "off") == 0) {
3936
3937             lcf->open_file_cache = NULL;
3938
3939             continue;
3940         }
3941
3942     failed:
3943
3944         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3945                            "invalid \"open_file_cache\" parameter \"%V\"",
3946                            &value[i]);
3947         return NGX_CONF_ERROR;
3948     }
3949
3950     if (lcf->open_file_cache == NULL) {
3951         return NGX_CONF_OK;
3952     }
3953
3954     if (max == 0) {
3955         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3956                            "\"open_file_cache\" must have \"max\" parameter");
3957         return NGX_CONF_ERROR;
3958     }
3959
3960     lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
3961     if (lcf->open_file_cache) {
3962         return NGX_CONF_OK;
3963     }
3964
3965     return NGX_CONF_ERROR;
3966 }
3967
3968
3969 static char *
3970 ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3971 {
3972     ngx_http_core_loc_conf_t *lcf = conf;
3973
3974     lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
3975     if (lcf->err_log == NULL) {
3976         return NGX_CONF_ERROR;
3977     }
3978
3979     return ngx_set_error_log_levels(cf, lcf->err_log);
3980 }
3981
3982
3983 static char *
3984 ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3985 {
3986     ngx_http_core_loc_conf_t *lcf = conf;
3987
3988     ngx_str_t  *value;
3989
3990     if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
3991         return "is duplicate";
3992     }
3993
3994     value = cf->args->elts;
3995
3996     lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
3997
3998     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
3999         return "invalid value";
4000     }
4001
4002     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
4003         return "value must be less than 597 hours";
4004     }
4005
4006     if (cf->args->nelts == 2) {
4007         return NGX_CONF_OK;
4008     }
4009
4010     lcf->keepalive_header = ngx_parse_time(&value[2], 1);
4011
4012     if (lcf->keepalive_header == NGX_ERROR) {
4013         return "invalid value";
4014     }
4015
4016     if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
4017         return "value must be less than 68 years";
4018     }
4019
4020     return NGX_CONF_OK;
4021 }
4022
4023
4024 static char *
4025 ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4026 {
4027     ngx_http_core_loc_conf_t *lcf = conf;
4028
4029     if (lcf->internal != NGX_CONF_UNSET) {
4030         return "is duplicate";
4031     }
4032
4033     lcf->internal = 1;
4034
4035     return NGX_CONF_OK;
4036 }
4037
4038
4039 static char *
4040 ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4041 {
4042     ngx_http_core_loc_conf_t  *clcf = conf;
4043
4044     ngx_url_t   u;
4045     ngx_str_t  *value;
4046
4047     if (clcf->resolver) {
4048         return "is duplicate";
4049     }
4050
4051     value = cf->args->elts;
4052
4053     ngx_memzero(&u, sizeof(ngx_url_t));
4054
4055     u.host = value[1];
4056     u.port = 53;
4057
4058     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
4059         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
4060         return NGX_CONF_ERROR;
4061     }
4062
4063     clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
4064     if (clcf->resolver == NULL) {
4065         return NGX_OK;
4066     }
4067
4068     return NGX_CONF_OK;
4069 }
4070
4071
4072 #if (NGX_HTTP_GZIP)
4073
4074 static char *
4075 ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4076 {
4077     ngx_http_core_loc_conf_t  *clcf = conf;
4078
4079 #if (NGX_PCRE)
4080
4081     ngx_str_t         err, *value;
4082     ngx_uint_t        i;
4083     ngx_regex_elt_t  *re;
4084     u_char            errstr[NGX_MAX_CONF_ERRSTR];
4085
4086     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
4087         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
4088                                               sizeof(ngx_regex_elt_t));
4089         if (clcf->gzip_disable == NULL) {
4090             return NGX_CONF_ERROR;
4091         }
4092     }
4093
4094     value = cf->args->elts;
4095
4096     err.len = NGX_MAX_CONF_ERRSTR;
4097     err.data = errstr;
4098
4099     for (i = 1; i < cf->args->nelts; i++) {
4100
4101         if (ngx_strcmp(value[1].data, "msie6") == 0) {
4102             clcf->gzip_disable_msie6 = 1;
4103             continue;
4104         }
4105
4106         re = ngx_array_push(clcf->gzip_disable);
4107         if (re == NULL) {
4108             return NGX_CONF_ERROR;
4109         }
4110
4111         re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
4112                                       &err);
4113
4114         if (re->regex == NULL) {
4115             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
4116             return NGX_CONF_ERROR;
4117         }
4118
4119         re->name = value[i].data;
4120     }
4121
4122     return NGX_CONF_OK;
4123
4124 #else
4125     ngx_str_t  *value;
4126
4127     value = cf->args->elts;
4128
4129     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) {
4130         clcf->gzip_disable_msie6 = 1;
4131         return NGX_CONF_OK;
4132     }
4133
4134     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4135                        "without PCRE library \"gzip_disable\" supports "
4136                        "builtin \"msie6\" mask only");
4137
4138     return NGX_CONF_ERROR;
4139 #endif
4140 }
4141
4142 #endif
4143
4144
4145 static char *
4146 ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
4147 {
4148 #if (NGX_FREEBSD)
4149     ssize_t *np = data;
4150
4151     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
4152         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4153                            "\"send_lowat\" must be less than %d "
4154                            "(sysctl net.inet.tcp.sendspace)",
4155                            ngx_freebsd_net_inet_tcp_sendspace);
4156
4157         return NGX_CONF_ERROR;
4158     }
4159
4160 #elif !(NGX_HAVE_SO_SNDLOWAT)
4161     ssize_t *np = data;
4162
4163     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4164                        "\"send_lowat\" is not supported, ignored");
4165
4166     *np = 0;
4167
4168 #endif
4169
4170     return NGX_CONF_OK;
4171 }
4172
4173
4174 static char *
4175 ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
4176 {
4177     size_t *sp = data;
4178
4179     if (*sp < NGX_MIN_POOL_SIZE) {
4180         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4181                            "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
4182
4183         return NGX_CONF_ERROR;
4184     }
4185
4186     return NGX_CONF_OK;
4187 }