66698d5259922bb9dbd5d5553670bc2b0df0096d
[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         /* 16 bytes are preallocation */
1090         reserve = ngx_abs((ssize_t) (len - r->uri.len)) + alias + 16;
1091
1092         if (reserve > allocated) {
1093
1094             /* we just need to allocate path and to copy a root */
1095
1096             if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) {
1097                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1098                 return NGX_OK;
1099             }
1100
1101             name = path.data + root;
1102             allocated = path.len - root - (r->uri.len - alias);
1103          }
1104
1105         if (tf->values == NULL) {
1106
1107             /* tf->name.len includes the terminating '\0' */
1108
1109             ngx_memcpy(name, tf->name.data, tf->name.len);
1110
1111             path.len = (name + tf->name.len - 1) - path.data;
1112
1113         } else {
1114             e.ip = tf->values->elts;
1115             e.pos = name;
1116             e.flushed = 1;
1117
1118             while (*(uintptr_t *) e.ip) {
1119                 code = *(ngx_http_script_code_pt *) e.ip;
1120                 code((ngx_http_script_engine_t *) &e);
1121             }
1122
1123             path.len = e.pos - path.data;
1124
1125             *e.pos = '\0';
1126
1127             if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
1128                 ngx_memcpy(name, name + alias, len - alias);
1129                 path.len -= alias;
1130             }
1131         }
1132
1133         test_dir = tf->test_dir;
1134
1135         tf++;
1136
1137         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1138                        "try to use file: \"%s\"", name);
1139
1140         if (tf->lengths == NULL && tf->name.len == 0) {
1141
1142             path.len -= root;
1143             path.data += root;
1144
1145             if (path.data[0] == '@') {
1146                 (void) ngx_http_named_location(r, &path);
1147
1148             } else {
1149                 (void) ngx_http_internal_redirect(r, &path, NULL);
1150             }
1151
1152             return NGX_OK;
1153         }
1154
1155         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1156
1157         of.directio = clcf->directio;
1158         of.valid = clcf->open_file_cache_valid;
1159         of.min_uses = clcf->open_file_cache_min_uses;
1160         of.errors = clcf->open_file_cache_errors;
1161         of.events = clcf->open_file_cache_events;
1162
1163         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1164             != NGX_OK)
1165         {
1166             if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
1167                 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1168                               ngx_open_file_n " \"%s\" failed", path.data);
1169             }
1170
1171             continue;
1172         }
1173
1174         if (of.is_dir && !test_dir) {
1175             continue;
1176         }
1177
1178         path.len -= root;
1179         path.data += root;
1180
1181         if (!alias) {
1182             r->uri = path;
1183
1184         } else {
1185             r->uri.len = alias + path.len;
1186             r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1187             if (r->uri.data == NULL) {
1188                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1189                 return NGX_OK;
1190             }
1191
1192             p = ngx_copy(r->uri.data, clcf->name.data, alias);
1193             ngx_memcpy(p, name, path.len);
1194         }
1195
1196         if (ngx_http_set_exten(r) != NGX_OK) {
1197             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1198             return NGX_OK;
1199         }
1200
1201         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1202                        "try file uri: \"%V\"", &r->uri);
1203
1204         r->phase_handler++;
1205         return NGX_AGAIN;
1206     }
1207
1208     /* not reached */
1209 }
1210
1211
1212 ngx_int_t
1213 ngx_http_core_content_phase(ngx_http_request_t *r,
1214     ngx_http_phase_handler_t *ph)
1215 {
1216     size_t     root;
1217     ngx_int_t  rc;
1218     ngx_str_t  path;
1219
1220     if (r->content_handler) {
1221         r->write_event_handler = ngx_http_request_empty_handler;
1222         ngx_http_finalize_request(r, r->content_handler(r));
1223         return NGX_OK;
1224     }
1225
1226     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1227                    "content phase: %ui", r->phase_handler);
1228
1229     rc = ph->handler(r);
1230
1231     if (rc == NGX_DONE) {
1232         return NGX_OK;
1233     }
1234
1235     if (rc != NGX_DECLINED) {
1236         ngx_http_finalize_request(r, rc);
1237         return NGX_OK;
1238     }
1239
1240     /* rc == NGX_DECLINED */
1241
1242     ph++;
1243
1244     if (ph->checker) {
1245         r->phase_handler++;
1246         return NGX_AGAIN;
1247     }
1248
1249     /* no content handler was found */
1250
1251     if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
1252
1253         if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
1254             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1255                           "directory index of \"%s\" is forbidden", path.data);
1256         }
1257
1258         ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
1259         return NGX_OK;
1260     }
1261
1262     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
1263
1264     ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1265     return NGX_OK;
1266 }
1267
1268
1269 void
1270 ngx_http_update_location_config(ngx_http_request_t *r)
1271 {
1272     ngx_http_core_loc_conf_t  *clcf;
1273
1274     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1275
1276     if (r->method & clcf->limit_except) {
1277         r->loc_conf = clcf->limit_except_loc_conf;
1278         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1279     }
1280
1281     if (r == r->main) {
1282         r->connection->log->file = clcf->err_log->file;
1283
1284         if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1285             r->connection->log->log_level = clcf->err_log->log_level;
1286         }
1287     }
1288
1289     if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
1290         r->connection->sendfile = 1;
1291
1292     } else {
1293         r->connection->sendfile = 0;
1294     }
1295
1296     if (clcf->client_body_in_file_only) {
1297         r->request_body_in_file_only = 1;
1298         r->request_body_in_persistent_file = 1;
1299         r->request_body_in_clean_file =
1300             clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
1301         r->request_body_file_log_level = NGX_LOG_NOTICE;
1302
1303     } else {
1304         r->request_body_file_log_level = NGX_LOG_WARN;
1305     }
1306
1307     if (r->keepalive && clcf->keepalive_timeout == 0) {
1308         r->keepalive = 0;
1309     }
1310
1311     if (!clcf->tcp_nopush) {
1312         /* disable TCP_NOPUSH/TCP_CORK use */
1313         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
1314     }
1315
1316     if (r->limit_rate == 0) {
1317         r->limit_rate = clcf->limit_rate;
1318     }
1319
1320     if (clcf->handler) {
1321         r->content_handler = clcf->handler;
1322     }
1323 }
1324
1325
1326 /*
1327  * NGX_OK       - exact or regex match
1328  * NGX_DONE     - auto redirect
1329  * NGX_AGAIN    - inclusive match
1330  * NGX_ERROR    - regex error
1331  * NGX_DECLINED - no match
1332  */
1333
1334 static ngx_int_t
1335 ngx_http_core_find_location(ngx_http_request_t *r)
1336 {
1337     ngx_int_t                  rc;
1338     ngx_http_core_loc_conf_t  *pclcf;
1339 #if (NGX_PCRE)
1340     ngx_int_t                  n, len;
1341     ngx_uint_t                 noregex;
1342     ngx_http_core_loc_conf_t  *clcf, **clcfp;
1343
1344     noregex = 0;
1345 #endif
1346
1347     pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1348
1349     rc = ngx_http_core_find_static_location(r, pclcf->static_locations);
1350
1351     if (rc == NGX_AGAIN) {
1352
1353 #if (NGX_PCRE)
1354         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1355
1356         noregex = clcf->noregex;
1357 #endif
1358
1359         /* look up nested locations */
1360
1361         rc = ngx_http_core_find_location(r);
1362     }
1363
1364     if (rc == NGX_OK || rc == NGX_DONE) {
1365         return rc;
1366     }
1367
1368     /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */
1369
1370 #if (NGX_PCRE)
1371
1372     if (noregex == 0 && pclcf->regex_locations) {
1373
1374         len = 0;
1375
1376         for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
1377
1378             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1379                            "test location: ~ \"%V\"", &(*clcfp)->name);
1380
1381             if ((*clcfp)->captures) {
1382
1383                 len = (NGX_HTTP_MAX_CAPTURES + 1) * 3;
1384
1385                 if (r->captures == NULL) {
1386                     r->captures = ngx_palloc(r->pool, len * sizeof(int));
1387                     if (r->captures == NULL) {
1388                         return NGX_ERROR;
1389                     }
1390                 }
1391             }
1392
1393             n = ngx_regex_exec((*clcfp)->regex, &r->uri, r->captures, len);
1394
1395             if (n == NGX_REGEX_NO_MATCHED) {
1396                 continue;
1397             }
1398
1399             if (n < 0) {
1400                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1401                               ngx_regex_exec_n
1402                               " failed: %d on \"%V\" using \"%V\"",
1403                               n, &r->uri, &(*clcfp)->name);
1404                 return NGX_ERROR;
1405             }
1406
1407             /* match */
1408
1409             r->loc_conf = (*clcfp)->loc_conf;
1410
1411             r->ncaptures = len;
1412             r->captures_data = r->uri.data;
1413
1414             /* look up nested locations */
1415
1416             rc = ngx_http_core_find_location(r);
1417
1418             return (rc == NGX_ERROR) ? rc : NGX_OK;
1419         }
1420     }
1421 #endif
1422
1423     return rc;
1424 }
1425
1426
1427 /*
1428  * NGX_OK       - exact match
1429  * NGX_DONE     - auto redirect
1430  * NGX_AGAIN    - inclusive match
1431  * NGX_DECLINED - no match
1432  */
1433
1434 static ngx_int_t
1435 ngx_http_core_find_static_location(ngx_http_request_t *r,
1436     ngx_http_location_tree_node_t *node)
1437 {
1438     u_char     *uri;
1439     size_t      len, n;
1440     ngx_int_t   rc, rv;
1441
1442     len = r->uri.len;
1443     uri = r->uri.data;
1444
1445     rv = NGX_DECLINED;
1446
1447     for ( ;; ) {
1448
1449         if (node == NULL) {
1450             return rv;
1451         }
1452
1453         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1454                        "test location: \"%*s\"", node->len, node->name);
1455
1456         n = (len <= (size_t) node->len) ? len : node->len;
1457
1458         rc = ngx_filename_cmp(uri, node->name, n);
1459
1460         if (rc != 0) {
1461             node = (rc < 0) ? node->left : node->right;
1462
1463             continue;
1464         }
1465
1466         if (len > (size_t) node->len) {
1467
1468             if (node->inclusive) {
1469
1470                 r->loc_conf = node->inclusive->loc_conf;
1471                 rv = NGX_AGAIN;
1472
1473                 node = node->tree;
1474                 uri += n;
1475                 len -= n;
1476
1477                 continue;
1478             }
1479
1480             /* exact only */
1481
1482             node = node->right;
1483
1484             continue;
1485         }
1486
1487         if (len == (size_t) node->len) {
1488
1489             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1490                                           node->inclusive->loc_conf;
1491             return NGX_OK;
1492         }
1493
1494         /* len < node->len */
1495
1496         if (len + 1 == (size_t) node->len && node->auto_redirect) {
1497
1498             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1499                                           node->inclusive->loc_conf;
1500             rv = NGX_DONE;
1501         }
1502
1503         node = node->left;
1504     }
1505 }
1506
1507
1508 void *
1509 ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
1510 {
1511     u_char       c, *p;
1512     ngx_uint_t   i, hash;
1513
1514     if (r->headers_out.content_type.len == 0) {
1515         return NULL;
1516     }
1517
1518     if (r->headers_out.content_type_lowcase == NULL) {
1519
1520         p = ngx_pnalloc(r->pool, r->headers_out.content_type_len);
1521
1522         if (p == NULL) {
1523             return NULL;
1524         }
1525
1526         r->headers_out.content_type_lowcase = p;
1527
1528         hash = 0;
1529
1530         for (i = 0; i < r->headers_out.content_type_len; i++) {
1531             c = ngx_tolower(r->headers_out.content_type.data[i]);
1532             hash = ngx_hash(hash, c);
1533             *p++ = c;
1534         }
1535
1536         r->headers_out.content_type_hash = hash;
1537     }
1538
1539     return ngx_hash_find(types_hash,
1540                          r->headers_out.content_type_hash,
1541                          r->headers_out.content_type_lowcase,
1542                          r->headers_out.content_type_len);
1543 }
1544
1545
1546 ngx_int_t
1547 ngx_http_set_content_type(ngx_http_request_t *r)
1548 {
1549     u_char                     c, *exten;
1550     ngx_str_t                 *type;
1551     ngx_uint_t                 i, hash;
1552     ngx_http_core_loc_conf_t  *clcf;
1553
1554     if (r->headers_out.content_type.len) {
1555         return NGX_OK;
1556     }
1557
1558     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1559
1560     if (r->exten.len) {
1561
1562         hash = 0;
1563
1564         for (i = 0; i < r->exten.len; i++) {
1565             c = r->exten.data[i];
1566
1567             if (c >= 'A' && c <= 'Z') {
1568
1569                 exten = ngx_pnalloc(r->pool, r->exten.len);
1570                 if (exten == NULL) {
1571                     return NGX_ERROR;
1572                 }
1573
1574                 hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);
1575
1576                 r->exten.data = exten;
1577
1578                 break;
1579             }
1580
1581             hash = ngx_hash(hash, c);
1582         }
1583
1584         type = ngx_hash_find(&clcf->types_hash, hash,
1585                              r->exten.data, r->exten.len);
1586
1587         if (type) {
1588             r->headers_out.content_type_len = type->len;
1589             r->headers_out.content_type = *type;
1590
1591             return NGX_OK;
1592         }
1593     }
1594
1595     r->headers_out.content_type_len = clcf->default_type.len;
1596     r->headers_out.content_type = clcf->default_type;
1597
1598     return NGX_OK;
1599 }
1600
1601
1602 ngx_int_t
1603 ngx_http_set_exten(ngx_http_request_t *r)
1604 {
1605     ngx_int_t  i;
1606
1607     r->exten.len = 0;
1608     r->exten.data = NULL;
1609
1610     for (i = r->uri.len - 1; i > 1; i--) {
1611         if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
1612
1613             r->exten.len = r->uri.len - i - 1;
1614             r->exten.data = &r->uri.data[i + 1];
1615
1616             break;
1617
1618         } else if (r->uri.data[i] == '/') {
1619             break;
1620         }
1621     }
1622
1623     return NGX_OK;
1624 }
1625
1626
1627 ngx_int_t
1628 ngx_http_send_header(ngx_http_request_t *r)
1629 {
1630     if (r->err_status) {
1631         r->headers_out.status = r->err_status;
1632         r->headers_out.status_line.len = 0;
1633     }
1634
1635     return ngx_http_top_header_filter(r);
1636 }
1637
1638
1639 ngx_int_t
1640 ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
1641 {
1642     ngx_int_t  rc;
1643
1644     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1645                    "http output filter \"%V?%V\"", &r->uri, &r->args);
1646
1647     rc = ngx_http_top_body_filter(r, in);
1648
1649     if (rc == NGX_ERROR) {
1650         /* NGX_ERROR may be returned by any filter */
1651         r->connection->error = 1;
1652     }
1653
1654     return rc;
1655 }
1656
1657
1658 u_char *
1659 ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
1660     size_t *root_length, size_t reserved)
1661 {
1662     u_char                    *last;
1663     size_t                     alias;
1664     ngx_http_core_loc_conf_t  *clcf;
1665
1666     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1667
1668     alias = clcf->alias ? clcf->name.len : 0;
1669
1670     if (alias && !r->valid_location) {
1671         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1672                       "\"alias\" could not be used in location \"%V\" "
1673                       "where URI was rewritten", &clcf->name);
1674         return NULL;
1675     }
1676
1677     if (clcf->root_lengths == NULL) {
1678
1679         *root_length = clcf->root.len;
1680
1681         path->len = clcf->root.len + reserved + r->uri.len - alias + 1;
1682
1683         path->data = ngx_pnalloc(r->pool, path->len);
1684         if (path->data == NULL) {
1685             return NULL;
1686         }
1687
1688         last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
1689
1690     } else {
1691         if (ngx_http_script_run(r, path, clcf->root_lengths->elts, ++reserved,
1692                                 clcf->root_values->elts)
1693             == NULL)
1694         {
1695             return NULL;
1696         }
1697
1698         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0) != NGX_OK) {
1699             return NULL;
1700         }
1701
1702         *root_length = path->len - reserved;
1703         last = path->data + *root_length;
1704
1705         if (alias) {
1706             *last = '\0';
1707             return last;
1708         }
1709     }
1710
1711     last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
1712
1713     return last;
1714 }
1715
1716
1717 ngx_int_t
1718 ngx_http_auth_basic_user(ngx_http_request_t *r)
1719 {
1720     ngx_str_t   auth, encoded;
1721     ngx_uint_t  len;
1722
1723     if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
1724         return NGX_DECLINED;
1725     }
1726
1727     if (r->headers_in.authorization == NULL) {
1728         r->headers_in.user.data = (u_char *) "";
1729         return NGX_DECLINED;
1730     }
1731
1732     encoded = r->headers_in.authorization->value;
1733
1734     if (encoded.len < sizeof("Basic ") - 1
1735         || ngx_strncasecmp(encoded.data, (u_char *) "Basic ",
1736                            sizeof("Basic ") - 1)
1737            != 0)
1738     {
1739         r->headers_in.user.data = (u_char *) "";
1740         return NGX_DECLINED;
1741     }
1742
1743     encoded.len -= sizeof("Basic ") - 1;
1744     encoded.data += sizeof("Basic ") - 1;
1745
1746     while (encoded.len && encoded.data[0] == ' ') {
1747         encoded.len--;
1748         encoded.data++;
1749     }
1750
1751     if (encoded.len == 0) {
1752         r->headers_in.user.data = (u_char *) "";
1753         return NGX_DECLINED;
1754     }
1755
1756     auth.len = ngx_base64_decoded_length(encoded.len);
1757     auth.data = ngx_pnalloc(r->pool, auth.len + 1);
1758     if (auth.data == NULL) {
1759         return NGX_ERROR;
1760     }
1761
1762     if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
1763         r->headers_in.user.data = (u_char *) "";
1764         return NGX_DECLINED;
1765     }
1766
1767     auth.data[auth.len] = '\0';
1768
1769     for (len = 0; len < auth.len; len++) {
1770         if (auth.data[len] == ':') {
1771             break;
1772         }
1773     }
1774
1775     if (len == 0 || len == auth.len) {
1776         r->headers_in.user.data = (u_char *) "";
1777         return NGX_DECLINED;
1778     }
1779
1780     r->headers_in.user.len = len;
1781     r->headers_in.user.data = auth.data;
1782     r->headers_in.passwd.len = auth.len - len - 1;
1783     r->headers_in.passwd.data = &auth.data[len + 1];
1784
1785     return NGX_OK;
1786 }
1787
1788
1789 ngx_int_t
1790 ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
1791 {
1792     socklen_t            len;
1793     ngx_connection_t    *c;
1794     u_char               sa[NGX_SOCKADDRLEN];
1795
1796     c = r->connection;
1797
1798     if (c->local_sockaddr == NULL) {
1799
1800         len = NGX_SOCKADDRLEN;
1801
1802         if (getsockname(c->fd, (struct sockaddr *) &sa, &len) == -1) {
1803             ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1804             return NGX_ERROR;
1805         }
1806
1807         c->local_sockaddr = ngx_palloc(r->connection->pool, len);
1808         if (c->local_sockaddr == NULL) {
1809             return NGX_ERROR;
1810         }
1811
1812         c->local_socklen = len;
1813         ngx_memcpy(c->local_sockaddr, &sa, len);
1814     }
1815
1816     if (s == NULL) {
1817         return NGX_OK;
1818     }
1819
1820     s->len = ngx_sock_ntop(c->local_sockaddr, s->data, s->len, 0);
1821
1822     return NGX_OK;
1823 }
1824
1825
1826 #if (NGX_HTTP_GZIP)
1827
1828 ngx_int_t
1829 ngx_http_gzip_ok(ngx_http_request_t *r)
1830 {
1831     time_t                     date, expires;
1832     ngx_uint_t                 p;
1833     ngx_array_t               *cc;
1834     ngx_table_elt_t           *e, *d;
1835     ngx_http_core_loc_conf_t  *clcf;
1836
1837     if (r->gzip == 1) {
1838         return NGX_OK;
1839     }
1840
1841     if (r->gzip == 2) {
1842         return NGX_DECLINED;
1843     }
1844
1845     r->gzip = 2;
1846
1847     if (r != r->main
1848         || r->headers_in.accept_encoding == NULL
1849         || ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
1850                            "gzip", 4 - 1)
1851            == NULL
1852
1853         /*
1854          * if the URL (without the "http://" prefix) is longer than 253 bytes,
1855          * then MSIE 4.x can not handle the compressed stream - it waits
1856          * too long, hangs up or crashes
1857          */
1858
1859         || (r->headers_in.msie4 && r->unparsed_uri.len > 200))
1860     {
1861         return NGX_DECLINED;
1862     }
1863
1864     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1865
1866     if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
1867         return NGX_DECLINED;
1868     }
1869
1870     if (r->http_version < clcf->gzip_http_version) {
1871         return NGX_DECLINED;
1872     }
1873
1874     if (r->headers_in.via == NULL) {
1875         goto ok;
1876     }
1877
1878     p = clcf->gzip_proxied;
1879
1880     if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
1881         return NGX_DECLINED;
1882     }
1883
1884     if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
1885         goto ok;
1886     }
1887
1888     if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
1889         goto ok;
1890     }
1891
1892     e = r->headers_out.expires;
1893
1894     if (e) {
1895
1896         if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
1897             return NGX_DECLINED;
1898         }
1899
1900         expires = ngx_http_parse_time(e->value.data, e->value.len);
1901         if (expires == NGX_ERROR) {
1902             return NGX_DECLINED;
1903         }
1904
1905         d = r->headers_out.date;
1906
1907         if (d) {
1908             date = ngx_http_parse_time(d->value.data, d->value.len);
1909             if (date == NGX_ERROR) {
1910                 return NGX_DECLINED;
1911             }
1912
1913         } else {
1914             date = ngx_time();
1915         }
1916
1917         if (expires < date) {
1918             goto ok;
1919         }
1920
1921         return NGX_DECLINED;
1922     }
1923
1924     cc = &r->headers_out.cache_control;
1925
1926     if (cc->elts) {
1927
1928         if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
1929             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
1930                                                  NULL)
1931                >= 0)
1932         {
1933             goto ok;
1934         }
1935
1936         if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
1937             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
1938                                                  NULL)
1939                >= 0)
1940         {
1941             goto ok;
1942         }
1943
1944         if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
1945             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
1946                                                  NULL)
1947                >= 0)
1948         {
1949             goto ok;
1950         }
1951
1952         return NGX_DECLINED;
1953     }
1954
1955     if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
1956         return NGX_DECLINED;
1957     }
1958
1959     if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
1960         return NGX_DECLINED;
1961     }
1962
1963 ok:
1964
1965 #if (NGX_PCRE)
1966
1967     if (clcf->gzip_disable && r->headers_in.user_agent) {
1968
1969         if (ngx_regex_exec_array(clcf->gzip_disable,
1970                                  &r->headers_in.user_agent->value,
1971                                  r->connection->log)
1972             != NGX_DECLINED)
1973         {
1974             return NGX_DECLINED;
1975         }
1976     }
1977
1978 #endif
1979
1980     r->gzip = 1;
1981
1982     return NGX_OK;
1983 }
1984
1985 #endif
1986
1987
1988 ngx_int_t
1989 ngx_http_subrequest(ngx_http_request_t *r,
1990     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
1991     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
1992 {
1993     ngx_connection_t              *c;
1994     ngx_http_request_t            *sr;
1995     ngx_http_core_srv_conf_t      *cscf;
1996     ngx_http_postponed_request_t  *pr, *p;
1997
1998     r->main->subrequests--;
1999
2000     if (r->main->subrequests == 0) {
2001         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2002                       "subrequests cycle while processing \"%V\"", uri);
2003         r->main->subrequests = 1;
2004         return NGX_ERROR;
2005     }
2006
2007     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
2008     if (sr == NULL) {
2009         return NGX_ERROR;
2010     }
2011
2012     sr->signature = NGX_HTTP_MODULE;
2013
2014     c = r->connection;
2015     sr->connection = c;
2016
2017     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
2018     if (sr->ctx == NULL) {
2019         return NGX_ERROR;
2020     }
2021
2022     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
2023                       sizeof(ngx_table_elt_t))
2024         != NGX_OK)
2025     {
2026         return NGX_ERROR;
2027     }
2028
2029     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2030     sr->main_conf = cscf->ctx->main_conf;
2031     sr->srv_conf = cscf->ctx->srv_conf;
2032     sr->loc_conf = cscf->ctx->loc_conf;
2033
2034     sr->pool = r->pool;
2035
2036     sr->headers_in = r->headers_in;
2037
2038     ngx_http_clear_content_length(sr);
2039     ngx_http_clear_accept_ranges(sr);
2040     ngx_http_clear_last_modified(sr);
2041
2042     sr->request_body = r->request_body;
2043
2044     sr->method = NGX_HTTP_GET;
2045     sr->http_version = r->http_version;
2046
2047     sr->request_line = r->request_line;
2048     sr->uri = *uri;
2049
2050     if (args) {
2051         sr->args = *args;
2052     }
2053
2054     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2055                    "http subrequest \"%V?%V\"", uri, &sr->args);
2056
2057     sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
2058     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
2059     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
2060
2061     sr->unparsed_uri = r->unparsed_uri;
2062     sr->method_name = ngx_http_core_get_method;
2063     sr->http_protocol = r->http_protocol;
2064
2065     if (ngx_http_set_exten(sr) != NGX_OK) {
2066         return NGX_ERROR;
2067     }
2068
2069     sr->main = r->main;
2070     sr->parent = r;
2071     sr->post_subrequest = ps;
2072     sr->read_event_handler = ngx_http_request_empty_handler;
2073     sr->write_event_handler = ngx_http_handler;
2074
2075     if (c->data == r && r->postponed == NULL) {
2076         c->data = sr;
2077     }
2078
2079     sr->variables = r->variables;
2080
2081     sr->log_handler = r->log_handler;
2082
2083     pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
2084     if (pr == NULL) {
2085         return NGX_ERROR;
2086     }
2087
2088     pr->request = sr;
2089     pr->out = NULL;
2090     pr->next = NULL;
2091
2092     if (r->postponed) {
2093         for (p = r->postponed; p->next; p = p->next) { /* void */ }
2094         p->next = pr;
2095
2096     } else {
2097         r->postponed = pr;
2098     }
2099
2100     sr->internal = 1;
2101
2102     sr->discard_body = r->discard_body;
2103     sr->expect_tested = 1;
2104     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
2105
2106     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
2107
2108     r->main->subrequests++;
2109
2110     *psr = sr;
2111
2112     return ngx_http_post_request(sr);
2113 }
2114
2115
2116 ngx_int_t
2117 ngx_http_internal_redirect(ngx_http_request_t *r,
2118     ngx_str_t *uri, ngx_str_t *args)
2119 {
2120     ngx_http_core_srv_conf_t  *cscf;
2121
2122     r->uri_changes--;
2123
2124     if (r->uri_changes == 0) {
2125         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2126                       "rewrite or internal redirection cycle "
2127                       "while internal redirect to \"%V\"", uri);
2128
2129         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2130         return NGX_DONE;
2131     }
2132
2133     r->uri = *uri;
2134
2135     if (args) {
2136         r->args = *args;
2137
2138     } else {
2139         r->args.len = 0;
2140         r->args.data = NULL;
2141     }
2142
2143     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2144                    "internal redirect: \"%V?%V\"", uri, &r->args);
2145
2146     if (ngx_http_set_exten(r) != NGX_OK) {
2147         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2148         return NGX_DONE;
2149     }
2150
2151     /* clear the modules contexts */
2152     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2153
2154     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2155     r->loc_conf = cscf->ctx->loc_conf;
2156
2157     ngx_http_update_location_config(r);
2158
2159     r->internal = 1;
2160
2161     ngx_http_handler(r);
2162
2163     return NGX_DONE;
2164 }
2165
2166
2167 ngx_int_t
2168 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
2169 {
2170     ngx_http_core_srv_conf_t    *cscf;
2171     ngx_http_core_loc_conf_t   **clcfp;
2172     ngx_http_core_main_conf_t   *cmcf;
2173
2174     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2175
2176     if (cscf->named_locations) {
2177
2178         for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
2179
2180             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2181                            "test location: \"%V\"", &(*clcfp)->name);
2182
2183             if (name->len != (*clcfp)->name.len
2184                 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
2185             {
2186                 continue;
2187             }
2188
2189             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2190                            "using location: %V \"%V?%V\"",
2191                            name, &r->uri, &r->args);
2192
2193             r->internal = 1;
2194             r->content_handler = NULL;
2195             r->loc_conf = (*clcfp)->loc_conf;
2196
2197             ngx_http_update_location_config(r);
2198
2199             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2200
2201             r->phase_handler = cmcf->phase_engine.location_rewrite_index;
2202
2203             ngx_http_core_run_phases(r);
2204
2205             return NGX_DONE;
2206         }
2207     }
2208
2209     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2210                   "could not find named location \"%V\"", name);
2211
2212     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2213
2214     return NGX_DONE;
2215 }
2216
2217
2218 ngx_http_cleanup_t *
2219 ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
2220 {
2221     ngx_http_cleanup_t  *cln;
2222
2223     r = r->main;
2224
2225     cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
2226     if (cln == NULL) {
2227         return NULL;
2228     }
2229
2230     if (size) {
2231         cln->data = ngx_palloc(r->pool, size);
2232         if (cln->data == NULL) {
2233             return NULL;
2234         }
2235
2236     } else {
2237         cln->data = NULL;
2238     }
2239
2240     cln->handler = NULL;
2241     cln->next = r->cleanup;
2242
2243     r->cleanup = cln;
2244
2245     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2246                    "http cleanup add: %p", cln);
2247
2248     return cln;
2249 }
2250
2251
2252 static char *
2253 ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2254 {
2255     char                        *rv;
2256     void                        *mconf;
2257     ngx_uint_t                   i;
2258     ngx_conf_t                   pcf;
2259     ngx_http_module_t           *module;
2260     ngx_http_conf_ctx_t         *ctx, *http_ctx;
2261     ngx_http_core_srv_conf_t    *cscf, **cscfp;
2262     ngx_http_core_main_conf_t   *cmcf;
2263
2264     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2265     if (ctx == NULL) {
2266         return NGX_CONF_ERROR;
2267     }
2268
2269     http_ctx = cf->ctx;
2270     ctx->main_conf = http_ctx->main_conf;
2271
2272     /* the server{}'s srv_conf */
2273
2274     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2275     if (ctx->srv_conf == NULL) {
2276         return NGX_CONF_ERROR;
2277     }
2278
2279     /* the server{}'s loc_conf */
2280
2281     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2282     if (ctx->loc_conf == NULL) {
2283         return NGX_CONF_ERROR;
2284     }
2285
2286     for (i = 0; ngx_modules[i]; i++) {
2287         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2288             continue;
2289         }
2290
2291         module = ngx_modules[i]->ctx;
2292
2293         if (module->create_srv_conf) {
2294             mconf = module->create_srv_conf(cf);
2295             if (mconf == NULL) {
2296                 return NGX_CONF_ERROR;
2297             }
2298
2299             ctx->srv_conf[ngx_modules[i]->ctx_index] = mconf;
2300         }
2301
2302         if (module->create_loc_conf) {
2303             mconf = module->create_loc_conf(cf);
2304             if (mconf == NULL) {
2305                 return NGX_CONF_ERROR;
2306             }
2307
2308             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
2309         }
2310     }
2311
2312
2313     /* the server configuration context */
2314
2315     cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
2316     cscf->ctx = ctx;
2317
2318
2319     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
2320
2321     cscfp = ngx_array_push(&cmcf->servers);
2322     if (cscfp == NULL) {
2323         return NGX_CONF_ERROR;
2324     }
2325
2326     *cscfp = cscf;
2327
2328
2329     /* parse inside server{} */
2330
2331     pcf = *cf;
2332     cf->ctx = ctx;
2333     cf->cmd_type = NGX_HTTP_SRV_CONF;
2334
2335     rv = ngx_conf_parse(cf, NULL);
2336
2337     *cf = pcf;
2338
2339     return rv;
2340 }
2341
2342
2343 static char *
2344 ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2345 {
2346     char                      *rv;
2347     u_char                    *mod;
2348     size_t                     len;
2349     ngx_str_t                 *value, *name;
2350     ngx_uint_t                 i;
2351     ngx_conf_t                 save;
2352     ngx_http_module_t         *module;
2353     ngx_http_conf_ctx_t       *ctx, *pctx;
2354     ngx_http_core_loc_conf_t  *clcf, *pclcf;
2355
2356     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2357     if (ctx == NULL) {
2358         return NGX_CONF_ERROR;
2359     }
2360
2361     pctx = cf->ctx;
2362     ctx->main_conf = pctx->main_conf;
2363     ctx->srv_conf = pctx->srv_conf;
2364
2365     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2366     if (ctx->loc_conf == NULL) {
2367         return NGX_CONF_ERROR;
2368     }
2369
2370     for (i = 0; ngx_modules[i]; i++) {
2371         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2372             continue;
2373         }
2374
2375         module = ngx_modules[i]->ctx;
2376
2377         if (module->create_loc_conf) {
2378             ctx->loc_conf[ngx_modules[i]->ctx_index] =
2379                                                    module->create_loc_conf(cf);
2380             if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) {
2381                  return NGX_CONF_ERROR;
2382             }
2383         }
2384     }
2385
2386     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
2387     clcf->loc_conf = ctx->loc_conf;
2388
2389     value = cf->args->elts;
2390
2391     if (cf->args->nelts == 3) {
2392
2393         len = value[1].len;
2394         mod = value[1].data;
2395         name = &value[2];
2396
2397         if (len == 1 && mod[0] == '=') {
2398
2399             clcf->name = *name;
2400             clcf->exact_match = 1;
2401
2402         } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
2403
2404             clcf->name = *name;
2405             clcf->noregex = 1;
2406
2407         } else if (len == 1 && mod[0] == '~') {
2408
2409             if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2410                 return NGX_CONF_ERROR;
2411             }
2412
2413         } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
2414
2415             if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2416                 return NGX_CONF_ERROR;
2417             }
2418
2419         } else {
2420             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2421                                "invalid location modifier \"%V\"", &value[1]);
2422             return NGX_CONF_ERROR;
2423         }
2424
2425     } else {
2426
2427         name = &value[1];
2428
2429         if (name->data[0] == '=') {
2430
2431             clcf->name.len = name->len - 1;
2432             clcf->name.data = name->data + 1;
2433             clcf->exact_match = 1;
2434
2435         } else if (name->data[0] == '^' && name->data[1] == '~') {
2436
2437             clcf->name.len = name->len - 2;
2438             clcf->name.data = name->data + 2;
2439             clcf->noregex = 1;
2440
2441         } else if (name->data[0] == '~') {
2442
2443             name->len--;
2444             name->data++;
2445
2446             if (name->data[0] == '*') {
2447
2448                 name->len--;
2449                 name->data++;
2450
2451                 if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2452                     return NGX_CONF_ERROR;
2453                 }
2454
2455             } else {
2456                 if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2457                     return NGX_CONF_ERROR;
2458                 }
2459             }
2460
2461         } else {
2462
2463             clcf->name = *name;
2464
2465             if (name->data[0] == '@') {
2466                 clcf->named = 1;
2467             }
2468         }
2469     }
2470
2471     pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
2472
2473     if (pclcf->name.len) {
2474
2475         /* nested location */
2476
2477 #if 0
2478         clcf->prev_location = pclcf;
2479 #endif
2480
2481         if (pclcf->exact_match) {
2482             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2483                                "location \"%V\" could not be inside "
2484                                "the exact location \"%V\"",
2485                                &clcf->name, &pclcf->name);
2486             return NGX_CONF_ERROR;
2487         }
2488
2489         if (pclcf->named) {
2490             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2491                                "location \"%V\" could not be inside "
2492                                "the named location \"%V\"",
2493                                &clcf->name, &pclcf->name);
2494             return NGX_CONF_ERROR;
2495         }
2496
2497         if (clcf->named) {
2498             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2499                                "named location \"%V\" must be "
2500                                "on server level only",
2501                                &clcf->name);
2502             return NGX_CONF_ERROR;
2503         }
2504
2505         len = pclcf->name.len;
2506
2507 #if (NGX_PCRE)
2508         if (clcf->regex == NULL
2509             && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2510 #else
2511         if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2512 #endif
2513         {
2514             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2515                                "location \"%V\" is outside location \"%V\"",
2516                                &clcf->name, &pclcf->name);
2517             return NGX_CONF_ERROR;
2518         }
2519     }
2520
2521     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
2522         return NGX_CONF_ERROR;
2523     }
2524
2525     save = *cf;
2526     cf->ctx = ctx;
2527     cf->cmd_type = NGX_HTTP_LOC_CONF;
2528
2529     rv = ngx_conf_parse(cf, NULL);
2530
2531     *cf = save;
2532
2533     return rv;
2534 }
2535
2536
2537 static ngx_int_t
2538 ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
2539     ngx_str_t *regex, ngx_uint_t caseless)
2540 {
2541 #if (NGX_PCRE)
2542     ngx_str_t  err;
2543     u_char     errstr[NGX_MAX_CONF_ERRSTR];
2544
2545     err.len = NGX_MAX_CONF_ERRSTR;
2546     err.data = errstr;
2547
2548     clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
2549                                     cf->pool, &err);
2550
2551     if (clcf->regex == NULL) {
2552         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
2553         return NGX_ERROR;
2554     }
2555
2556     clcf->name = *regex;
2557     clcf->captures = (ngx_regex_capture_count(clcf->regex) > 0);
2558
2559     return NGX_OK;
2560
2561 #else
2562
2563     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2564                        "the using of the regex \"%V\" requires PCRE library",
2565                        regex);
2566     return NGX_ERROR;
2567
2568 #endif
2569 }
2570
2571
2572 static char *
2573 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2574 {
2575     ngx_http_core_loc_conf_t *lcf = conf;
2576
2577     char        *rv;
2578     ngx_conf_t   save;
2579
2580     if (lcf->types == NULL) {
2581         lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
2582         if (lcf->types == NULL) {
2583             return NGX_CONF_ERROR;
2584         }
2585     }
2586
2587     save = *cf;
2588     cf->handler = ngx_http_core_type;
2589     cf->handler_conf = conf;
2590
2591     rv = ngx_conf_parse(cf, NULL);
2592
2593     *cf = save;
2594
2595     return rv;
2596 }
2597
2598
2599 static char *
2600 ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
2601 {
2602     ngx_http_core_loc_conf_t *lcf = conf;
2603
2604     ngx_str_t       *value, *content_type, *old, file;
2605     ngx_uint_t       i, n, hash;
2606     ngx_hash_key_t  *type;
2607
2608     value = cf->args->elts;
2609
2610     if (ngx_strcmp(value[0].data, "include") == 0) {
2611         file = value[1];
2612
2613         if (ngx_conf_full_name(cf->cycle, &file, 1) != NGX_OK) {
2614             return NGX_CONF_ERROR;
2615         }
2616
2617         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
2618
2619         return ngx_conf_parse(cf, &file);
2620     }
2621
2622     content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
2623     if (content_type == NULL) {
2624         return NGX_CONF_ERROR;
2625     }
2626
2627     *content_type = value[0];
2628
2629     for (i = 1; i < cf->args->nelts; i++) {
2630
2631         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
2632
2633         type = lcf->types->elts;
2634         for (n = 0; n < lcf->types->nelts; n++) {
2635             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
2636                 old = type[n].value;
2637                 type[n].value = content_type;
2638
2639                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2640                                    "duplicate extention \"%V\", "
2641                                    "content type: \"%V\", "
2642                                    "old content type: \"%V\"",
2643                                    &value[i], content_type, old);
2644                 continue;
2645             }
2646         }
2647
2648
2649         type = ngx_array_push(lcf->types);
2650         if (type == NULL) {
2651             return NGX_CONF_ERROR;
2652         }
2653
2654         type->key = value[i];
2655         type->key_hash = hash;
2656         type->value = content_type;
2657     }
2658
2659     return NGX_CONF_OK;
2660 }
2661
2662
2663 static ngx_int_t
2664 ngx_http_core_preconfiguration(ngx_conf_t *cf)
2665 {
2666     return ngx_http_variables_add_core_vars(cf);
2667 }
2668
2669
2670 static void *
2671 ngx_http_core_create_main_conf(ngx_conf_t *cf)
2672 {
2673     ngx_http_core_main_conf_t  *cmcf;
2674
2675     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
2676     if (cmcf == NULL) {
2677         return NGX_CONF_ERROR;
2678     }
2679
2680     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
2681                        sizeof(ngx_http_core_srv_conf_t *))
2682         != NGX_OK)
2683     {
2684         return NGX_CONF_ERROR;
2685     }
2686
2687     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
2688     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
2689
2690     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
2691     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
2692
2693     return cmcf;
2694 }
2695
2696
2697 static char *
2698 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
2699 {
2700     ngx_http_core_main_conf_t *cmcf = conf;
2701
2702     if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
2703         cmcf->server_names_hash_max_size = 512;
2704     }
2705
2706     if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2707         cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
2708     }
2709
2710     cmcf->server_names_hash_bucket_size =
2711             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
2712
2713
2714     if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
2715         cmcf->variables_hash_max_size = 512;
2716     }
2717
2718     if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2719         cmcf->variables_hash_bucket_size = 64;
2720     }
2721
2722     cmcf->variables_hash_bucket_size =
2723                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
2724
2725     return NGX_CONF_OK;
2726 }
2727
2728
2729 static void *
2730 ngx_http_core_create_srv_conf(ngx_conf_t *cf)
2731 {
2732     ngx_http_core_srv_conf_t  *cscf;
2733
2734     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
2735     if (cscf == NULL) {
2736         return NGX_CONF_ERROR;
2737     }
2738
2739     /*
2740      * set by ngx_pcalloc():
2741      *
2742      *     conf->client_large_buffers.num = 0;
2743      */
2744
2745     if (ngx_array_init(&cscf->listen, cf->temp_pool, 4,
2746                        sizeof(ngx_http_listen_t))
2747         != NGX_OK)
2748     {
2749         return NGX_CONF_ERROR;
2750     }
2751
2752     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
2753                        sizeof(ngx_http_server_name_t))
2754         != NGX_OK)
2755     {
2756         return NGX_CONF_ERROR;
2757     }
2758
2759     cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
2760     cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
2761     cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
2762     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
2763     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
2764     cscf->merge_slashes = NGX_CONF_UNSET;
2765     cscf->underscores_in_headers = NGX_CONF_UNSET;
2766
2767     return cscf;
2768 }
2769
2770
2771 static char *
2772 ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
2773 {
2774     ngx_http_core_srv_conf_t *prev = parent;
2775     ngx_http_core_srv_conf_t *conf = child;
2776
2777     ngx_http_listen_t       *ls;
2778     struct sockaddr_in      *sin;
2779     ngx_http_server_name_t  *sn;
2780
2781     /* TODO: it does not merge, it inits only */
2782
2783     if (conf->listen.nelts == 0) {
2784         ls = ngx_array_push(&conf->listen);
2785         if (ls == NULL) {
2786             return NGX_CONF_ERROR;
2787         }
2788
2789         ngx_memzero(ls, sizeof(ngx_http_listen_t));
2790
2791         sin = (struct sockaddr_in *) &ls->sockaddr;
2792
2793         sin->sin_family = AF_INET;
2794 #if (NGX_WIN32)
2795         sin->sin_port = htons(80);
2796 #else
2797         sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
2798 #endif
2799         sin->sin_addr.s_addr = INADDR_ANY;
2800
2801         ls->socklen = sizeof(struct sockaddr_in);
2802
2803         ls->conf.backlog = NGX_LISTEN_BACKLOG;
2804         ls->conf.rcvbuf = -1;
2805         ls->conf.sndbuf = -1;
2806         ls->conf.wildcard = 1;
2807
2808         (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr,
2809                              NGX_SOCKADDR_STRLEN, 1);
2810     }
2811
2812     if (conf->server_name.data == NULL) {
2813         conf->server_name = cf->cycle->hostname;
2814
2815         sn = ngx_array_push(&conf->server_names);
2816         if (sn == NULL) {
2817             return NGX_CONF_ERROR;
2818         }
2819
2820 #if (NGX_PCRE)
2821         sn->regex = NULL;
2822         sn->captures = 0;
2823 #endif
2824         sn->core_srv_conf = conf;
2825         sn->name.len = conf->server_name.len;
2826         sn->name.data = conf->server_name.data;
2827     }
2828
2829     ngx_conf_merge_size_value(conf->connection_pool_size,
2830                               prev->connection_pool_size, 256);
2831     ngx_conf_merge_size_value(conf->request_pool_size,
2832                               prev->request_pool_size, 4096);
2833     ngx_conf_merge_msec_value(conf->client_header_timeout,
2834                               prev->client_header_timeout, 60000);
2835     ngx_conf_merge_size_value(conf->client_header_buffer_size,
2836                               prev->client_header_buffer_size, 1024);
2837     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
2838                               prev->large_client_header_buffers,
2839                               4, ngx_pagesize);
2840
2841     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
2842         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2843                            "the \"large_client_header_buffers\" size must be "
2844                            "equal to or bigger than \"connection_pool_size\"");
2845         return NGX_CONF_ERROR;
2846     }
2847
2848     ngx_conf_merge_value(conf->ignore_invalid_headers,
2849                               prev->ignore_invalid_headers, 1);
2850
2851     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
2852
2853     ngx_conf_merge_value(conf->underscores_in_headers,
2854                               prev->underscores_in_headers, 0);
2855
2856     return NGX_CONF_OK;
2857 }
2858
2859
2860 static void *
2861 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
2862 {
2863     ngx_http_core_loc_conf_t  *lcf;
2864
2865     lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
2866     if (lcf == NULL) {
2867         return NGX_CONF_ERROR;
2868     }
2869
2870     /*
2871      * set by ngx_pcalloc():
2872      *
2873      *     lcf->root = { 0, NULL };
2874      *     lcf->limit_except = 0;
2875      *     lcf->post_action = { 0, NULL };
2876      *     lcf->types = NULL;
2877      *     lcf->default_type = { 0, NULL };
2878      *     lcf->err_log = NULL;
2879      *     lcf->error_pages = NULL;
2880      *     lcf->try_files = NULL;
2881      *     lcf->client_body_path = NULL;
2882      *     lcf->regex = NULL;
2883      *     lcf->exact_match = 0;
2884      *     lcf->auto_redirect = 0;
2885      *     lcf->alias = 0;
2886      *     lcf->gzip_proxied = 0;
2887      */
2888
2889     lcf->client_max_body_size = NGX_CONF_UNSET;
2890     lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
2891     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
2892     lcf->satisfy = NGX_CONF_UNSET_UINT;
2893     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
2894     lcf->internal = NGX_CONF_UNSET;
2895     lcf->client_body_in_file_only = NGX_CONF_UNSET;
2896     lcf->sendfile = NGX_CONF_UNSET;
2897     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
2898     lcf->directio = NGX_CONF_UNSET;
2899     lcf->tcp_nopush = NGX_CONF_UNSET;
2900     lcf->tcp_nodelay = NGX_CONF_UNSET;
2901     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
2902     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
2903     lcf->postpone_output = NGX_CONF_UNSET_SIZE;
2904     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
2905     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
2906     lcf->keepalive_header = NGX_CONF_UNSET;
2907     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
2908     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
2909     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
2910     lcf->reset_timedout_connection = NGX_CONF_UNSET;
2911     lcf->server_name_in_redirect = NGX_CONF_UNSET;
2912     lcf->port_in_redirect = NGX_CONF_UNSET;
2913     lcf->msie_padding = NGX_CONF_UNSET;
2914     lcf->msie_refresh = NGX_CONF_UNSET;
2915     lcf->log_not_found = NGX_CONF_UNSET;
2916     lcf->log_subrequest = NGX_CONF_UNSET;
2917     lcf->recursive_error_pages = NGX_CONF_UNSET;
2918     lcf->server_tokens = NGX_CONF_UNSET;
2919     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
2920     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
2921
2922     lcf->open_file_cache = NGX_CONF_UNSET_PTR;
2923     lcf->open_file_cache_valid = NGX_CONF_UNSET;
2924     lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
2925     lcf->open_file_cache_errors = NGX_CONF_UNSET;
2926     lcf->open_file_cache_events = NGX_CONF_UNSET;
2927
2928 #if (NGX_HTTP_GZIP)
2929     lcf->gzip_vary = NGX_CONF_UNSET;
2930     lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
2931 #if (NGX_PCRE)
2932     lcf->gzip_disable = NGX_CONF_UNSET_PTR;
2933     lcf->gzip_disable_msie6 = 3;
2934 #endif
2935 #endif
2936
2937     return lcf;
2938 }
2939
2940
2941 static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
2942 static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
2943 static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
2944
2945 static ngx_hash_key_t  ngx_http_core_default_types[] = {
2946     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
2947     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
2948     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
2949     { ngx_null_string, 0, NULL }
2950 };
2951
2952
2953 static char *
2954 ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2955 {
2956     ngx_http_core_loc_conf_t *prev = parent;
2957     ngx_http_core_loc_conf_t *conf = child;
2958
2959     ngx_uint_t        i;
2960     ngx_hash_key_t   *type;
2961     ngx_hash_init_t   types_hash;
2962
2963     if (conf->root.data == NULL) {
2964
2965         conf->alias = prev->alias;
2966         conf->root = prev->root;
2967         conf->root_lengths = prev->root_lengths;
2968         conf->root_values = prev->root_values;
2969
2970         if (prev->root.data == NULL) {
2971             conf->root.len = sizeof("html") - 1;
2972             conf->root.data = (u_char *) "html";
2973
2974             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) != NGX_OK) {
2975                 return NGX_CONF_ERROR;
2976             }
2977         }
2978     }
2979
2980     if (conf->post_action.data == NULL) {
2981         conf->post_action = prev->post_action;
2982     }
2983
2984     ngx_conf_merge_uint_value(conf->types_hash_max_size,
2985                               prev->types_hash_max_size, 1024);
2986
2987     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
2988                               prev->types_hash_bucket_size,
2989                               ngx_cacheline_size);
2990
2991     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
2992                                              ngx_cacheline_size);
2993
2994     /*
2995      * the special handling the "types" directive in the "http" section
2996      * to inherit the http's conf->types_hash to all servers
2997      */
2998
2999     if (prev->types && prev->types_hash.buckets == NULL) {
3000
3001         types_hash.hash = &prev->types_hash;
3002         types_hash.key = ngx_hash_key_lc;
3003         types_hash.max_size = conf->types_hash_max_size;
3004         types_hash.bucket_size = conf->types_hash_bucket_size;
3005         types_hash.name = "types_hash";
3006         types_hash.pool = cf->pool;
3007         types_hash.temp_pool = NULL;
3008
3009         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
3010             != NGX_OK)
3011         {
3012             return NGX_CONF_ERROR;
3013         }
3014     }
3015
3016     if (conf->types == NULL) {
3017         conf->types = prev->types;
3018         conf->types_hash = prev->types_hash;
3019     }
3020
3021     if (conf->types == NULL) {
3022         conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
3023         if (conf->types == NULL) {
3024             return NGX_CONF_ERROR;
3025         }
3026
3027         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
3028             type = ngx_array_push(conf->types);
3029             if (type == NULL) {
3030                 return NGX_CONF_ERROR;
3031             }
3032
3033             type->key = ngx_http_core_default_types[i].key;
3034             type->key_hash =
3035                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3036                                        ngx_http_core_default_types[i].key.len);
3037             type->value = ngx_http_core_default_types[i].value;
3038         }
3039     }
3040
3041     if (conf->types_hash.buckets == NULL) {
3042
3043         types_hash.hash = &conf->types_hash;
3044         types_hash.key = ngx_hash_key_lc;
3045         types_hash.max_size = conf->types_hash_max_size;
3046         types_hash.bucket_size = conf->types_hash_bucket_size;
3047         types_hash.name = "mime_types_hash";
3048         types_hash.pool = cf->pool;
3049         types_hash.temp_pool = NULL;
3050
3051         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3052             != NGX_OK)
3053         {
3054             return NGX_CONF_ERROR;
3055         }
3056     }
3057
3058     if (conf->err_log == NULL) {
3059         if (prev->err_log) {
3060             conf->err_log = prev->err_log;
3061         } else {
3062             conf->err_log = cf->cycle->new_log;
3063         }
3064     }
3065
3066     if (conf->error_pages == NULL && prev->error_pages) {
3067         conf->error_pages = prev->error_pages;
3068     }
3069
3070     ngx_conf_merge_str_value(conf->default_type,
3071                               prev->default_type, "text/plain");
3072
3073     ngx_conf_merge_off_value(conf->client_max_body_size,
3074                               prev->client_max_body_size, 1 * 1024 * 1024);
3075     ngx_conf_merge_size_value(conf->client_body_buffer_size,
3076                               prev->client_body_buffer_size,
3077                               (size_t) 2 * ngx_pagesize);
3078     ngx_conf_merge_msec_value(conf->client_body_timeout,
3079                               prev->client_body_timeout, 60000);
3080
3081     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3082                               NGX_HTTP_SATISFY_ALL);
3083     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3084                               NGX_HTTP_IMS_EXACT);
3085     ngx_conf_merge_value(conf->internal, prev->internal, 0);
3086     ngx_conf_merge_value(conf->client_body_in_file_only,
3087                               prev->client_body_in_file_only, 0);
3088     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3089     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3090                               prev->sendfile_max_chunk, 0);
3091     ngx_conf_merge_off_value(conf->directio, prev->directio,
3092                               NGX_MAX_OFF_T_VALUE);
3093     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3094     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3095
3096     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3097     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3098     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3099                               1460);
3100     ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3101     ngx_conf_merge_msec_value(conf->keepalive_timeout,
3102                               prev->keepalive_timeout, 75000);
3103     ngx_conf_merge_sec_value(conf->keepalive_header,
3104                               prev->keepalive_header, 0);
3105     ngx_conf_merge_msec_value(conf->lingering_time,
3106                               prev->lingering_time, 30000);
3107     ngx_conf_merge_msec_value(conf->lingering_timeout,
3108                               prev->lingering_timeout, 5000);
3109     ngx_conf_merge_msec_value(conf->resolver_timeout,
3110                               prev->resolver_timeout, 30000);
3111
3112     if (conf->resolver == NULL) {
3113
3114         if (prev->resolver == NULL) {
3115
3116             /*
3117              * create dummy resolver in http {} context
3118              * to inherit it in all servers
3119              */
3120
3121             prev->resolver = ngx_resolver_create(cf, NULL);
3122             if (prev->resolver == NULL) {
3123                 return NGX_CONF_ERROR;
3124             }
3125         }
3126
3127         conf->resolver = prev->resolver;
3128     }
3129
3130     ngx_conf_merge_path_value(conf->client_body_temp_path,
3131                               prev->client_body_temp_path,
3132                               NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
3133                               ngx_garbage_collector_temp_handler, cf);
3134
3135     ngx_conf_merge_value(conf->reset_timedout_connection,
3136                               prev->reset_timedout_connection, 0);
3137     ngx_conf_merge_value(conf->server_name_in_redirect,
3138                               prev->server_name_in_redirect, 1);
3139     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3140     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3141     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3142     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3143     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3144     ngx_conf_merge_value(conf->recursive_error_pages,
3145                               prev->recursive_error_pages, 0);
3146     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
3147
3148     ngx_conf_merge_ptr_value(conf->open_file_cache,
3149                               prev->open_file_cache, NULL);
3150
3151     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3152                               prev->open_file_cache_valid, 60);
3153
3154     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3155                               prev->open_file_cache_min_uses, 1);
3156
3157     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3158                               prev->open_file_cache_errors, 0);
3159
3160     ngx_conf_merge_sec_value(conf->open_file_cache_events,
3161                               prev->open_file_cache_events, 0);
3162 #if (NGX_HTTP_GZIP)
3163
3164     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3165     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3166                               NGX_HTTP_VERSION_11);
3167     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3168                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3169
3170 #if (NGX_PCRE)
3171     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3172 #endif
3173
3174     if (conf->gzip_disable_msie6 == 3) {
3175         conf->gzip_disable_msie6 =
3176             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3177     }
3178
3179 #endif
3180
3181     return NGX_CONF_OK;
3182 }
3183
3184
3185 static char *
3186 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3187 {
3188     ngx_http_core_srv_conf_t *scf = conf;
3189
3190     ngx_str_t          *value, size;
3191     ngx_url_t           u;
3192     ngx_uint_t          n;
3193     ngx_http_listen_t  *ls;
3194
3195     /*
3196      * TODO: check duplicate 'listen' directives,
3197      *       add resolved name to server names ???
3198      */
3199
3200     value = cf->args->elts;
3201
3202     ngx_memzero(&u, sizeof(ngx_url_t));
3203
3204     u.url = value[1];
3205     u.listen = 1;
3206     u.default_port = 80;
3207
3208     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3209         if (u.err) {
3210             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3211                                "%s in \"%V\" of the \"listen\" directive",
3212                                u.err, &u.url);
3213         }
3214
3215         return NGX_CONF_ERROR;
3216     }
3217
3218     ls = ngx_array_push(&scf->listen);
3219     if (ls == NULL) {
3220         return NGX_CONF_ERROR;
3221     }
3222
3223     ngx_memzero(ls, sizeof(ngx_http_listen_t));
3224
3225     ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
3226
3227     ls->socklen = u.socklen;
3228     ls->file_name = cf->conf_file->file.name.data;
3229     ls->line = cf->conf_file->line;
3230     ls->conf.backlog = NGX_LISTEN_BACKLOG;
3231     ls->conf.rcvbuf = -1;
3232     ls->conf.sndbuf = -1;
3233     ls->conf.wildcard = u.wildcard;
3234
3235     (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr,
3236                          NGX_SOCKADDR_STRLEN, 1);
3237
3238     if (cf->args->nelts == 2) {
3239         return NGX_CONF_OK;
3240     }
3241
3242     if (ngx_strcmp(value[2].data, "default") == 0) {
3243         ls->conf.default_server = 1;
3244         n = 3;
3245
3246     } else {
3247         n = 2;
3248     }
3249
3250     for ( /* void */ ; n < cf->args->nelts; n++) {
3251
3252         if (ls->conf.default_server == 0) {
3253             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3254                                "\"%V\" parameter can be specified for "
3255                                "the default \"listen\" directive only",
3256                                &value[n]);
3257             return NGX_CONF_ERROR;
3258         }
3259
3260         if (ngx_strcmp(value[n].data, "bind") == 0) {
3261             ls->conf.bind = 1;
3262             continue;
3263         }
3264
3265         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
3266             ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
3267             ls->conf.bind = 1;
3268
3269             if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
3270                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3271                                    "invalid backlog \"%V\"", &value[n]);
3272                 return NGX_CONF_ERROR;
3273             }
3274
3275             continue;
3276         }
3277
3278         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
3279             size.len = value[n].len - 7;
3280             size.data = value[n].data + 7;
3281
3282             ls->conf.rcvbuf = ngx_parse_size(&size);
3283             ls->conf.bind = 1;
3284
3285             if (ls->conf.rcvbuf == NGX_ERROR) {
3286                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3287                                    "invalid rcvbuf \"%V\"", &value[n]);
3288                 return NGX_CONF_ERROR;
3289             }
3290
3291             continue;
3292         }
3293
3294         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
3295             size.len = value[n].len - 7;
3296             size.data = value[n].data + 7;
3297
3298             ls->conf.sndbuf = ngx_parse_size(&size);
3299             ls->conf.bind = 1;
3300
3301             if (ls->conf.sndbuf == NGX_ERROR) {
3302                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3303                                    "invalid sndbuf \"%V\"", &value[n]);
3304                 return NGX_CONF_ERROR;
3305             }
3306
3307             continue;
3308         }
3309
3310         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
3311 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
3312             ls->conf.accept_filter = (char *) &value[n].data[14];
3313             ls->conf.bind = 1;
3314 #else
3315             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3316                                "accept filters \"%V\" are not supported "
3317                                "on this platform, ignored",
3318                                &value[n]);
3319 #endif
3320             continue;
3321         }
3322
3323         if (ngx_strcmp(value[n].data, "deferred") == 0) {
3324 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
3325             ls->conf.deferred_accept = 1;
3326             ls->conf.bind = 1;
3327 #else
3328             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3329                                "the deferred accept is not supported "
3330                                "on this platform, ignored");
3331 #endif
3332             continue;
3333         }
3334
3335         if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
3336 #if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
3337             struct sockaddr  *sa;
3338
3339             sa = (struct sockaddr *) ls->sockaddr;
3340
3341             if (sa->sa_family == AF_INET6) {
3342
3343                 if (ngx_strcmp(&value[n].data[10], "n") == 0) {
3344                     ls->conf.ipv6only = 1;
3345
3346                 } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) {
3347                     ls->conf.ipv6only = 2;
3348
3349                 } else {
3350                     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3351                                        "invalid ipv6only flags \"%s\"",
3352                                        &value[n].data[9]);
3353                     return NGX_CONF_ERROR;
3354                 }
3355
3356                 ls->conf.bind = 1;
3357
3358             } else {
3359                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3360                                    "ipv6only is not supported "
3361                                    "on addr \"%s\", ignored",
3362                                    ls->conf.addr);
3363             }
3364
3365             continue;
3366 #else
3367             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3368                                "bind ipv6only is not supported "
3369                                "on this platform");
3370             return NGX_CONF_ERROR;
3371 #endif
3372         }
3373
3374         if (ngx_strcmp(value[n].data, "ssl") == 0) {
3375 #if (NGX_HTTP_SSL)
3376             ls->conf.ssl = 1;
3377             continue;
3378 #else
3379             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3380                                "the \"ssl\" parameter requires "
3381                                "ngx_http_ssl_module");
3382             return NGX_CONF_ERROR;
3383 #endif
3384         }
3385
3386         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3387                            "the invalid \"%V\" parameter", &value[n]);
3388         return NGX_CONF_ERROR;
3389     }
3390
3391     return NGX_CONF_OK;
3392 }
3393
3394
3395 static char *
3396 ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3397 {
3398     ngx_http_core_srv_conf_t *cscf = conf;
3399
3400     u_char                   ch;
3401     ngx_str_t               *value, name;
3402     ngx_uint_t               i;
3403     ngx_http_server_name_t  *sn;
3404
3405     value = cf->args->elts;
3406
3407     ch = value[1].data[0];
3408
3409     if (cscf->server_name.data == NULL) {
3410         if (value[1].len) {
3411             name = value[1];
3412
3413             if (ch == '.') {
3414                 name.len--;
3415                 name.data++;
3416             }
3417
3418             cscf->server_name.len = name.len;
3419             cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
3420             if (cscf->server_name.data == NULL) {
3421                 return NGX_CONF_ERROR;
3422             }
3423
3424         } else {
3425             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3426                                "the first server name must not be empty");
3427             return NGX_CONF_ERROR;
3428         }
3429     }
3430
3431     for (i = 1; i < cf->args->nelts; i++) {
3432
3433         ch = value[i].data[0];
3434
3435         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
3436             || (ch == '.' && value[i].len < 2))
3437         {
3438             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3439                                "server name \"%V\" is invalid", &value[i]);
3440             return NGX_CONF_ERROR;
3441         }
3442
3443         if (ngx_strchr(value[i].data, '/')) {
3444             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3445                                "server name \"%V\" has strange symbols",
3446                                &value[i]);
3447         }
3448
3449         if (value[i].len == 1 && ch == '*') {
3450             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3451                                "\"server_name *\" is unsupported, use "
3452                                "\"server_name_in_redirect off\" instead");
3453             return NGX_CONF_ERROR;
3454         }
3455
3456         sn = ngx_array_push(&cscf->server_names);
3457         if (sn == NULL) {
3458             return NGX_CONF_ERROR;
3459         }
3460
3461 #if (NGX_PCRE)
3462         sn->regex = NULL;
3463         sn->captures = 0;
3464 #endif
3465         sn->core_srv_conf = cscf;
3466         sn->name = value[i];
3467
3468         if (value[i].data[0] != '~') {
3469             continue;
3470         }
3471
3472 #if (NGX_PCRE)
3473         {
3474         ngx_str_t  err;
3475         u_char     errstr[NGX_MAX_CONF_ERRSTR];
3476
3477         err.len = NGX_MAX_CONF_ERRSTR;
3478         err.data = errstr;
3479
3480         value[i].len--;
3481         value[i].data++;
3482
3483         sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
3484
3485         if (sn->regex == NULL) {
3486             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
3487             return NGX_CONF_ERROR;
3488         }
3489
3490         sn->captures = (ngx_regex_capture_count(sn->regex) > 0);
3491         sn->name = value[i];
3492         }
3493 #else
3494         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3495                            "the using of the regex \"%V\" "
3496                            "requires PCRE library", &value[i]);
3497
3498         return NGX_CONF_ERROR;
3499 #endif
3500     }
3501
3502     return NGX_CONF_OK;
3503 }
3504
3505
3506 static char *
3507 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3508 {
3509     ngx_http_core_loc_conf_t *lcf = conf;
3510
3511     ngx_str_t                  *value;
3512     ngx_uint_t                  alias, n;
3513     ngx_http_script_compile_t   sc;
3514
3515     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
3516
3517     if (lcf->root.data) {
3518
3519         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
3520
3521         if ((ngx_uint_t) lcf->alias == alias) {
3522             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3523                                "\"%V\" directive is duplicate",
3524                                &cmd->name);
3525         } else {
3526             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3527                                "\"%V\" directive is duplicate, "
3528                                "\"%s\" directive is specified before",
3529                                &cmd->name, lcf->alias ? "alias" : "root");
3530         }
3531
3532         return NGX_CONF_ERROR;
3533     }
3534
3535     if (lcf->named && alias) {
3536         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3537                            "the \"alias\" directive may not be used "
3538                            "inside named location");
3539
3540         return NGX_CONF_ERROR;
3541     }
3542
3543     value = cf->args->elts;
3544
3545     if (ngx_strstr(value[1].data, "$document_root")
3546         || ngx_strstr(value[1].data, "${document_root}"))
3547     {
3548         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3549                            "the $document_root variable may not be used "
3550                            "in the \"%V\" directive",
3551                            &cmd->name);
3552
3553         return NGX_CONF_ERROR;
3554     }
3555
3556     if (ngx_strstr(value[1].data, "$realpath_root")
3557         || ngx_strstr(value[1].data, "${realpath_root}"))
3558     {
3559         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3560                            "the $realpath_root variable may not be used "
3561                            "in the \"%V\" directive",
3562                            &cmd->name);
3563
3564         return NGX_CONF_ERROR;
3565     }
3566
3567     lcf->alias = alias;
3568     lcf->root = value[1];
3569
3570     if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
3571         lcf->root.len--;
3572     }
3573
3574     if (lcf->root.data[0] != '$') {
3575         if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) != NGX_OK) {
3576             return NGX_CONF_ERROR;
3577         }
3578     }
3579
3580     n = ngx_http_script_variables_count(&lcf->root);
3581
3582     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3583
3584     if (n) {
3585         sc.cf = cf;
3586         sc.source = &lcf->root;
3587         sc.lengths = &lcf->root_lengths;
3588         sc.values = &lcf->root_values;
3589         sc.variables = n;
3590         sc.complete_lengths = 1;
3591         sc.complete_values = 1;
3592
3593         if (ngx_http_script_compile(&sc) != NGX_OK) {
3594             return NGX_CONF_ERROR;
3595         }
3596     }
3597
3598 #if (NGX_PCRE)
3599
3600     if (alias && lcf->regex
3601         && (ngx_regex_capture_count(lcf->regex) <= 0 || sc.ncaptures == 0))
3602     {
3603         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3604                            "the \"alias\" directive must use captures "
3605                            "inside location given by regular expression");
3606
3607         return NGX_CONF_ERROR;
3608     }
3609
3610 #endif
3611
3612     return NGX_CONF_OK;
3613 }
3614
3615
3616 static ngx_http_method_name_t  ngx_methods_names[] = {
3617    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
3618    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
3619    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
3620    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
3621    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
3622    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
3623    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
3624    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
3625    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
3626    { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
3627    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
3628    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
3629    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
3630    { NULL, 0 }
3631 };
3632
3633
3634 static char *
3635 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3636 {
3637     ngx_http_core_loc_conf_t *pclcf = conf;
3638
3639     char                      *rv;
3640     void                      *mconf;
3641     ngx_str_t                 *value;
3642     ngx_uint_t                 i;
3643     ngx_conf_t                 save;
3644     ngx_http_module_t         *module;
3645     ngx_http_conf_ctx_t       *ctx, *pctx;
3646     ngx_http_method_name_t    *name;
3647     ngx_http_core_loc_conf_t  *clcf;
3648
3649     if (pclcf->limit_except) {
3650         return "duplicate";
3651     }
3652
3653     pclcf->limit_except = 0xffffffff;
3654
3655     value = cf->args->elts;
3656
3657     for (i = 1; i < cf->args->nelts; i++) {
3658         for (name = ngx_methods_names; name->name; name++) {
3659
3660             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
3661                 pclcf->limit_except &= name->method;
3662                 goto next;
3663             }
3664         }
3665
3666         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3667                            "invalid method \"%V\"", &value[i]);
3668         return NGX_CONF_ERROR;
3669
3670     next:
3671         continue;
3672     }
3673
3674     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
3675         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
3676     }
3677
3678     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3679     if (ctx == NULL) {
3680         return NGX_CONF_ERROR;
3681     }
3682
3683     pctx = cf->ctx;
3684     ctx->main_conf = pctx->main_conf;
3685     ctx->srv_conf = pctx->srv_conf;
3686
3687     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
3688     if (ctx->loc_conf == NULL) {
3689         return NGX_CONF_ERROR;
3690     }
3691
3692     for (i = 0; ngx_modules[i]; i++) {
3693         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
3694             continue;
3695         }
3696
3697         module = ngx_modules[i]->ctx;
3698
3699         if (module->create_loc_conf) {
3700
3701             mconf = module->create_loc_conf(cf);
3702             if (mconf == NULL) {
3703                  return NGX_CONF_ERROR;
3704             }
3705
3706             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
3707         }
3708     }
3709
3710
3711     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
3712     pclcf->limit_except_loc_conf = ctx->loc_conf;
3713     clcf->loc_conf = ctx->loc_conf;
3714     clcf->name = pclcf->name;
3715     clcf->noname = 1;
3716
3717     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
3718         return NGX_CONF_ERROR;
3719     }
3720
3721     save = *cf;
3722     cf->ctx = ctx;
3723     cf->cmd_type = NGX_HTTP_LMT_CONF;
3724
3725     rv = ngx_conf_parse(cf, NULL);
3726
3727     *cf = save;
3728
3729     return rv;
3730 }
3731
3732
3733 static char *
3734 ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3735 {
3736     ngx_http_core_loc_conf_t *clcf = conf;
3737
3738     ngx_str_t  *value;
3739
3740     if (clcf->directio != NGX_CONF_UNSET) {
3741         return "is duplicate";
3742     }
3743
3744     value = cf->args->elts;
3745
3746     if (ngx_strcmp(value[1].data, "off") == 0) {
3747         clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
3748         return NGX_CONF_OK;
3749     }
3750
3751     clcf->directio = ngx_parse_offset(&value[1]);
3752     if (clcf->directio == (off_t) NGX_ERROR) {
3753         return "invalid value";
3754     }
3755
3756     return NGX_CONF_OK;
3757 }
3758
3759
3760 static char *
3761 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3762 {
3763     ngx_http_core_loc_conf_t *lcf = conf;
3764
3765     u_char                     *args;
3766     ngx_int_t                   overwrite;
3767     ngx_str_t                  *value, uri;
3768     ngx_uint_t                  i, n, nvar;
3769     ngx_array_t                *uri_lengths, *uri_values;
3770     ngx_http_err_page_t        *err;
3771     ngx_http_script_compile_t   sc;
3772
3773     if (lcf->error_pages == NULL) {
3774         lcf->error_pages = ngx_array_create(cf->pool, 4,
3775                                             sizeof(ngx_http_err_page_t));
3776         if (lcf->error_pages == NULL) {
3777             return NGX_CONF_ERROR;
3778         }
3779     }
3780
3781     value = cf->args->elts;
3782
3783     i = cf->args->nelts - 2;
3784
3785     if (value[i].data[0] == '=') {
3786         if (i == 1) {
3787             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3788                                "invalid value \"%V\"", &value[i]);
3789             return NGX_CONF_ERROR;
3790         }
3791
3792         if (value[i].len > 1) {
3793             overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
3794
3795             if (overwrite == NGX_ERROR) {
3796                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3797                                    "invalid value \"%V\"", &value[i]);
3798                 return NGX_CONF_ERROR;
3799             }
3800
3801         } else {
3802             overwrite = 0;
3803         }
3804
3805         n = 2;
3806
3807     } else {
3808         overwrite = -1;
3809         n = 1;
3810     }
3811
3812     uri = value[cf->args->nelts - 1];
3813     uri_lengths = NULL;
3814     uri_values = NULL;
3815
3816     nvar = ngx_http_script_variables_count(&uri);
3817
3818     if (nvar) {
3819         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3820
3821         sc.cf = cf;
3822         sc.source = &uri;
3823         sc.lengths = &uri_lengths;
3824         sc.values = &uri_values;
3825         sc.variables = nvar;
3826         sc.complete_lengths = 1;
3827         sc.complete_values = 1;
3828
3829         if (ngx_http_script_compile(&sc) != NGX_OK) {
3830             return NGX_CONF_ERROR;
3831         }
3832     }
3833
3834     args = (u_char *) ngx_strchr(uri.data, '?');
3835
3836     for (i = 1; i < cf->args->nelts - n; i++) {
3837         err = ngx_array_push(lcf->error_pages);
3838         if (err == NULL) {
3839             return NGX_CONF_ERROR;
3840         }
3841
3842         err->status = ngx_atoi(value[i].data, value[i].len);
3843
3844         if (err->status == NGX_ERROR || err->status == 499) {
3845             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3846                                "invalid value \"%V\"", &value[i]);
3847             return NGX_CONF_ERROR;
3848         }
3849
3850         if (err->status < 400 || err->status > 599) {
3851             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3852                                "value \"%V\" must be between 400 and 599",
3853                                &value[i]);
3854             return NGX_CONF_ERROR;
3855         }
3856
3857         if (overwrite >= 0) {
3858             err->overwrite = overwrite;
3859
3860         } else {
3861             switch (err->status) {
3862                 case NGX_HTTP_TO_HTTPS:
3863                 case NGX_HTTPS_CERT_ERROR:
3864                 case NGX_HTTPS_NO_CERT:
3865                     err->overwrite = NGX_HTTP_BAD_REQUEST;
3866                     break;
3867
3868                 default:
3869                     err->overwrite = err->status;
3870                     break;
3871             }
3872         }
3873
3874         if (args) {
3875             err->uri.len = args - uri.data;
3876             err->uri.data = uri.data;
3877             args++;
3878             err->args.len = (uri.data + uri.len) - args;
3879             err->args.data = args;
3880
3881         } else {
3882             err->uri = uri;
3883             err->args.len = 0;
3884             err->args.data = NULL;
3885         }
3886
3887         err->uri_lengths = uri_lengths;
3888         err->uri_values = uri_values;
3889     }
3890
3891     return NGX_CONF_OK;
3892 }
3893
3894
3895 static char *
3896 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3897 {
3898     ngx_http_core_loc_conf_t *clcf = conf;
3899
3900     ngx_str_t                  *value;
3901     ngx_uint_t                  i, n;
3902     ngx_http_try_file_t        *tf;
3903     ngx_http_script_compile_t   sc;
3904     ngx_http_core_main_conf_t  *cmcf;
3905
3906     if (clcf->try_files) {
3907         return "is duplicate";
3908     }
3909
3910     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
3911
3912     cmcf->try_files = 1;
3913
3914     tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
3915     if (tf == NULL) {
3916         return NGX_CONF_ERROR;
3917     }
3918
3919     clcf->try_files = tf;
3920
3921     value = cf->args->elts;
3922
3923     for (i = 0; i < cf->args->nelts - 1; i++) {
3924
3925         tf[i].name = value[i + 1];
3926
3927         if (tf[i].name.data[tf[i].name.len - 1] == '/') {
3928             tf[i].test_dir = 1;
3929             tf[i].name.len--;
3930         }
3931
3932         n = ngx_http_script_variables_count(&tf[i].name);
3933
3934         if (n) {
3935             ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3936
3937             sc.cf = cf;
3938             sc.source = &tf[i].name;
3939             sc.lengths = &tf[i].lengths;
3940             sc.values = &tf[i].values;
3941             sc.variables = n;
3942             sc.complete_lengths = 1;
3943             sc.complete_values = 1;
3944
3945             if (ngx_http_script_compile(&sc) != NGX_OK) {
3946                 return NGX_CONF_ERROR;
3947             }
3948
3949         } else {
3950             /* add trailing '\0' to length */
3951             tf[i].name.len++;
3952         }
3953     }
3954
3955     return NGX_CONF_OK;
3956 }
3957
3958
3959 static char *
3960 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3961 {
3962     ngx_http_core_loc_conf_t *lcf = conf;
3963
3964     time_t       inactive;
3965     ngx_str_t   *value, s;
3966     ngx_int_t    max;
3967     ngx_uint_t   i;
3968
3969     if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) {
3970         return "is duplicate";
3971     }
3972
3973     value = cf->args->elts;
3974
3975     max = 0;
3976     inactive = 60;
3977
3978     for (i = 1; i < cf->args->nelts; i++) {
3979
3980         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
3981
3982             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
3983             if (max == NGX_ERROR) {
3984                 goto failed;
3985             }
3986
3987             continue;
3988         }
3989
3990         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
3991
3992             s.len = value[i].len - 9;
3993             s.data = value[i].data + 9;
3994
3995             inactive = ngx_parse_time(&s, 1);
3996             if (inactive < 0) {
3997                 goto failed;
3998             }
3999
4000             continue;
4001         }
4002
4003         if (ngx_strcmp(value[i].data, "off") == 0) {
4004
4005             lcf->open_file_cache = NULL;
4006
4007             continue;
4008         }
4009
4010     failed:
4011
4012         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4013                            "invalid \"open_file_cache\" parameter \"%V\"",
4014                            &value[i]);
4015         return NGX_CONF_ERROR;
4016     }
4017
4018     if (lcf->open_file_cache == NULL) {
4019         return NGX_CONF_OK;
4020     }
4021
4022     if (max == 0) {
4023         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4024                            "\"open_file_cache\" must have \"max\" parameter");
4025         return NGX_CONF_ERROR;
4026     }
4027
4028     lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
4029     if (lcf->open_file_cache) {
4030         return NGX_CONF_OK;
4031     }
4032
4033     return NGX_CONF_ERROR;
4034 }
4035
4036
4037 static char *
4038 ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4039 {
4040     ngx_http_core_loc_conf_t *lcf = conf;
4041
4042     lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
4043     if (lcf->err_log == NULL) {
4044         return NGX_CONF_ERROR;
4045     }
4046
4047     return ngx_set_error_log_levels(cf, lcf->err_log);
4048 }
4049
4050
4051 static char *
4052 ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4053 {
4054     ngx_http_core_loc_conf_t *lcf = conf;
4055
4056     ngx_str_t  *value;
4057
4058     if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
4059         return "is duplicate";
4060     }
4061
4062     value = cf->args->elts;
4063
4064     lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
4065
4066     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
4067         return "invalid value";
4068     }
4069
4070     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
4071         return "value must be less than 597 hours";
4072     }
4073
4074     if (cf->args->nelts == 2) {
4075         return NGX_CONF_OK;
4076     }
4077
4078     lcf->keepalive_header = ngx_parse_time(&value[2], 1);
4079
4080     if (lcf->keepalive_header == NGX_ERROR) {
4081         return "invalid value";
4082     }
4083
4084     if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
4085         return "value must be less than 68 years";
4086     }
4087
4088     return NGX_CONF_OK;
4089 }
4090
4091
4092 static char *
4093 ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4094 {
4095     ngx_http_core_loc_conf_t *lcf = conf;
4096
4097     if (lcf->internal != NGX_CONF_UNSET) {
4098         return "is duplicate";
4099     }
4100
4101     lcf->internal = 1;
4102
4103     return NGX_CONF_OK;
4104 }
4105
4106
4107 static char *
4108 ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4109 {
4110     ngx_http_core_loc_conf_t  *clcf = conf;
4111
4112     ngx_url_t   u;
4113     ngx_str_t  *value;
4114
4115     if (clcf->resolver) {
4116         return "is duplicate";
4117     }
4118
4119     value = cf->args->elts;
4120
4121     ngx_memzero(&u, sizeof(ngx_url_t));
4122
4123     u.host = value[1];
4124     u.port = 53;
4125
4126     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
4127         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
4128         return NGX_CONF_ERROR;
4129     }
4130
4131     clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
4132     if (clcf->resolver == NULL) {
4133         return NGX_OK;
4134     }
4135
4136     return NGX_CONF_OK;
4137 }
4138
4139
4140 #if (NGX_HTTP_GZIP)
4141
4142 static char *
4143 ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4144 {
4145     ngx_http_core_loc_conf_t  *clcf = conf;
4146
4147 #if (NGX_PCRE)
4148
4149     ngx_str_t         err, *value;
4150     ngx_uint_t        i;
4151     ngx_regex_elt_t  *re;
4152     u_char            errstr[NGX_MAX_CONF_ERRSTR];
4153
4154     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
4155         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
4156                                               sizeof(ngx_regex_elt_t));
4157         if (clcf->gzip_disable == NULL) {
4158             return NGX_CONF_ERROR;
4159         }
4160     }
4161
4162     value = cf->args->elts;
4163
4164     err.len = NGX_MAX_CONF_ERRSTR;
4165     err.data = errstr;
4166
4167     for (i = 1; i < cf->args->nelts; i++) {
4168
4169         if (ngx_strcmp(value[1].data, "msie6") == 0) {
4170             clcf->gzip_disable_msie6 = 1;
4171             continue;
4172         }
4173
4174         re = ngx_array_push(clcf->gzip_disable);
4175         if (re == NULL) {
4176             return NGX_CONF_ERROR;
4177         }
4178
4179         re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
4180                                       &err);
4181
4182         if (re->regex == NULL) {
4183             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
4184             return NGX_CONF_ERROR;
4185         }
4186
4187         re->name = value[i].data;
4188     }
4189
4190     return NGX_CONF_OK;
4191
4192 #else
4193     ngx_str_t  *value;
4194
4195     value = cf->args->elts;
4196
4197     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) {
4198         clcf->gzip_disable_msie6 = 1;
4199         return NGX_CONF_OK;
4200     }
4201
4202     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4203                        "without PCRE library \"gzip_disable\" supports "
4204                        "builtin \"msie6\" mask only");
4205
4206     return NGX_CONF_ERROR;
4207 #endif
4208 }
4209
4210 #endif
4211
4212
4213 static char *
4214 ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
4215 {
4216 #if (NGX_FREEBSD)
4217     ssize_t *np = data;
4218
4219     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
4220         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4221                            "\"send_lowat\" must be less than %d "
4222                            "(sysctl net.inet.tcp.sendspace)",
4223                            ngx_freebsd_net_inet_tcp_sendspace);
4224
4225         return NGX_CONF_ERROR;
4226     }
4227
4228 #elif !(NGX_HAVE_SO_SNDLOWAT)
4229     ssize_t *np = data;
4230
4231     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4232                        "\"send_lowat\" is not supported, ignored");
4233
4234     *np = 0;
4235
4236 #endif
4237
4238     return NGX_CONF_OK;
4239 }
4240
4241
4242 static char *
4243 ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
4244 {
4245     size_t *sp = data;
4246
4247     if (*sp < NGX_MIN_POOL_SIZE) {
4248         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4249                            "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
4250
4251         return NGX_CONF_ERROR;
4252     }
4253
4254     return NGX_CONF_OK;
4255 }