1
2/*
3 * Copyright (C) Igor Sysoev
4 * Copyright (C) Nginx, Inc.
5 */
6
7
8#include <ngx_config.h>
9#include <ngx_core.h>
10#include <ngx_http.h>
11
12
13typedef struct {
14    u_char    *name;
15    uint32_t   method;
16} ngx_http_method_name_t;
17
18
19#define NGX_HTTP_REQUEST_BODY_FILE_OFF    0
20#define NGX_HTTP_REQUEST_BODY_FILE_ON     1
21#define NGX_HTTP_REQUEST_BODY_FILE_CLEAN  2
22
23
24static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
25static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
26    ngx_http_location_tree_node_t *node);
27
28static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
29static ngx_int_t ngx_http_core_postconfiguration(ngx_conf_t *cf);
30static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
31static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
32static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
33static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf,
34    void *parent, void *child);
35static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf);
36static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
37    void *parent, void *child);
38
39static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
40    void *dummy);
41static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd,
42    void *dummy);
43static ngx_int_t ngx_http_core_regex_location(ngx_conf_t *cf,
44    ngx_http_core_loc_conf_t *clcf, ngx_str_t *regex, ngx_uint_t caseless);
45
46static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd,
47    void *conf);
48static char *ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy,
49    void *conf);
50
51static char *ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
52    void *conf);
53static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
54    void *conf);
55static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
56static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
57    void *conf);
58static char *ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd,
59    void *conf);
60static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
61    void *conf);
62static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
63    void *conf);
64static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd,
65    void *conf);
66static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
67    void *conf);
68static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
69    void *conf);
70static char *ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
71    void *conf);
72static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
73    void *conf);
74static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
75    void *conf);
76#if (NGX_HTTP_GZIP)
77static ngx_int_t ngx_http_gzip_accept_encoding(ngx_str_t *ae);
78static ngx_uint_t ngx_http_gzip_quantity(u_char *p, u_char *last);
79static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
80    void *conf);
81#endif
82static ngx_int_t ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r,
83    ngx_addr_t *addr, u_char *xff, size_t xfflen, ngx_array_t *proxies,
84    int recursive);
85#if (NGX_HAVE_OPENAT)
86static char *ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd,
87    void *conf);
88#endif
89
90static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
91static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data);
92
93static ngx_conf_post_t  ngx_http_core_lowat_post =
94    { ngx_http_core_lowat_check };
95
96static ngx_conf_post_handler_pt  ngx_http_core_pool_size_p =
97    ngx_http_core_pool_size;
98
99
100static ngx_conf_enum_t  ngx_http_core_request_body_in_file[] = {
101    { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF },
102    { ngx_string("on"), NGX_HTTP_REQUEST_BODY_FILE_ON },
103    { ngx_string("clean"), NGX_HTTP_REQUEST_BODY_FILE_CLEAN },
104    { ngx_null_string, 0 }
105};
106
107
108static ngx_conf_enum_t  ngx_http_core_satisfy[] = {
109    { ngx_string("all"), NGX_HTTP_SATISFY_ALL },
110    { ngx_string("any"), NGX_HTTP_SATISFY_ANY },
111    { ngx_null_string, 0 }
112};
113
114
115static ngx_conf_enum_t  ngx_http_core_lingering_close[] = {
116    { ngx_string("off"), NGX_HTTP_LINGERING_OFF },
117    { ngx_string("on"), NGX_HTTP_LINGERING_ON },
118    { ngx_string("always"), NGX_HTTP_LINGERING_ALWAYS },
119    { ngx_null_string, 0 }
120};
121
122
123static ngx_conf_enum_t  ngx_http_core_server_tokens[] = {
124    { ngx_string("off"), NGX_HTTP_SERVER_TOKENS_OFF },
125    { ngx_string("on"), NGX_HTTP_SERVER_TOKENS_ON },
126    { ngx_string("build"), NGX_HTTP_SERVER_TOKENS_BUILD },
127    { ngx_null_string, 0 }
128};
129
130
131static ngx_conf_enum_t  ngx_http_core_if_modified_since[] = {
132    { ngx_string("off"), NGX_HTTP_IMS_OFF },
133    { ngx_string("exact"), NGX_HTTP_IMS_EXACT },
134    { ngx_string("before"), NGX_HTTP_IMS_BEFORE },
135    { ngx_null_string, 0 }
136};
137
138
139static ngx_conf_bitmask_t  ngx_http_core_keepalive_disable[] = {
140    { ngx_string("none"), NGX_HTTP_KEEPALIVE_DISABLE_NONE },
141    { ngx_string("msie6"), NGX_HTTP_KEEPALIVE_DISABLE_MSIE6 },
142    { ngx_string("safari"), NGX_HTTP_KEEPALIVE_DISABLE_SAFARI },
143    { ngx_null_string, 0 }
144};
145
146
147static ngx_path_init_t  ngx_http_client_temp_path = {
148    ngx_string(NGX_HTTP_CLIENT_TEMP_PATH), { 0, 0, 0 }
149};
150
151
152#if (NGX_HTTP_GZIP)
153
154static ngx_conf_enum_t  ngx_http_gzip_http_version[] = {
155    { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
156    { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
157    { ngx_null_string, 0 }
158};
159
160
161static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
162    { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
163    { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
164    { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
165    { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
166    { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
167    { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
168    { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
169    { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
170    { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
171    { ngx_null_string, 0 }
172};
173
174
175static ngx_str_t  ngx_http_gzip_no_cache = ngx_string("no-cache");
176static ngx_str_t  ngx_http_gzip_no_store = ngx_string("no-store");
177static ngx_str_t  ngx_http_gzip_private = ngx_string("private");
178
179#endif
180
181
182static ngx_command_t  ngx_http_core_commands[] = {
183
184    { ngx_string("variables_hash_max_size"),
185      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
186      ngx_conf_set_num_slot,
187      NGX_HTTP_MAIN_CONF_OFFSET,
188      offsetof(ngx_http_core_main_conf_t, variables_hash_max_size),
189      NULL },
190
191    { ngx_string("variables_hash_bucket_size"),
192      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
193      ngx_conf_set_num_slot,
194      NGX_HTTP_MAIN_CONF_OFFSET,
195      offsetof(ngx_http_core_main_conf_t, variables_hash_bucket_size),
196      NULL },
197
198    { ngx_string("server_names_hash_max_size"),
199      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
200      ngx_conf_set_num_slot,
201      NGX_HTTP_MAIN_CONF_OFFSET,
202      offsetof(ngx_http_core_main_conf_t, server_names_hash_max_size),
203      NULL },
204
205    { ngx_string("server_names_hash_bucket_size"),
206      NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
207      ngx_conf_set_num_slot,
208      NGX_HTTP_MAIN_CONF_OFFSET,
209      offsetof(ngx_http_core_main_conf_t, server_names_hash_bucket_size),
210      NULL },
211
212    { ngx_string("server"),
213      NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
214      ngx_http_core_server,
215      0,
216      0,
217      NULL },
218
219    { ngx_string("connection_pool_size"),
220      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
221      ngx_conf_set_size_slot,
222      NGX_HTTP_SRV_CONF_OFFSET,
223      offsetof(ngx_http_core_srv_conf_t, connection_pool_size),
224      &ngx_http_core_pool_size_p },
225
226    { ngx_string("request_pool_size"),
227      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
228      ngx_conf_set_size_slot,
229      NGX_HTTP_SRV_CONF_OFFSET,
230      offsetof(ngx_http_core_srv_conf_t, request_pool_size),
231      &ngx_http_core_pool_size_p },
232
233    { ngx_string("client_header_timeout"),
234      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
235      ngx_conf_set_msec_slot,
236      NGX_HTTP_SRV_CONF_OFFSET,
237      offsetof(ngx_http_core_srv_conf_t, client_header_timeout),
238      NULL },
239
240    { ngx_string("client_header_buffer_size"),
241      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
242      ngx_conf_set_size_slot,
243      NGX_HTTP_SRV_CONF_OFFSET,
244      offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size),
245      NULL },
246
247    { ngx_string("large_client_header_buffers"),
248      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
249      ngx_conf_set_bufs_slot,
250      NGX_HTTP_SRV_CONF_OFFSET,
251      offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
252      NULL },
253
254    { ngx_string("ignore_invalid_headers"),
255      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
256      ngx_conf_set_flag_slot,
257      NGX_HTTP_SRV_CONF_OFFSET,
258      offsetof(ngx_http_core_srv_conf_t, ignore_invalid_headers),
259      NULL },
260
261    { ngx_string("merge_slashes"),
262      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
263      ngx_conf_set_flag_slot,
264      NGX_HTTP_SRV_CONF_OFFSET,
265      offsetof(ngx_http_core_srv_conf_t, merge_slashes),
266      NULL },
267
268    { ngx_string("underscores_in_headers"),
269      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
270      ngx_conf_set_flag_slot,
271      NGX_HTTP_SRV_CONF_OFFSET,
272      offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
273      NULL },
274
275    { ngx_string("location"),
276      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
277      ngx_http_core_location,
278      NGX_HTTP_SRV_CONF_OFFSET,
279      0,
280      NULL },
281
282    { ngx_string("listen"),
283      NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
284      ngx_http_core_listen,
285      NGX_HTTP_SRV_CONF_OFFSET,
286      0,
287      NULL },
288
289    { ngx_string("server_name"),
290      NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
291      ngx_http_core_server_name,
292      NGX_HTTP_SRV_CONF_OFFSET,
293      0,
294      NULL },
295
296    { ngx_string("types_hash_max_size"),
297      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
298      ngx_conf_set_num_slot,
299      NGX_HTTP_LOC_CONF_OFFSET,
300      offsetof(ngx_http_core_loc_conf_t, types_hash_max_size),
301      NULL },
302
303    { ngx_string("types_hash_bucket_size"),
304      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
305      ngx_conf_set_num_slot,
306      NGX_HTTP_LOC_CONF_OFFSET,
307      offsetof(ngx_http_core_loc_conf_t, types_hash_bucket_size),
308      NULL },
309
310    { ngx_string("types"),
311      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
312                                          |NGX_CONF_BLOCK|NGX_CONF_NOARGS,
313      ngx_http_core_types,
314      NGX_HTTP_LOC_CONF_OFFSET,
315      0,
316      NULL },
317
318    { ngx_string("default_type"),
319      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
320      ngx_conf_set_str_slot,
321      NGX_HTTP_LOC_CONF_OFFSET,
322      offsetof(ngx_http_core_loc_conf_t, default_type),
323      NULL },
324
325    { ngx_string("root"),
326      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
327                        |NGX_CONF_TAKE1,
328      ngx_http_core_root,
329      NGX_HTTP_LOC_CONF_OFFSET,
330      0,
331      NULL },
332
333    { ngx_string("alias"),
334      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
335      ngx_http_core_root,
336      NGX_HTTP_LOC_CONF_OFFSET,
337      0,
338      NULL },
339
340    { ngx_string("limit_except"),
341      NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
342      ngx_http_core_limit_except,
343      NGX_HTTP_LOC_CONF_OFFSET,
344      0,
345      NULL },
346
347    { ngx_string("client_max_body_size"),
348      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
349      ngx_conf_set_off_slot,
350      NGX_HTTP_LOC_CONF_OFFSET,
351      offsetof(ngx_http_core_loc_conf_t, client_max_body_size),
352      NULL },
353
354    { ngx_string("client_body_buffer_size"),
355      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
356      ngx_conf_set_size_slot,
357      NGX_HTTP_LOC_CONF_OFFSET,
358      offsetof(ngx_http_core_loc_conf_t, client_body_buffer_size),
359      NULL },
360
361    { ngx_string("client_body_timeout"),
362      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
363      ngx_conf_set_msec_slot,
364      NGX_HTTP_LOC_CONF_OFFSET,
365      offsetof(ngx_http_core_loc_conf_t, client_body_timeout),
366      NULL },
367
368    { ngx_string("client_body_temp_path"),
369      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
370      ngx_conf_set_path_slot,
371      NGX_HTTP_LOC_CONF_OFFSET,
372      offsetof(ngx_http_core_loc_conf_t, client_body_temp_path),
373      NULL },
374
375    { ngx_string("client_body_in_file_only"),
376      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
377      ngx_conf_set_enum_slot,
378      NGX_HTTP_LOC_CONF_OFFSET,
379      offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only),
380      &ngx_http_core_request_body_in_file },
381
382    { ngx_string("client_body_in_single_buffer"),
383      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
384      ngx_conf_set_flag_slot,
385      NGX_HTTP_LOC_CONF_OFFSET,
386      offsetof(ngx_http_core_loc_conf_t, client_body_in_single_buffer),
387      NULL },
388
389    { ngx_string("sendfile"),
390      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
391                        |NGX_CONF_FLAG,
392      ngx_conf_set_flag_slot,
393      NGX_HTTP_LOC_CONF_OFFSET,
394      offsetof(ngx_http_core_loc_conf_t, sendfile),
395      NULL },
396
397    { ngx_string("sendfile_max_chunk"),
398      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
399      ngx_conf_set_size_slot,
400      NGX_HTTP_LOC_CONF_OFFSET,
401      offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk),
402      NULL },
403
404    { ngx_string("aio"),
405      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
406      ngx_http_core_set_aio,
407      NGX_HTTP_LOC_CONF_OFFSET,
408      0,
409      NULL },
410
411    { ngx_string("aio_write"),
412      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
413      ngx_conf_set_flag_slot,
414      NGX_HTTP_LOC_CONF_OFFSET,
415      offsetof(ngx_http_core_loc_conf_t, aio_write),
416      NULL },
417
418    { ngx_string("read_ahead"),
419      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
420      ngx_conf_set_size_slot,
421      NGX_HTTP_LOC_CONF_OFFSET,
422      offsetof(ngx_http_core_loc_conf_t, read_ahead),
423      NULL },
424
425    { ngx_string("directio"),
426      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
427      ngx_http_core_directio,
428      NGX_HTTP_LOC_CONF_OFFSET,
429      0,
430      NULL },
431
432    { ngx_string("directio_alignment"),
433      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
434      ngx_conf_set_off_slot,
435      NGX_HTTP_LOC_CONF_OFFSET,
436      offsetof(ngx_http_core_loc_conf_t, directio_alignment),
437      NULL },
438
439    { ngx_string("tcp_nopush"),
440      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
441      ngx_conf_set_flag_slot,
442      NGX_HTTP_LOC_CONF_OFFSET,
443      offsetof(ngx_http_core_loc_conf_t, tcp_nopush),
444      NULL },
445
446    { ngx_string("tcp_nodelay"),
447      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
448      ngx_conf_set_flag_slot,
449      NGX_HTTP_LOC_CONF_OFFSET,
450      offsetof(ngx_http_core_loc_conf_t, tcp_nodelay),
451      NULL },
452
453    { ngx_string("send_timeout"),
454      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
455      ngx_conf_set_msec_slot,
456      NGX_HTTP_LOC_CONF_OFFSET,
457      offsetof(ngx_http_core_loc_conf_t, send_timeout),
458      NULL },
459
460    { ngx_string("send_lowat"),
461      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
462      ngx_conf_set_size_slot,
463      NGX_HTTP_LOC_CONF_OFFSET,
464      offsetof(ngx_http_core_loc_conf_t, send_lowat),
465      &ngx_http_core_lowat_post },
466
467    { ngx_string("postpone_output"),
468      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
469      ngx_conf_set_size_slot,
470      NGX_HTTP_LOC_CONF_OFFSET,
471      offsetof(ngx_http_core_loc_conf_t, postpone_output),
472      NULL },
473
474    { ngx_string("limit_rate"),
475      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
476                        |NGX_CONF_TAKE1,
477      ngx_conf_set_size_slot,
478      NGX_HTTP_LOC_CONF_OFFSET,
479      offsetof(ngx_http_core_loc_conf_t, limit_rate),
480      NULL },
481
482    { ngx_string("limit_rate_after"),
483      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
484                        |NGX_CONF_TAKE1,
485      ngx_conf_set_size_slot,
486      NGX_HTTP_LOC_CONF_OFFSET,
487      offsetof(ngx_http_core_loc_conf_t, limit_rate_after),
488      NULL },
489
490    { ngx_string("keepalive_timeout"),
491      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
492      ngx_http_core_keepalive,
493      NGX_HTTP_LOC_CONF_OFFSET,
494      0,
495      NULL },
496
497    { ngx_string("keepalive_requests"),
498      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
499      ngx_conf_set_num_slot,
500      NGX_HTTP_LOC_CONF_OFFSET,
501      offsetof(ngx_http_core_loc_conf_t, keepalive_requests),
502      NULL },
503
504    { ngx_string("keepalive_disable"),
505      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
506      ngx_conf_set_bitmask_slot,
507      NGX_HTTP_LOC_CONF_OFFSET,
508      offsetof(ngx_http_core_loc_conf_t, keepalive_disable),
509      &ngx_http_core_keepalive_disable },
510
511    { ngx_string("satisfy"),
512      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
513      ngx_conf_set_enum_slot,
514      NGX_HTTP_LOC_CONF_OFFSET,
515      offsetof(ngx_http_core_loc_conf_t, satisfy),
516      &ngx_http_core_satisfy },
517
518    { ngx_string("internal"),
519      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
520      ngx_http_core_internal,
521      NGX_HTTP_LOC_CONF_OFFSET,
522      0,
523      NULL },
524
525    { ngx_string("lingering_close"),
526      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
527      ngx_conf_set_enum_slot,
528      NGX_HTTP_LOC_CONF_OFFSET,
529      offsetof(ngx_http_core_loc_conf_t, lingering_close),
530      &ngx_http_core_lingering_close },
531
532    { ngx_string("lingering_time"),
533      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
534      ngx_conf_set_msec_slot,
535      NGX_HTTP_LOC_CONF_OFFSET,
536      offsetof(ngx_http_core_loc_conf_t, lingering_time),
537      NULL },
538
539    { ngx_string("lingering_timeout"),
540      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
541      ngx_conf_set_msec_slot,
542      NGX_HTTP_LOC_CONF_OFFSET,
543      offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
544      NULL },
545
546    { ngx_string("reset_timedout_connection"),
547      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
548      ngx_conf_set_flag_slot,
549      NGX_HTTP_LOC_CONF_OFFSET,
550      offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
551      NULL },
552
553    { ngx_string("absolute_redirect"),
554      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
555      ngx_conf_set_flag_slot,
556      NGX_HTTP_LOC_CONF_OFFSET,
557      offsetof(ngx_http_core_loc_conf_t, absolute_redirect),
558      NULL },
559
560    { ngx_string("server_name_in_redirect"),
561      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
562      ngx_conf_set_flag_slot,
563      NGX_HTTP_LOC_CONF_OFFSET,
564      offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
565      NULL },
566
567    { ngx_string("port_in_redirect"),
568      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
569      ngx_conf_set_flag_slot,
570      NGX_HTTP_LOC_CONF_OFFSET,
571      offsetof(ngx_http_core_loc_conf_t, port_in_redirect),
572      NULL },
573
574    { ngx_string("msie_padding"),
575      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
576      ngx_conf_set_flag_slot,
577      NGX_HTTP_LOC_CONF_OFFSET,
578      offsetof(ngx_http_core_loc_conf_t, msie_padding),
579      NULL },
580
581    { ngx_string("msie_refresh"),
582      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
583      ngx_conf_set_flag_slot,
584      NGX_HTTP_LOC_CONF_OFFSET,
585      offsetof(ngx_http_core_loc_conf_t, msie_refresh),
586      NULL },
587
588    { ngx_string("log_not_found"),
589      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
590      ngx_conf_set_flag_slot,
591      NGX_HTTP_LOC_CONF_OFFSET,
592      offsetof(ngx_http_core_loc_conf_t, log_not_found),
593      NULL },
594
595    { ngx_string("log_subrequest"),
596      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
597      ngx_conf_set_flag_slot,
598      NGX_HTTP_LOC_CONF_OFFSET,
599      offsetof(ngx_http_core_loc_conf_t, log_subrequest),
600      NULL },
601
602    { ngx_string("recursive_error_pages"),
603      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
604      ngx_conf_set_flag_slot,
605      NGX_HTTP_LOC_CONF_OFFSET,
606      offsetof(ngx_http_core_loc_conf_t, recursive_error_pages),
607      NULL },
608
609    { ngx_string("server_tokens"),
610      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
611      ngx_conf_set_enum_slot,
612      NGX_HTTP_LOC_CONF_OFFSET,
613      offsetof(ngx_http_core_loc_conf_t, server_tokens),
614      &ngx_http_core_server_tokens },
615
616    { ngx_string("if_modified_since"),
617      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
618      ngx_conf_set_enum_slot,
619      NGX_HTTP_LOC_CONF_OFFSET,
620      offsetof(ngx_http_core_loc_conf_t, if_modified_since),
621      &ngx_http_core_if_modified_since },
622
623    { ngx_string("max_ranges"),
624      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
625      ngx_conf_set_num_slot,
626      NGX_HTTP_LOC_CONF_OFFSET,
627      offsetof(ngx_http_core_loc_conf_t, max_ranges),
628      NULL },
629
630    { ngx_string("chunked_transfer_encoding"),
631      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
632      ngx_conf_set_flag_slot,
633      NGX_HTTP_LOC_CONF_OFFSET,
634      offsetof(ngx_http_core_loc_conf_t, chunked_transfer_encoding),
635      NULL },
636
637    { ngx_string("etag"),
638      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
639      ngx_conf_set_flag_slot,
640      NGX_HTTP_LOC_CONF_OFFSET,
641      offsetof(ngx_http_core_loc_conf_t, etag),
642      NULL },
643
644    { ngx_string("error_page"),
645      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
646                        |NGX_CONF_2MORE,
647      ngx_http_core_error_page,
648      NGX_HTTP_LOC_CONF_OFFSET,
649      0,
650      NULL },
651
652    { ngx_string("try_files"),
653      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
654      ngx_http_core_try_files,
655      NGX_HTTP_LOC_CONF_OFFSET,
656      0,
657      NULL },
658
659    { ngx_string("post_action"),
660      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
661                        |NGX_CONF_TAKE1,
662      ngx_conf_set_str_slot,
663      NGX_HTTP_LOC_CONF_OFFSET,
664      offsetof(ngx_http_core_loc_conf_t, post_action),
665      NULL },
666
667    { ngx_string("error_log"),
668      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
669      ngx_http_core_error_log,
670      NGX_HTTP_LOC_CONF_OFFSET,
671      0,
672      NULL },
673
674    { ngx_string("open_file_cache"),
675      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
676      ngx_http_core_open_file_cache,
677      NGX_HTTP_LOC_CONF_OFFSET,
678      offsetof(ngx_http_core_loc_conf_t, open_file_cache),
679      NULL },
680
681    { ngx_string("open_file_cache_valid"),
682      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
683      ngx_conf_set_sec_slot,
684      NGX_HTTP_LOC_CONF_OFFSET,
685      offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid),
686      NULL },
687
688    { ngx_string("open_file_cache_min_uses"),
689      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
690      ngx_conf_set_num_slot,
691      NGX_HTTP_LOC_CONF_OFFSET,
692      offsetof(ngx_http_core_loc_conf_t, open_file_cache_min_uses),
693      NULL },
694
695    { ngx_string("open_file_cache_errors"),
696      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
697      ngx_conf_set_flag_slot,
698      NGX_HTTP_LOC_CONF_OFFSET,
699      offsetof(ngx_http_core_loc_conf_t, open_file_cache_errors),
700      NULL },
701
702    { ngx_string("open_file_cache_events"),
703      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
704      ngx_conf_set_flag_slot,
705      NGX_HTTP_LOC_CONF_OFFSET,
706      offsetof(ngx_http_core_loc_conf_t, open_file_cache_events),
707      NULL },
708
709    { ngx_string("resolver"),
710      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
711      ngx_http_core_resolver,
712      NGX_HTTP_LOC_CONF_OFFSET,
713      0,
714      NULL },
715
716    { ngx_string("resolver_timeout"),
717      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
718      ngx_conf_set_msec_slot,
719      NGX_HTTP_LOC_CONF_OFFSET,
720      offsetof(ngx_http_core_loc_conf_t, resolver_timeout),
721      NULL },
722
723#if (NGX_HTTP_GZIP)
724
725    { ngx_string("gzip_vary"),
726      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
727      ngx_conf_set_flag_slot,
728      NGX_HTTP_LOC_CONF_OFFSET,
729      offsetof(ngx_http_core_loc_conf_t, gzip_vary),
730      NULL },
731
732    { ngx_string("gzip_http_version"),
733      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
734      ngx_conf_set_enum_slot,
735      NGX_HTTP_LOC_CONF_OFFSET,
736      offsetof(ngx_http_core_loc_conf_t, gzip_http_version),
737      &ngx_http_gzip_http_version },
738
739    { ngx_string("gzip_proxied"),
740      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
741      ngx_conf_set_bitmask_slot,
742      NGX_HTTP_LOC_CONF_OFFSET,
743      offsetof(ngx_http_core_loc_conf_t, gzip_proxied),
744      &ngx_http_gzip_proxied_mask },
745
746    { ngx_string("gzip_disable"),
747      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
748      ngx_http_gzip_disable,
749      NGX_HTTP_LOC_CONF_OFFSET,
750      0,
751      NULL },
752
753#endif
754
755#if (NGX_HAVE_OPENAT)
756
757    { ngx_string("disable_symlinks"),
758      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
759      ngx_http_disable_symlinks,
760      NGX_HTTP_LOC_CONF_OFFSET,
761      0,
762      NULL },
763
764#endif
765
766      ngx_null_command
767};
768
769
770static ngx_http_module_t  ngx_http_core_module_ctx = {
771    ngx_http_core_preconfiguration,        /* preconfiguration */
772    ngx_http_core_postconfiguration,       /* postconfiguration */
773
774    ngx_http_core_create_main_conf,        /* create main configuration */
775    ngx_http_core_init_main_conf,          /* init main configuration */
776
777    ngx_http_core_create_srv_conf,         /* create server configuration */
778    ngx_http_core_merge_srv_conf,          /* merge server configuration */
779
780    ngx_http_core_create_loc_conf,         /* create location configuration */
781    ngx_http_core_merge_loc_conf           /* merge location configuration */
782};
783
784
785ngx_module_t  ngx_http_core_module = {
786    NGX_MODULE_V1,
787    &ngx_http_core_module_ctx,             /* module context */
788    ngx_http_core_commands,                /* module directives */
789    NGX_HTTP_MODULE,                       /* module type */
790    NULL,                                  /* init master */
791    NULL,                                  /* init module */
792    NULL,                                  /* init process */
793    NULL,                                  /* init thread */
794    NULL,                                  /* exit thread */
795    NULL,                                  /* exit process */
796    NULL,                                  /* exit master */
797    NGX_MODULE_V1_PADDING
798};
799
800
801ngx_str_t  ngx_http_core_get_method = { 3, (u_char *) "GET" };
802
803
804void
805ngx_http_handler(ngx_http_request_t *r)
806{
807    ngx_http_core_main_conf_t  *cmcf;
808
809    r->connection->log->action = NULL;
810
811    if (!r->internal) {
812        switch (r->headers_in.connection_type) {
813        case 0:
814            r->keepalive = (r->http_version > NGX_HTTP_VERSION_10);
815            break;
816
817        case NGX_HTTP_CONNECTION_CLOSE:
818            r->keepalive = 0;
819            break;
820
821        case NGX_HTTP_CONNECTION_KEEP_ALIVE:
822            r->keepalive = 1;
823            break;
824        }
825
826        r->lingering_close = (r->headers_in.content_length_n > 0
827                              || r->headers_in.chunked);
828        r->phase_handler = 0;
829
830    } else {
831        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
832        r->phase_handler = cmcf->phase_engine.server_rewrite_index;
833    }
834
835    r->valid_location = 1;
836#if (NGX_HTTP_GZIP)
837    r->gzip_tested = 0;
838    r->gzip_ok = 0;
839    r->gzip_vary = 0;
840#endif
841
842    r->write_event_handler = ngx_http_core_run_phases;
843    ngx_http_core_run_phases(r);
844}
845
846
847void
848ngx_http_core_run_phases(ngx_http_request_t *r)
849{
850    ngx_int_t                   rc;
851    ngx_http_phase_handler_t   *ph;
852    ngx_http_core_main_conf_t  *cmcf;
853
854    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
855
856    ph = cmcf->phase_engine.handlers;
857
858    while (ph[r->phase_handler].checker) {
859
860        rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
861
862        if (rc == NGX_OK) {
863            return;
864        }
865    }
866}
867
868
869ngx_int_t
870ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
871{
872    ngx_int_t  rc;
873
874    /*
875     * generic phase checker,
876     * used by the post read and pre-access phases
877     */
878
879    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
880                   "generic phase: %ui", r->phase_handler);
881
882    rc = ph->handler(r);
883
884    if (rc == NGX_OK) {
885        r->phase_handler = ph->next;
886        return NGX_AGAIN;
887    }
888
889    if (rc == NGX_DECLINED) {
890        r->phase_handler++;
891        return NGX_AGAIN;
892    }
893
894    if (rc == NGX_AGAIN || rc == NGX_DONE) {
895        return NGX_OK;
896    }
897
898    /* rc == NGX_ERROR || rc == NGX_HTTP_...  */
899
900    ngx_http_finalize_request(r, rc);
901
902    return NGX_OK;
903}
904
905
906ngx_int_t
907ngx_http_core_rewrite_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
908{
909    ngx_int_t  rc;
910
911    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
912                   "rewrite phase: %ui", r->phase_handler);
913
914    rc = ph->handler(r);
915
916    if (rc == NGX_DECLINED) {
917        r->phase_handler++;
918        return NGX_AGAIN;
919    }
920
921    if (rc == NGX_DONE) {
922        return NGX_OK;
923    }
924
925    /* NGX_OK, NGX_AGAIN, NGX_ERROR, NGX_HTTP_...  */
926
927    ngx_http_finalize_request(r, rc);
928
929    return NGX_OK;
930}
931
932
933ngx_int_t
934ngx_http_core_find_config_phase(ngx_http_request_t *r,
935    ngx_http_phase_handler_t *ph)
936{
937    u_char                    *p;
938    size_t                     len;
939    ngx_int_t                  rc;
940    ngx_http_core_loc_conf_t  *clcf;
941
942    r->content_handler = NULL;
943    r->uri_changed = 0;
944
945    rc = ngx_http_core_find_location(r);
946
947    if (rc == NGX_ERROR) {
948        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
949        return NGX_OK;
950    }
951
952    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
953
954    if (!r->internal && clcf->internal) {
955        ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
956        return NGX_OK;
957    }
958
959    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
960                   "using configuration \"%s%V\"",
961                   (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")),
962                   &clcf->name);
963
964    ngx_http_update_location_config(r);
965
966    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
967                   "http cl:%O max:%O",
968                   r->headers_in.content_length_n, clcf->client_max_body_size);
969
970    if (r->headers_in.content_length_n != -1
971        && !r->discard_body
972        && clcf->client_max_body_size
973        && clcf->client_max_body_size < r->headers_in.content_length_n)
974    {
975        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
976                      "client intended to send too large body: %O bytes",
977                      r->headers_in.content_length_n);
978
979        r->expect_tested = 1;
980        (void) ngx_http_discard_request_body(r);
981        ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
982        return NGX_OK;
983    }
984
985    if (rc == NGX_DONE) {
986        ngx_http_clear_location(r);
987
988        r->headers_out.location = ngx_list_push(&r->headers_out.headers);
989        if (r->headers_out.location == NULL) {
990            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
991            return NGX_OK;
992        }
993
994        r->headers_out.location->hash = 1;
995        ngx_str_set(&r->headers_out.location->key, "Location");
996
997        if (r->args.len == 0) {
998            r->headers_out.location->value = clcf->name;
999
1000        } else {
1001            len = clcf->name.len + 1 + r->args.len;
1002            p = ngx_pnalloc(r->pool, len);
1003
1004            if (p == NULL) {
1005                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1006                return NGX_OK;
1007            }
1008
1009            r->headers_out.location->value.len = len;
1010            r->headers_out.location->value.data = p;
1011
1012            p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
1013            *p++ = '?';
1014            ngx_memcpy(p, r->args.data, r->args.len);
1015        }
1016
1017        ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
1018        return NGX_OK;
1019    }
1020
1021    r->phase_handler++;
1022    return NGX_AGAIN;
1023}
1024
1025
1026ngx_int_t
1027ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
1028    ngx_http_phase_handler_t *ph)
1029{
1030    ngx_http_core_srv_conf_t  *cscf;
1031
1032    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1033                   "post rewrite phase: %ui", r->phase_handler);
1034
1035    if (!r->uri_changed) {
1036        r->phase_handler++;
1037        return NGX_AGAIN;
1038    }
1039
1040    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1041                   "uri changes: %d", r->uri_changes);
1042
1043    /*
1044     * gcc before 3.3 compiles the broken code for
1045     *     if (r->uri_changes-- == 0)
1046     * if the r->uri_changes is defined as
1047     *     unsigned  uri_changes:4
1048     */
1049
1050    r->uri_changes--;
1051
1052    if (r->uri_changes == 0) {
1053        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1054                      "rewrite or internal redirection cycle "
1055                      "while processing \"%V\"", &r->uri);
1056
1057        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1058        return NGX_OK;
1059    }
1060
1061    r->phase_handler = ph->next;
1062
1063    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1064    r->loc_conf = cscf->ctx->loc_conf;
1065
1066    return NGX_AGAIN;
1067}
1068
1069
1070ngx_int_t
1071ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
1072{
1073    ngx_int_t                  rc;
1074    ngx_http_core_loc_conf_t  *clcf;
1075
1076    if (r != r->main) {
1077        r->phase_handler = ph->next;
1078        return NGX_AGAIN;
1079    }
1080
1081    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1082                   "access phase: %ui", r->phase_handler);
1083
1084    rc = ph->handler(r);
1085
1086    if (rc == NGX_DECLINED) {
1087        r->phase_handler++;
1088        return NGX_AGAIN;
1089    }
1090
1091    if (rc == NGX_AGAIN || rc == NGX_DONE) {
1092        return NGX_OK;
1093    }
1094
1095    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1096
1097    if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
1098
1099        if (rc == NGX_OK) {
1100            r->phase_handler++;
1101            return NGX_AGAIN;
1102        }
1103
1104    } else {
1105        if (rc == NGX_OK) {
1106            r->access_code = 0;
1107
1108            if (r->headers_out.www_authenticate) {
1109                r->headers_out.www_authenticate->hash = 0;
1110            }
1111
1112            r->phase_handler = ph->next;
1113            return NGX_AGAIN;
1114        }
1115
1116        if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
1117            if (r->access_code != NGX_HTTP_UNAUTHORIZED) {
1118                r->access_code = rc;
1119            }
1120
1121            r->phase_handler++;
1122            return NGX_AGAIN;
1123        }
1124    }
1125
1126    /* rc == NGX_ERROR || rc == NGX_HTTP_...  */
1127
1128    ngx_http_finalize_request(r, rc);
1129    return NGX_OK;
1130}
1131
1132
1133ngx_int_t
1134ngx_http_core_post_access_phase(ngx_http_request_t *r,
1135    ngx_http_phase_handler_t *ph)
1136{
1137    ngx_int_t  access_code;
1138
1139    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1140                   "post access phase: %ui", r->phase_handler);
1141
1142    access_code = r->access_code;
1143
1144    if (access_code) {
1145        if (access_code == NGX_HTTP_FORBIDDEN) {
1146            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1147                          "access forbidden by rule");
1148        }
1149
1150        r->access_code = 0;
1151        ngx_http_finalize_request(r, access_code);
1152        return NGX_OK;
1153    }
1154
1155    r->phase_handler++;
1156    return NGX_AGAIN;
1157}
1158
1159
1160ngx_int_t
1161ngx_http_core_try_files_phase(ngx_http_request_t *r,
1162    ngx_http_phase_handler_t *ph)
1163{
1164    size_t                        len, root, alias, reserve, allocated;
1165    u_char                       *p, *name;
1166    ngx_str_t                     path, args;
1167    ngx_uint_t                    test_dir;
1168    ngx_http_try_file_t          *tf;
1169    ngx_open_file_info_t          of;
1170    ngx_http_script_code_pt       code;
1171    ngx_http_script_engine_t      e;
1172    ngx_http_core_loc_conf_t     *clcf;
1173    ngx_http_script_len_code_pt   lcode;
1174
1175    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1176                   "try files phase: %ui", r->phase_handler);
1177
1178    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1179
1180    if (clcf->try_files == NULL) {
1181        r->phase_handler++;
1182        return NGX_AGAIN;
1183    }
1184
1185    allocated = 0;
1186    root = 0;
1187    name = NULL;
1188    /* suppress MSVC warning */
1189    path.data = NULL;
1190
1191    tf = clcf->try_files;
1192
1193    alias = clcf->alias;
1194
1195    for ( ;; ) {
1196
1197        if (tf->lengths) {
1198            ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1199
1200            e.ip = tf->lengths->elts;
1201            e.request = r;
1202
1203            /* 1 is for terminating '\0' as in static names */
1204            len = 1;
1205
1206            while (*(uintptr_t *) e.ip) {
1207                lcode = *(ngx_http_script_len_code_pt *) e.ip;
1208                len += lcode(&e);
1209            }
1210
1211        } else {
1212            len = tf->name.len;
1213        }
1214
1215        if (!alias) {
1216            reserve = len > r->uri.len ? len - r->uri.len : 0;
1217
1218        } else if (alias == NGX_MAX_SIZE_T_VALUE) {
1219            reserve = len;
1220
1221        } else {
1222            reserve = len > r->uri.len - alias ? len - (r->uri.len - alias) : 0;
1223        }
1224
1225        if (reserve > allocated || !allocated) {
1226
1227            /* 16 bytes are preallocation */
1228            allocated = reserve + 16;
1229
1230            if (ngx_http_map_uri_to_path(r, &path, &root, allocated) == NULL) {
1231                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1232                return NGX_OK;
1233            }
1234
1235            name = path.data + root;
1236        }
1237
1238        if (tf->values == NULL) {
1239
1240            /* tf->name.len includes the terminating '\0' */
1241
1242            ngx_memcpy(name, tf->name.data, tf->name.len);
1243
1244            path.len = (name + tf->name.len - 1) - path.data;
1245
1246        } else {
1247            e.ip = tf->values->elts;
1248            e.pos = name;
1249            e.flushed = 1;
1250
1251            while (*(uintptr_t *) e.ip) {
1252                code = *(ngx_http_script_code_pt *) e.ip;
1253                code((ngx_http_script_engine_t *) &e);
1254            }
1255
1256            path.len = e.pos - path.data;
1257
1258            *e.pos = '\0';
1259
1260            if (alias && alias != NGX_MAX_SIZE_T_VALUE
1261                && ngx_strncmp(name, r->uri.data, alias) == 0)
1262            {
1263                ngx_memmove(name, name + alias, len - alias);
1264                path.len -= alias;
1265            }
1266        }
1267
1268        test_dir = tf->test_dir;
1269
1270        tf++;
1271
1272        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1273                       "trying to use %s: \"%s\" \"%s\"",
1274                       test_dir ? "dir" : "file", name, path.data);
1275
1276        if (tf->lengths == NULL && tf->name.len == 0) {
1277
1278            if (tf->code) {
1279                ngx_http_finalize_request(r, tf->code);
1280                return NGX_OK;
1281            }
1282
1283            path.len -= root;
1284            path.data += root;
1285
1286            if (path.data[0] == '@') {
1287                (void) ngx_http_named_location(r, &path);
1288
1289            } else {
1290                ngx_http_split_args(r, &path, &args);
1291
1292                (void) ngx_http_internal_redirect(r, &path, &args);
1293            }
1294
1295            ngx_http_finalize_request(r, NGX_DONE);
1296            return NGX_OK;
1297        }
1298
1299        ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1300
1301        of.read_ahead = clcf->read_ahead;
1302        of.directio = clcf->directio;
1303        of.valid = clcf->open_file_cache_valid;
1304        of.min_uses = clcf->open_file_cache_min_uses;
1305        of.test_only = 1;
1306        of.errors = clcf->open_file_cache_errors;
1307        of.events = clcf->open_file_cache_events;
1308
1309        if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) {
1310            ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1311            return NGX_OK;
1312        }
1313
1314        if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1315            != NGX_OK)
1316        {
1317            if (of.err == 0) {
1318                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1319                return NGX_OK;
1320            }
1321
1322            if (of.err != NGX_ENOENT
1323                && of.err != NGX_ENOTDIR
1324                && of.err != NGX_ENAMETOOLONG)
1325            {
1326                ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1327                              "%s \"%s\" failed", of.failed, path.data);
1328            }
1329
1330            continue;
1331        }
1332
1333        if (of.is_dir != test_dir) {
1334            continue;
1335        }
1336
1337        path.len -= root;
1338        path.data += root;
1339
1340        if (!alias) {
1341            r->uri = path;
1342
1343        } else if (alias == NGX_MAX_SIZE_T_VALUE) {
1344            if (!test_dir) {
1345                r->uri = path;
1346                r->add_uri_to_alias = 1;
1347            }
1348
1349        } else {
1350            name = r->uri.data;
1351
1352            r->uri.len = alias + path.len;
1353            r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1354            if (r->uri.data == NULL) {
1355                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1356                return NGX_OK;
1357            }
1358
1359            p = ngx_copy(r->uri.data, name, alias);
1360            ngx_memcpy(p, path.data, path.len);
1361        }
1362
1363        ngx_http_set_exten(r);
1364
1365        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1366                       "try file uri: \"%V\"", &r->uri);
1367
1368        r->phase_handler++;
1369        return NGX_AGAIN;
1370    }
1371
1372    /* not reached */
1373}
1374
1375
1376ngx_int_t
1377ngx_http_core_content_phase(ngx_http_request_t *r,
1378    ngx_http_phase_handler_t *ph)
1379{
1380    size_t     root;
1381    ngx_int_t  rc;
1382    ngx_str_t  path;
1383
1384    if (r->content_handler) {
1385        r->write_event_handler = ngx_http_request_empty_handler;
1386        ngx_http_finalize_request(r, r->content_handler(r));
1387        return NGX_OK;
1388    }
1389
1390    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1391                   "content phase: %ui", r->phase_handler);
1392
1393    rc = ph->handler(r);
1394
1395    if (rc != NGX_DECLINED) {
1396        ngx_http_finalize_request(r, rc);
1397        return NGX_OK;
1398    }
1399
1400    /* rc == NGX_DECLINED */
1401
1402    ph++;
1403
1404    if (ph->checker) {
1405        r->phase_handler++;
1406        return NGX_AGAIN;
1407    }
1408
1409    /* no content handler was found */
1410
1411    if (r->uri.data[r->uri.len - 1] == '/') {
1412
1413        if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
1414            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1415                          "directory index of \"%s\" is forbidden", path.data);
1416        }
1417
1418        ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
1419        return NGX_OK;
1420    }
1421
1422    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
1423
1424    ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1425    return NGX_OK;
1426}
1427
1428
1429void
1430ngx_http_update_location_config(ngx_http_request_t *r)
1431{
1432    ngx_http_core_loc_conf_t  *clcf;
1433
1434    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1435
1436    if (r->method & clcf->limit_except) {
1437        r->loc_conf = clcf->limit_except_loc_conf;
1438        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1439    }
1440
1441    if (r == r->main) {
1442        ngx_set_connection_log(r->connection, clcf->error_log);
1443    }
1444
1445    if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
1446        r->connection->sendfile = 1;
1447
1448    } else {
1449        r->connection->sendfile = 0;
1450    }
1451
1452    if (clcf->client_body_in_file_only) {
1453        r->request_body_in_file_only = 1;
1454        r->request_body_in_persistent_file = 1;
1455        r->request_body_in_clean_file =
1456            clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
1457        r->request_body_file_log_level = NGX_LOG_NOTICE;
1458
1459    } else {
1460        r->request_body_file_log_level = NGX_LOG_WARN;
1461    }
1462
1463    r->request_body_in_single_buf = clcf->client_body_in_single_buffer;
1464
1465    if (r->keepalive) {
1466        if (clcf->keepalive_timeout == 0) {
1467            r->keepalive = 0;
1468
1469        } else if (r->connection->requests >= clcf->keepalive_requests) {
1470            r->keepalive = 0;
1471
1472        } else if (r->headers_in.msie6
1473                   && r->method == NGX_HTTP_POST
1474                   && (clcf->keepalive_disable
1475                       & NGX_HTTP_KEEPALIVE_DISABLE_MSIE6))
1476        {
1477            /*
1478             * MSIE may wait for some time if an response for
1479             * a POST request was sent over a keepalive connection
1480             */
1481            r->keepalive = 0;
1482
1483        } else if (r->headers_in.safari
1484                   && (clcf->keepalive_disable
1485                       & NGX_HTTP_KEEPALIVE_DISABLE_SAFARI))
1486        {
1487            /*
1488             * Safari may send a POST request to a closed keepalive
1489             * connection and may stall for some time, see
1490             *     https://bugs.webkit.org/show_bug.cgi?id=5760
1491             */
1492            r->keepalive = 0;
1493        }
1494    }
1495
1496    if (!clcf->tcp_nopush) {
1497        /* disable TCP_NOPUSH/TCP_CORK use */
1498        r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
1499    }
1500
1501    if (r->limit_rate == 0) {
1502        r->limit_rate = clcf->limit_rate;
1503    }
1504
1505    if (clcf->handler) {
1506        r->content_handler = clcf->handler;
1507    }
1508}
1509
1510
1511/*
1512 * NGX_OK       - exact or regex match
1513 * NGX_DONE     - auto redirect
1514 * NGX_AGAIN    - inclusive match
1515 * NGX_ERROR    - regex error
1516 * NGX_DECLINED - no match
1517 */
1518
1519static ngx_int_t
1520ngx_http_core_find_location(ngx_http_request_t *r)
1521{
1522    ngx_int_t                  rc;
1523    ngx_http_core_loc_conf_t  *pclcf;
1524#if (NGX_PCRE)
1525    ngx_int_t                  n;
1526    ngx_uint_t                 noregex;
1527    ngx_http_core_loc_conf_t  *clcf, **clcfp;
1528
1529    noregex = 0;
1530#endif
1531
1532    pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1533
1534    rc = ngx_http_core_find_static_location(r, pclcf->static_locations);
1535
1536    if (rc == NGX_AGAIN) {
1537
1538#if (NGX_PCRE)
1539        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1540
1541        noregex = clcf->noregex;
1542#endif
1543
1544        /* look up nested locations */
1545
1546        rc = ngx_http_core_find_location(r);
1547    }
1548
1549    if (rc == NGX_OK || rc == NGX_DONE) {
1550        return rc;
1551    }
1552
1553    /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */
1554
1555#if (NGX_PCRE)
1556
1557    if (noregex == 0 && pclcf->regex_locations) {
1558
1559        for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
1560
1561            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1562                           "test location: ~ \"%V\"", &(*clcfp)->name);
1563
1564            n = ngx_http_regex_exec(r, (*clcfp)->regex, &r->uri);
1565
1566            if (n == NGX_OK) {
1567                r->loc_conf = (*clcfp)->loc_conf;
1568
1569                /* look up nested locations */
1570
1571                rc = ngx_http_core_find_location(r);
1572
1573                return (rc == NGX_ERROR) ? rc : NGX_OK;
1574            }
1575
1576            if (n == NGX_DECLINED) {
1577                continue;
1578            }
1579
1580            return NGX_ERROR;
1581        }
1582    }
1583#endif
1584
1585    return rc;
1586}
1587
1588
1589/*
1590 * NGX_OK       - exact match
1591 * NGX_DONE     - auto redirect
1592 * NGX_AGAIN    - inclusive match
1593 * NGX_DECLINED - no match
1594 */
1595
1596static ngx_int_t
1597ngx_http_core_find_static_location(ngx_http_request_t *r,
1598    ngx_http_location_tree_node_t *node)
1599{
1600    u_char     *uri;
1601    size_t      len, n;
1602    ngx_int_t   rc, rv;
1603
1604    len = r->uri.len;
1605    uri = r->uri.data;
1606
1607    rv = NGX_DECLINED;
1608
1609    for ( ;; ) {
1610
1611        if (node == NULL) {
1612            return rv;
1613        }
1614
1615        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1616                       "test location: \"%*s\"",
1617                       (size_t) node->len, node->name);
1618
1619        n = (len <= (size_t) node->len) ? len : node->len;
1620
1621        rc = ngx_filename_cmp(uri, node->name, n);
1622
1623        if (rc != 0) {
1624            node = (rc < 0) ? node->left : node->right;
1625
1626            continue;
1627        }
1628
1629        if (len > (size_t) node->len) {
1630
1631            if (node->inclusive) {
1632
1633                r->loc_conf = node->inclusive->loc_conf;
1634                rv = NGX_AGAIN;
1635
1636                node = node->tree;
1637                uri += n;
1638                len -= n;
1639
1640                continue;
1641            }
1642
1643            /* exact only */
1644
1645            node = node->right;
1646
1647            continue;
1648        }
1649
1650        if (len == (size_t) node->len) {
1651
1652            if (node->exact) {
1653                r->loc_conf = node->exact->loc_conf;
1654                return NGX_OK;
1655
1656            } else {
1657                r->loc_conf = node->inclusive->loc_conf;
1658                return NGX_AGAIN;
1659            }
1660        }
1661
1662        /* len < node->len */
1663
1664        if (len + 1 == (size_t) node->len && node->auto_redirect) {
1665
1666            r->loc_conf = (node->exact) ? node->exact->loc_conf:
1667                                          node->inclusive->loc_conf;
1668            rv = NGX_DONE;
1669        }
1670
1671        node = node->left;
1672    }
1673}
1674
1675
1676void *
1677ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
1678{
1679    u_char      c, *lowcase;
1680    size_t      len;
1681    ngx_uint_t  i, hash;
1682
1683    if (types_hash->size == 0) {
1684        return (void *) 4;
1685    }
1686
1687    if (r->headers_out.content_type.len == 0) {
1688        return NULL;
1689    }
1690
1691    len = r->headers_out.content_type_len;
1692
1693    if (r->headers_out.content_type_lowcase == NULL) {
1694
1695        lowcase = ngx_pnalloc(r->pool, len);
1696        if (lowcase == NULL) {
1697            return NULL;
1698        }
1699
1700        r->headers_out.content_type_lowcase = lowcase;
1701
1702        hash = 0;
1703
1704        for (i = 0; i < len; i++) {
1705            c = ngx_tolower(r->headers_out.content_type.data[i]);
1706            hash = ngx_hash(hash, c);
1707            lowcase[i] = c;
1708        }
1709
1710        r->headers_out.content_type_hash = hash;
1711    }
1712
1713    return ngx_hash_find(types_hash, r->headers_out.content_type_hash,
1714                         r->headers_out.content_type_lowcase, len);
1715}
1716
1717
1718ngx_int_t
1719ngx_http_set_content_type(ngx_http_request_t *r)
1720{
1721    u_char                     c, *exten;
1722    ngx_str_t                 *type;
1723    ngx_uint_t                 i, hash;
1724    ngx_http_core_loc_conf_t  *clcf;
1725
1726    if (r->headers_out.content_type.len) {
1727        return NGX_OK;
1728    }
1729
1730    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1731
1732    if (r->exten.len) {
1733
1734        hash = 0;
1735
1736        for (i = 0; i < r->exten.len; i++) {
1737            c = r->exten.data[i];
1738
1739            if (c >= 'A' && c <= 'Z') {
1740
1741                exten = ngx_pnalloc(r->pool, r->exten.len);
1742                if (exten == NULL) {
1743                    return NGX_ERROR;
1744                }
1745
1746                hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);
1747
1748                r->exten.data = exten;
1749
1750                break;
1751            }
1752
1753            hash = ngx_hash(hash, c);
1754        }
1755
1756        type = ngx_hash_find(&clcf->types_hash, hash,
1757                             r->exten.data, r->exten.len);
1758
1759        if (type) {
1760            r->headers_out.content_type_len = type->len;
1761            r->headers_out.content_type = *type;
1762
1763            return NGX_OK;
1764        }
1765    }
1766
1767    r->headers_out.content_type_len = clcf->default_type.len;
1768    r->headers_out.content_type = clcf->default_type;
1769
1770    return NGX_OK;
1771}
1772
1773
1774void
1775ngx_http_set_exten(ngx_http_request_t *r)
1776{
1777    ngx_int_t  i;
1778
1779    ngx_str_null(&r->exten);
1780
1781    for (i = r->uri.len - 1; i > 1; i--) {
1782        if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
1783
1784            r->exten.len = r->uri.len - i - 1;
1785            r->exten.data = &r->uri.data[i + 1];
1786
1787            return;
1788
1789        } else if (r->uri.data[i] == '/') {
1790            return;
1791        }
1792    }
1793
1794    return;
1795}
1796
1797
1798ngx_int_t
1799ngx_http_set_etag(ngx_http_request_t *r)
1800{
1801    ngx_table_elt_t           *etag;
1802    ngx_http_core_loc_conf_t  *clcf;
1803
1804    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1805
1806    if (!clcf->etag) {
1807        return NGX_OK;
1808    }
1809
1810    etag = ngx_list_push(&r->headers_out.headers);
1811    if (etag == NULL) {
1812        return NGX_ERROR;
1813    }
1814
1815    etag->hash = 1;
1816    ngx_str_set(&etag->key, "ETag");
1817
1818    etag->value.data = ngx_pnalloc(r->pool, NGX_OFF_T_LEN + NGX_TIME_T_LEN + 3);
1819    if (etag->value.data == NULL) {
1820        etag->hash = 0;
1821        return NGX_ERROR;
1822    }
1823
1824    etag->value.len = ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
1825                                  r->headers_out.last_modified_time,
1826                                  r->headers_out.content_length_n)
1827                      - etag->value.data;
1828
1829    r->headers_out.etag = etag;
1830
1831    return NGX_OK;
1832}
1833
1834
1835void
1836ngx_http_weak_etag(ngx_http_request_t *r)
1837{
1838    size_t            len;
1839    u_char           *p;
1840    ngx_table_elt_t  *etag;
1841
1842    etag = r->headers_out.etag;
1843
1844    if (etag == NULL) {
1845        return;
1846    }
1847
1848    if (etag->value.len > 2
1849        && etag->value.data[0] == 'W'
1850        && etag->value.data[1] == '/')
1851    {
1852        return;
1853    }
1854
1855    if (etag->value.len < 1 || etag->value.data[0] != '"') {
1856        r->headers_out.etag->hash = 0;
1857        r->headers_out.etag = NULL;
1858        return;
1859    }
1860
1861    p = ngx_pnalloc(r->pool, etag->value.len + 2);
1862    if (p == NULL) {
1863        r->headers_out.etag->hash = 0;
1864        r->headers_out.etag = NULL;
1865        return;
1866    }
1867
1868    len = ngx_sprintf(p, "W/%V", &etag->value) - p;
1869
1870    etag->value.data = p;
1871    etag->value.len = len;
1872}
1873
1874
1875ngx_int_t
1876ngx_http_send_response(ngx_http_request_t *r, ngx_uint_t status,
1877    ngx_str_t *ct, ngx_http_complex_value_t *cv)
1878{
1879    ngx_int_t     rc;
1880    ngx_str_t     val;
1881    ngx_buf_t    *b;
1882    ngx_chain_t   out;
1883
1884    if (ngx_http_discard_request_body(r) != NGX_OK) {
1885        return NGX_HTTP_INTERNAL_SERVER_ERROR;
1886    }
1887
1888    r->headers_out.status = status;
1889
1890    if (ngx_http_complex_value(r, cv, &val) != NGX_OK) {
1891        return NGX_HTTP_INTERNAL_SERVER_ERROR;
1892    }
1893
1894    if (status == NGX_HTTP_MOVED_PERMANENTLY
1895        || status == NGX_HTTP_MOVED_TEMPORARILY
1896        || status == NGX_HTTP_SEE_OTHER
1897        || status == NGX_HTTP_TEMPORARY_REDIRECT)
1898    {
1899        ngx_http_clear_location(r);
1900
1901        r->headers_out.location = ngx_list_push(&r->headers_out.headers);
1902        if (r->headers_out.location == NULL) {
1903            return NGX_HTTP_INTERNAL_SERVER_ERROR;
1904        }
1905
1906        r->headers_out.location->hash = 1;
1907        ngx_str_set(&r->headers_out.location->key, "Location");
1908        r->headers_out.location->value = val;
1909
1910        return status;
1911    }
1912
1913    r->headers_out.content_length_n = val.len;
1914
1915    if (ct) {
1916        r->headers_out.content_type_len = ct->len;
1917        r->headers_out.content_type = *ct;
1918
1919    } else {
1920        if (ngx_http_set_content_type(r) != NGX_OK) {
1921            return NGX_HTTP_INTERNAL_SERVER_ERROR;
1922        }
1923    }
1924
1925    if (r->method == NGX_HTTP_HEAD || (r != r->main && val.len == 0)) {
1926        return ngx_http_send_header(r);
1927    }
1928
1929    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
1930    if (b == NULL) {
1931        return NGX_HTTP_INTERNAL_SERVER_ERROR;
1932    }
1933
1934    b->pos = val.data;
1935    b->last = val.data + val.len;
1936    b->memory = val.len ? 1 : 0;
1937    b->last_buf = (r == r->main) ? 1 : 0;
1938    b->last_in_chain = 1;
1939
1940    out.buf = b;
1941    out.next = NULL;
1942
1943    rc = ngx_http_send_header(r);
1944
1945    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
1946        return rc;
1947    }
1948
1949    return ngx_http_output_filter(r, &out);
1950}
1951
1952
1953ngx_int_t
1954ngx_http_send_header(ngx_http_request_t *r)
1955{
1956    if (r->post_action) {
1957        return NGX_OK;
1958    }
1959
1960    if (r->header_sent) {
1961        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1962                      "header already sent");
1963        return NGX_ERROR;
1964    }
1965
1966    if (r->err_status) {
1967        r->headers_out.status = r->err_status;
1968        r->headers_out.status_line.len = 0;
1969    }
1970
1971    return ngx_http_top_header_filter(r);
1972}
1973
1974
1975ngx_int_t
1976ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
1977{
1978    ngx_int_t          rc;
1979    ngx_connection_t  *c;
1980
1981    c = r->connection;
1982
1983    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
1984                   "http output filter \"%V?%V\"", &r->uri, &r->args);
1985
1986    rc = ngx_http_top_body_filter(r, in);
1987
1988    if (rc == NGX_ERROR) {
1989        /* NGX_ERROR may be returned by any filter */
1990        c->error = 1;
1991    }
1992
1993    return rc;
1994}
1995
1996
1997u_char *
1998ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
1999    size_t *root_length, size_t reserved)
2000{
2001    u_char                    *last;
2002    size_t                     alias;
2003    ngx_http_core_loc_conf_t  *clcf;
2004
2005    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2006
2007    alias = clcf->alias;
2008
2009    if (alias && !r->valid_location) {
2010        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
2011                      "\"alias\" cannot be used in location \"%V\" "
2012                      "where URI was rewritten", &clcf->name);
2013        return NULL;
2014    }
2015
2016    if (clcf->root_lengths == NULL) {
2017
2018        *root_length = clcf->root.len;
2019
2020        path->len = clcf->root.len + reserved + r->uri.len - alias + 1;
2021
2022        path->data = ngx_pnalloc(r->pool, path->len);
2023        if (path->data == NULL) {
2024            return NULL;
2025        }
2026
2027        last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
2028
2029    } else {
2030
2031        if (alias == NGX_MAX_SIZE_T_VALUE) {
2032            reserved += r->add_uri_to_alias ? r->uri.len + 1 : 1;
2033
2034        } else {
2035            reserved += r->uri.len - alias + 1;
2036        }
2037
2038        if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
2039                                clcf->root_values->elts)
2040            == NULL)
2041        {
2042            return NULL;
2043        }
2044
2045        if (ngx_get_full_name(r->pool, (ngx_str_t *) &ngx_cycle->prefix, path)
2046            != NGX_OK)
2047        {
2048            return NULL;
2049        }
2050
2051        *root_length = path->len - reserved;
2052        last = path->data + *root_length;
2053
2054        if (alias == NGX_MAX_SIZE_T_VALUE) {
2055            if (!r->add_uri_to_alias) {
2056                *last = '\0';
2057                return last;
2058            }
2059
2060            alias = 0;
2061        }
2062    }
2063
2064    last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
2065
2066    return last;
2067}
2068
2069
2070ngx_int_t
2071ngx_http_auth_basic_user(ngx_http_request_t *r)
2072{
2073    ngx_str_t   auth, encoded;
2074    ngx_uint_t  len;
2075
2076    if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
2077        return NGX_DECLINED;
2078    }
2079
2080    if (r->headers_in.authorization == NULL) {
2081        r->headers_in.user.data = (u_char *) "";
2082        return NGX_DECLINED;
2083    }
2084
2085    encoded = r->headers_in.authorization->value;
2086
2087    if (encoded.len < sizeof("Basic ") - 1
2088        || ngx_strncasecmp(encoded.data, (u_char *) "Basic ",
2089                           sizeof("Basic ") - 1)
2090           != 0)
2091    {
2092        r->headers_in.user.data = (u_char *) "";
2093        return NGX_DECLINED;
2094    }
2095
2096    encoded.len -= sizeof("Basic ") - 1;
2097    encoded.data += sizeof("Basic ") - 1;
2098
2099    while (encoded.len && encoded.data[0] == ' ') {
2100        encoded.len--;
2101        encoded.data++;
2102    }
2103
2104    if (encoded.len == 0) {
2105        r->headers_in.user.data = (u_char *) "";
2106        return NGX_DECLINED;
2107    }
2108
2109    auth.len = ngx_base64_decoded_length(encoded.len);
2110    auth.data = ngx_pnalloc(r->pool, auth.len + 1);
2111    if (auth.data == NULL) {
2112        return NGX_ERROR;
2113    }
2114
2115    if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
2116        r->headers_in.user.data = (u_char *) "";
2117        return NGX_DECLINED;
2118    }
2119
2120    auth.data[auth.len] = '\0';
2121
2122    for (len = 0; len < auth.len; len++) {
2123        if (auth.data[len] == ':') {
2124            break;
2125        }
2126    }
2127
2128    if (len == 0 || len == auth.len) {
2129        r->headers_in.user.data = (u_char *) "";
2130        return NGX_DECLINED;
2131    }
2132
2133    r->headers_in.user.len = len;
2134    r->headers_in.user.data = auth.data;
2135    r->headers_in.passwd.len = auth.len - len - 1;
2136    r->headers_in.passwd.data = &auth.data[len + 1];
2137
2138    return NGX_OK;
2139}
2140
2141
2142#if (NGX_HTTP_GZIP)
2143
2144ngx_int_t
2145ngx_http_gzip_ok(ngx_http_request_t *r)
2146{
2147    time_t                     date, expires;
2148    ngx_uint_t                 p;
2149    ngx_array_t               *cc;
2150    ngx_table_elt_t           *e, *d, *ae;
2151    ngx_http_core_loc_conf_t  *clcf;
2152
2153    r->gzip_tested = 1;
2154
2155    if (r != r->main) {
2156        return NGX_DECLINED;
2157    }
2158
2159    ae = r->headers_in.accept_encoding;
2160    if (ae == NULL) {
2161        return NGX_DECLINED;
2162    }
2163
2164    if (ae->value.len < sizeof("gzip") - 1) {
2165        return NGX_DECLINED;
2166    }
2167
2168    /*
2169     * test first for the most common case "gzip,...":
2170     *   MSIE:    "gzip, deflate"
2171     *   Firefox: "gzip,deflate"
2172     *   Chrome:  "gzip,deflate,sdch"
2173     *   Safari:  "gzip, deflate"
2174     *   Opera:   "gzip, deflate"
2175     */
2176
2177    if (ngx_memcmp(ae->value.data, "gzip,", 5) != 0
2178        && ngx_http_gzip_accept_encoding(&ae->value) != NGX_OK)
2179    {
2180        return NGX_DECLINED;
2181    }
2182
2183    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2184
2185    if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
2186        return NGX_DECLINED;
2187    }
2188
2189    if (r->http_version < clcf->gzip_http_version) {
2190        return NGX_DECLINED;
2191    }
2192
2193    if (r->headers_in.via == NULL) {
2194        goto ok;
2195    }
2196
2197    p = clcf->gzip_proxied;
2198
2199    if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
2200        return NGX_DECLINED;
2201    }
2202
2203    if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
2204        goto ok;
2205    }
2206
2207    if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
2208        goto ok;
2209    }
2210
2211    e = r->headers_out.expires;
2212
2213    if (e) {
2214
2215        if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
2216            return NGX_DECLINED;
2217        }
2218
2219        expires = ngx_parse_http_time(e->value.data, e->value.len);
2220        if (expires == NGX_ERROR) {
2221            return NGX_DECLINED;
2222        }
2223
2224        d = r->headers_out.date;
2225
2226        if (d) {
2227            date = ngx_parse_http_time(d->value.data, d->value.len);
2228            if (date == NGX_ERROR) {
2229                return NGX_DECLINED;
2230            }
2231
2232        } else {
2233            date = ngx_time();
2234        }
2235
2236        if (expires < date) {
2237            goto ok;
2238        }
2239
2240        return NGX_DECLINED;
2241    }
2242
2243    cc = &r->headers_out.cache_control;
2244
2245    if (cc->elts) {
2246
2247        if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
2248            && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
2249                                                 NULL)
2250               >= 0)
2251        {
2252            goto ok;
2253        }
2254
2255        if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
2256            && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
2257                                                 NULL)
2258               >= 0)
2259        {
2260            goto ok;
2261        }
2262
2263        if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
2264            && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
2265                                                 NULL)
2266               >= 0)
2267        {
2268            goto ok;
2269        }
2270
2271        return NGX_DECLINED;
2272    }
2273
2274    if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
2275        return NGX_DECLINED;
2276    }
2277
2278    if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
2279        return NGX_DECLINED;
2280    }
2281
2282ok:
2283
2284#if (NGX_PCRE)
2285
2286    if (clcf->gzip_disable && r->headers_in.user_agent) {
2287
2288        if (ngx_regex_exec_array(clcf->gzip_disable,
2289                                 &r->headers_in.user_agent->value,
2290                                 r->connection->log)
2291            != NGX_DECLINED)
2292        {
2293            return NGX_DECLINED;
2294        }
2295    }
2296
2297#endif
2298
2299    r->gzip_ok = 1;
2300
2301    return NGX_OK;
2302}
2303
2304
2305/*
2306 * gzip is enabled for the following quantities:
2307 *     "gzip; q=0.001" ... "gzip; q=1.000"
2308 * gzip is disabled for the following quantities:
2309 *     "gzip; q=0" ... "gzip; q=0.000", and for any invalid cases
2310 */
2311
2312static ngx_int_t
2313ngx_http_gzip_accept_encoding(ngx_str_t *ae)
2314{
2315    u_char  *p, *start, *last;
2316
2317    start = ae->data;
2318    last = start + ae->len;
2319
2320    for ( ;; ) {
2321        p = ngx_strcasestrn(start, "gzip", 4 - 1);
2322        if (p == NULL) {
2323            return NGX_DECLINED;
2324        }
2325
2326        if (p == start || (*(p - 1) == ',' || *(p - 1) == ' ')) {
2327            break;
2328        }
2329
2330        start = p + 4;
2331    }
2332
2333    p += 4;
2334
2335    while (p < last) {
2336        switch (*p++) {
2337        case ',':
2338            return NGX_OK;
2339        case ';':
2340            goto quantity;
2341        case ' ':
2342            continue;
2343        default:
2344            return NGX_DECLINED;
2345        }
2346    }
2347
2348    return NGX_OK;
2349
2350quantity:
2351
2352    while (p < last) {
2353        switch (*p++) {
2354        case 'q':
2355        case 'Q':
2356            goto equal;
2357        case ' ':
2358            continue;
2359        default:
2360            return NGX_DECLINED;
2361        }
2362    }
2363
2364    return NGX_OK;
2365
2366equal:
2367
2368    if (p + 2 > last || *p++ != '=') {
2369        return NGX_DECLINED;
2370    }
2371
2372    if (ngx_http_gzip_quantity(p, last) == 0) {
2373        return NGX_DECLINED;
2374    }
2375
2376    return NGX_OK;
2377}
2378
2379
2380static ngx_uint_t
2381ngx_http_gzip_quantity(u_char *p, u_char *last)
2382{
2383    u_char      c;
2384    ngx_uint_t  n, q;
2385
2386    c = *p++;
2387
2388    if (c != '0' && c != '1') {
2389        return 0;
2390    }
2391
2392    q = (c - '0') * 100;
2393
2394    if (p == last) {
2395        return q;
2396    }
2397
2398    c = *p++;
2399
2400    if (c == ',' || c == ' ') {
2401        return q;
2402    }
2403
2404    if (c != '.') {
2405        return 0;
2406    }
2407
2408    n = 0;
2409
2410    while (p < last) {
2411        c = *p++;
2412
2413        if (c == ',' || c == ' ') {
2414            break;
2415        }
2416
2417        if (c >= '0' && c <= '9') {
2418            q += c - '0';
2419            n++;
2420            continue;
2421        }
2422
2423        return 0;
2424    }
2425
2426    if (q > 100 || n > 3) {
2427        return 0;
2428    }
2429
2430    return q;
2431}
2432
2433#endif
2434
2435
2436ngx_int_t
2437ngx_http_subrequest(ngx_http_request_t *r,
2438    ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
2439    ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
2440{
2441    ngx_time_t                    *tp;
2442    ngx_connection_t              *c;
2443    ngx_http_request_t            *sr;
2444    ngx_http_core_srv_conf_t      *cscf;
2445    ngx_http_postponed_request_t  *pr, *p;
2446
2447    if (r->subrequests == 0) {
2448        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2449                      "subrequests cycle while processing \"%V\"", uri);
2450        return NGX_ERROR;
2451    }
2452
2453    /*
2454     * 1000 is reserved for other purposes.
2455     */
2456    if (r->main->count >= 65535 - 1000) {
2457        ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0,
2458                      "request reference counter overflow "
2459                      "while processing \"%V\"", uri);
2460        return NGX_ERROR;
2461    }
2462
2463    sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
2464    if (sr == NULL) {
2465        return NGX_ERROR;
2466    }
2467
2468    sr->signature = NGX_HTTP_MODULE;
2469
2470    c = r->connection;
2471    sr->connection = c;
2472
2473    sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
2474    if (sr->ctx == NULL) {
2475        return NGX_ERROR;
2476    }
2477
2478    if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
2479                      sizeof(ngx_table_elt_t))
2480        != NGX_OK)
2481    {
2482        return NGX_ERROR;
2483    }
2484
2485    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2486    sr->main_conf = cscf->ctx->main_conf;
2487    sr->srv_conf = cscf->ctx->srv_conf;
2488    sr->loc_conf = cscf->ctx->loc_conf;
2489
2490    sr->pool = r->pool;
2491
2492    sr->headers_in = r->headers_in;
2493
2494    ngx_http_clear_content_length(sr);
2495    ngx_http_clear_accept_ranges(sr);
2496    ngx_http_clear_last_modified(sr);
2497
2498    sr->request_body = r->request_body;
2499
2500#if (NGX_HTTP_V2)
2501    sr->stream = r->stream;
2502#endif
2503
2504    sr->method = NGX_HTTP_GET;
2505    sr->http_version = r->http_version;
2506
2507    sr->request_line = r->request_line;
2508    sr->uri = *uri;
2509
2510    if (args) {
2511        sr->args = *args;
2512    }
2513
2514    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2515                   "http subrequest \"%V?%V\"", uri, &sr->args);
2516
2517    sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
2518    sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
2519
2520    sr->unparsed_uri = r->unparsed_uri;
2521    sr->method_name = ngx_http_core_get_method;
2522    sr->http_protocol = r->http_protocol;
2523
2524    ngx_http_set_exten(sr);
2525
2526    sr->main = r->main;
2527    sr->parent = r;
2528    sr->post_subrequest = ps;
2529    sr->read_event_handler = ngx_http_request_empty_handler;
2530    sr->write_event_handler = ngx_http_handler;
2531
2532    if (c->data == r && r->postponed == NULL) {
2533        c->data = sr;
2534    }
2535
2536    sr->variables = r->variables;
2537
2538    sr->log_handler = r->log_handler;
2539
2540    pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
2541    if (pr == NULL) {
2542        return NGX_ERROR;
2543    }
2544
2545    pr->request = sr;
2546    pr->out = NULL;
2547    pr->next = NULL;
2548
2549    if (r->postponed) {
2550        for (p = r->postponed; p->next; p = p->next) { /* void */ }
2551        p->next = pr;
2552
2553    } else {
2554        r->postponed = pr;
2555    }
2556
2557    sr->internal = 1;
2558
2559    sr->discard_body = r->discard_body;
2560    sr->expect_tested = 1;
2561    sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
2562
2563    sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
2564    sr->subrequests = r->subrequests - 1;
2565
2566    tp = ngx_timeofday();
2567    sr->start_sec = tp->sec;
2568    sr->start_msec = tp->msec;
2569
2570    r->main->count++;
2571
2572    *psr = sr;
2573
2574    if (flags & NGX_HTTP_SUBREQUEST_CLONE) {
2575        sr->method = r->method;
2576        sr->method_name = r->method_name;
2577        sr->loc_conf = r->loc_conf;
2578        sr->valid_location = r->valid_location;
2579        sr->content_handler = r->content_handler;
2580        sr->phase_handler = r->phase_handler;
2581        sr->write_event_handler = ngx_http_core_run_phases;
2582
2583        ngx_http_update_location_config(sr);
2584    }
2585
2586    return ngx_http_post_request(sr, NULL);
2587}
2588
2589
2590ngx_int_t
2591ngx_http_internal_redirect(ngx_http_request_t *r,
2592    ngx_str_t *uri, ngx_str_t *args)
2593{
2594    ngx_http_core_srv_conf_t  *cscf;
2595
2596    r->uri_changes--;
2597
2598    if (r->uri_changes == 0) {
2599        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2600                      "rewrite or internal redirection cycle "
2601                      "while internally redirecting to \"%V\"", uri);
2602
2603        r->main->count++;
2604        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2605        return NGX_DONE;
2606    }
2607
2608    r->uri = *uri;
2609
2610    if (args) {
2611        r->args = *args;
2612
2613    } else {
2614        ngx_str_null(&r->args);
2615    }
2616
2617    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2618                   "internal redirect: \"%V?%V\"", uri, &r->args);
2619
2620    ngx_http_set_exten(r);
2621
2622    /* clear the modules contexts */
2623    ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2624
2625    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2626    r->loc_conf = cscf->ctx->loc_conf;
2627
2628    ngx_http_update_location_config(r);
2629
2630#if (NGX_HTTP_CACHE)
2631    r->cache = NULL;
2632#endif
2633
2634    r->internal = 1;
2635    r->valid_unparsed_uri = 0;
2636    r->add_uri_to_alias = 0;
2637    r->main->count++;
2638
2639    ngx_http_handler(r);
2640
2641    return NGX_DONE;
2642}
2643
2644
2645ngx_int_t
2646ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
2647{
2648    ngx_http_core_srv_conf_t    *cscf;
2649    ngx_http_core_loc_conf_t   **clcfp;
2650    ngx_http_core_main_conf_t   *cmcf;
2651
2652    r->main->count++;
2653    r->uri_changes--;
2654
2655    if (r->uri_changes == 0) {
2656        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2657                      "rewrite or internal redirection cycle "
2658                      "while redirect to named location \"%V\"", name);
2659
2660        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2661        return NGX_DONE;
2662    }
2663
2664    if (r->uri.len == 0) {
2665        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2666                      "empty URI in redirect to named location \"%V\"", name);
2667
2668        ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2669        return NGX_DONE;
2670    }
2671
2672    cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2673
2674    if (cscf->named_locations) {
2675
2676        for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
2677
2678            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2679                           "test location: \"%V\"", &(*clcfp)->name);
2680
2681            if (name->len != (*clcfp)->name.len
2682                || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
2683            {
2684                continue;
2685            }
2686
2687            ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2688                           "using location: %V \"%V?%V\"",
2689                           name, &r->uri, &r->args);
2690
2691            r->internal = 1;
2692            r->content_handler = NULL;
2693            r->uri_changed = 0;
2694            r->loc_conf = (*clcfp)->loc_conf;
2695
2696            /* clear the modules contexts */
2697            ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2698
2699            ngx_http_update_location_config(r);
2700
2701            cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2702
2703            r->phase_handler = cmcf->phase_engine.location_rewrite_index;
2704
2705            r->write_event_handler = ngx_http_core_run_phases;
2706            ngx_http_core_run_phases(r);
2707
2708            return NGX_DONE;
2709        }
2710    }
2711
2712    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2713                  "could not find named location \"%V\"", name);
2714
2715    ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2716
2717    return NGX_DONE;
2718}
2719
2720
2721ngx_http_cleanup_t *
2722ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
2723{
2724    ngx_http_cleanup_t  *cln;
2725
2726    r = r->main;
2727
2728    cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
2729    if (cln == NULL) {
2730        return NULL;
2731    }
2732
2733    if (size) {
2734        cln->data = ngx_palloc(r->pool, size);
2735        if (cln->data == NULL) {
2736            return NULL;
2737        }
2738
2739    } else {
2740        cln->data = NULL;
2741    }
2742
2743    cln->handler = NULL;
2744    cln->next = r->cleanup;
2745
2746    r->cleanup = cln;
2747
2748    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2749                   "http cleanup add: %p", cln);
2750
2751    return cln;
2752}
2753
2754
2755ngx_int_t
2756ngx_http_set_disable_symlinks(ngx_http_request_t *r,
2757    ngx_http_core_loc_conf_t *clcf, ngx_str_t *path, ngx_open_file_info_t *of)
2758{
2759#if (NGX_HAVE_OPENAT)
2760    u_char     *p;
2761    ngx_str_t   from;
2762
2763    of->disable_symlinks = clcf->disable_symlinks;
2764
2765    if (clcf->disable_symlinks_from == NULL) {
2766        return NGX_OK;
2767    }
2768
2769    if (ngx_http_complex_value(r, clcf->disable_symlinks_from, &from)
2770        != NGX_OK)
2771    {
2772        return NGX_ERROR;
2773    }
2774
2775    if (from.len == 0
2776        || from.len > path->len
2777        || ngx_memcmp(path->data, from.data, from.len) != 0)
2778    {
2779        return NGX_OK;
2780    }
2781
2782    if (from.len == path->len) {
2783        of->disable_symlinks = NGX_DISABLE_SYMLINKS_OFF;
2784        return NGX_OK;
2785    }
2786
2787    p = path->data + from.len;
2788
2789    if (*p == '/') {
2790        of->disable_symlinks_from = from.len;
2791        return NGX_OK;
2792    }
2793
2794    p--;
2795
2796    if (*p == '/') {
2797        of->disable_symlinks_from = from.len - 1;
2798    }
2799#endif
2800
2801    return NGX_OK;
2802}
2803
2804
2805ngx_int_t
2806ngx_http_get_forwarded_addr(ngx_http_request_t *r, ngx_addr_t *addr,
2807    ngx_array_t *headers, ngx_str_t *value, ngx_array_t *proxies,
2808    int recursive)
2809{
2810    ngx_int_t          rc;
2811    ngx_uint_t         i, found;
2812    ngx_table_elt_t  **h;
2813
2814    if (headers == NULL) {
2815        return ngx_http_get_forwarded_addr_internal(r, addr, value->data,
2816                                                    value->len, proxies,
2817                                                    recursive);
2818    }
2819
2820    i = headers->nelts;
2821    h = headers->elts;
2822
2823    rc = NGX_DECLINED;
2824
2825    found = 0;
2826
2827    while (i-- > 0) {
2828        rc = ngx_http_get_forwarded_addr_internal(r, addr, h[i]->value.data,
2829                                                  h[i]->value.len, proxies,
2830                                                  recursive);
2831
2832        if (!recursive) {
2833            break;
2834        }
2835
2836        if (rc == NGX_DECLINED && found) {
2837            rc = NGX_DONE;
2838            break;
2839        }
2840
2841        if (rc != NGX_OK) {
2842            break;
2843        }
2844
2845        found = 1;
2846    }
2847
2848    return rc;
2849}
2850
2851
2852static ngx_int_t
2853ngx_http_get_forwarded_addr_internal(ngx_http_request_t *r, ngx_addr_t *addr,
2854    u_char *xff, size_t xfflen, ngx_array_t *proxies, int recursive)
2855{
2856    u_char      *p;
2857    ngx_int_t    rc;
2858    ngx_addr_t   paddr;
2859
2860    if (ngx_cidr_match(addr->sockaddr, proxies) != NGX_OK) {
2861        return NGX_DECLINED;
2862    }
2863
2864    for (p = xff + xfflen - 1; p > xff; p--, xfflen--) {
2865        if (*p != ' ' && *p != ',') {
2866            break;
2867        }
2868    }
2869
2870    for ( /* void */ ; p > xff; p--) {
2871        if (*p == ' ' || *p == ',') {
2872            p++;
2873            break;
2874        }
2875    }
2876
2877    if (ngx_parse_addr_port(r->pool, &paddr, p, xfflen - (p - xff)) != NGX_OK) {
2878        return NGX_DECLINED;
2879    }
2880
2881    *addr = paddr;
2882
2883    if (recursive && p > xff) {
2884        rc = ngx_http_get_forwarded_addr_internal(r, addr, xff, p - 1 - xff,
2885                                                  proxies, 1);
2886
2887        if (rc == NGX_DECLINED) {
2888            return NGX_DONE;
2889        }
2890
2891        /* rc == NGX_OK || rc == NGX_DONE  */
2892        return rc;
2893    }
2894
2895    return NGX_OK;
2896}
2897
2898
2899static char *
2900ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2901{
2902    char                        *rv;
2903    void                        *mconf;
2904    ngx_uint_t                   i;
2905    ngx_conf_t                   pcf;
2906    ngx_http_module_t           *module;
2907    struct sockaddr_in          *sin;
2908    ngx_http_conf_ctx_t         *ctx, *http_ctx;
2909    ngx_http_listen_opt_t        lsopt;
2910    ngx_http_core_srv_conf_t    *cscf, **cscfp;
2911    ngx_http_core_main_conf_t   *cmcf;
2912
2913    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2914    if (ctx == NULL) {
2915        return NGX_CONF_ERROR;
2916    }
2917
2918    http_ctx = cf->ctx;
2919    ctx->main_conf = http_ctx->main_conf;
2920
2921    /* the server{}'s srv_conf */
2922
2923    ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2924    if (ctx->srv_conf == NULL) {
2925        return NGX_CONF_ERROR;
2926    }
2927
2928    /* the server{}'s loc_conf */
2929
2930    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2931    if (ctx->loc_conf == NULL) {
2932        return NGX_CONF_ERROR;
2933    }
2934
2935    for (i = 0; cf->cycle->modules[i]; i++) {
2936        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
2937            continue;
2938        }
2939
2940        module = cf->cycle->modules[i]->ctx;
2941
2942        if (module->create_srv_conf) {
2943            mconf = module->create_srv_conf(cf);
2944            if (mconf == NULL) {
2945                return NGX_CONF_ERROR;
2946            }
2947
2948            ctx->srv_conf[cf->cycle->modules[i]->ctx_index] = mconf;
2949        }
2950
2951        if (module->create_loc_conf) {
2952            mconf = module->create_loc_conf(cf);
2953            if (mconf == NULL) {
2954                return NGX_CONF_ERROR;
2955            }
2956
2957            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
2958        }
2959    }
2960
2961
2962    /* the server configuration context */
2963
2964    cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
2965    cscf->ctx = ctx;
2966
2967
2968    cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
2969
2970    cscfp = ngx_array_push(&cmcf->servers);
2971    if (cscfp == NULL) {
2972        return NGX_CONF_ERROR;
2973    }
2974
2975    *cscfp = cscf;
2976
2977
2978    /* parse inside server{} */
2979
2980    pcf = *cf;
2981    cf->ctx = ctx;
2982    cf->cmd_type = NGX_HTTP_SRV_CONF;
2983
2984    rv = ngx_conf_parse(cf, NULL);
2985
2986    *cf = pcf;
2987
2988    if (rv == NGX_CONF_OK && !cscf->listen) {
2989        ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
2990
2991        sin = &lsopt.sockaddr.sockaddr_in;
2992
2993        sin->sin_family = AF_INET;
2994#if (NGX_WIN32)
2995        sin->sin_port = htons(80);
2996#else
2997        sin->sin_port = htons((getuid() == 0) ? 80 : 8000);
2998#endif
2999        sin->sin_addr.s_addr = INADDR_ANY;
3000
3001        lsopt.socklen = sizeof(struct sockaddr_in);
3002
3003        lsopt.backlog = NGX_LISTEN_BACKLOG;
3004        lsopt.rcvbuf = -1;
3005        lsopt.sndbuf = -1;
3006#if (NGX_HAVE_SETFIB)
3007        lsopt.setfib = -1;
3008#endif
3009#if (NGX_HAVE_TCP_FASTOPEN)
3010        lsopt.fastopen = -1;
3011#endif
3012        lsopt.wildcard = 1;
3013
3014        (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen,
3015                             lsopt.addr, NGX_SOCKADDR_STRLEN, 1);
3016
3017        if (ngx_http_add_listen(cf, cscf, &lsopt) != NGX_OK) {
3018            return NGX_CONF_ERROR;
3019        }
3020    }
3021
3022    return rv;
3023}
3024
3025
3026static char *
3027ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
3028{
3029    char                      *rv;
3030    u_char                    *mod;
3031    size_t                     len;
3032    ngx_str_t                 *value, *name;
3033    ngx_uint_t                 i;
3034    ngx_conf_t                 save;
3035    ngx_http_module_t         *module;
3036    ngx_http_conf_ctx_t       *ctx, *pctx;
3037    ngx_http_core_loc_conf_t  *clcf, *pclcf;
3038
3039    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3040    if (ctx == NULL) {
3041        return NGX_CONF_ERROR;
3042    }
3043
3044    pctx = cf->ctx;
3045    ctx->main_conf = pctx->main_conf;
3046    ctx->srv_conf = pctx->srv_conf;
3047
3048    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
3049    if (ctx->loc_conf == NULL) {
3050        return NGX_CONF_ERROR;
3051    }
3052
3053    for (i = 0; cf->cycle->modules[i]; i++) {
3054        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
3055            continue;
3056        }
3057
3058        module = cf->cycle->modules[i]->ctx;
3059
3060        if (module->create_loc_conf) {
3061            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] =
3062                                                   module->create_loc_conf(cf);
3063            if (ctx->loc_conf[cf->cycle->modules[i]->ctx_index] == NULL) {
3064                return NGX_CONF_ERROR;
3065            }
3066        }
3067    }
3068
3069    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
3070    clcf->loc_conf = ctx->loc_conf;
3071
3072    value = cf->args->elts;
3073
3074    if (cf->args->nelts == 3) {
3075
3076        len = value[1].len;
3077        mod = value[1].data;
3078        name = &value[2];
3079
3080        if (len == 1 && mod[0] == '=') {
3081
3082            clcf->name = *name;
3083            clcf->exact_match = 1;
3084
3085        } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
3086
3087            clcf->name = *name;
3088            clcf->noregex = 1;
3089
3090        } else if (len == 1 && mod[0] == '~') {
3091
3092            if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
3093                return NGX_CONF_ERROR;
3094            }
3095
3096        } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
3097
3098            if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
3099                return NGX_CONF_ERROR;
3100            }
3101
3102        } else {
3103            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3104                               "invalid location modifier \"%V\"", &value[1]);
3105            return NGX_CONF_ERROR;
3106        }
3107
3108    } else {
3109
3110        name = &value[1];
3111
3112        if (name->data[0] == '=') {
3113
3114            clcf->name.len = name->len - 1;
3115            clcf->name.data = name->data + 1;
3116            clcf->exact_match = 1;
3117
3118        } else if (name->data[0] == '^' && name->data[1] == '~') {
3119
3120            clcf->name.len = name->len - 2;
3121            clcf->name.data = name->data + 2;
3122            clcf->noregex = 1;
3123
3124        } else if (name->data[0] == '~') {
3125
3126            name->len--;
3127            name->data++;
3128
3129            if (name->data[0] == '*') {
3130
3131                name->len--;
3132                name->data++;
3133
3134                if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
3135                    return NGX_CONF_ERROR;
3136                }
3137
3138            } else {
3139                if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
3140                    return NGX_CONF_ERROR;
3141                }
3142            }
3143
3144        } else {
3145
3146            clcf->name = *name;
3147
3148            if (name->data[0] == '@') {
3149                clcf->named = 1;
3150            }
3151        }
3152    }
3153
3154    pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
3155
3156    if (cf->cmd_type == NGX_HTTP_LOC_CONF) {
3157
3158        /* nested location */
3159
3160#if 0
3161        clcf->prev_location = pclcf;
3162#endif
3163
3164        if (pclcf->exact_match) {
3165            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3166                               "location \"%V\" cannot be inside "
3167                               "the exact location \"%V\"",
3168                               &clcf->name, &pclcf->name);
3169            return NGX_CONF_ERROR;
3170        }
3171
3172        if (pclcf->named) {
3173            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3174                               "location \"%V\" cannot be inside "
3175                               "the named location \"%V\"",
3176                               &clcf->name, &pclcf->name);
3177            return NGX_CONF_ERROR;
3178        }
3179
3180        if (clcf->named) {
3181            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3182                               "named location \"%V\" can be "
3183                               "on the server level only",
3184                               &clcf->name);
3185            return NGX_CONF_ERROR;
3186        }
3187
3188        len = pclcf->name.len;
3189
3190#if (NGX_PCRE)
3191        if (clcf->regex == NULL
3192            && ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
3193#else
3194        if (ngx_filename_cmp(clcf->name.data, pclcf->name.data, len) != 0)
3195#endif
3196        {
3197            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3198                               "location \"%V\" is outside location \"%V\"",
3199                               &clcf->name, &pclcf->name);
3200            return NGX_CONF_ERROR;
3201        }
3202    }
3203
3204    if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
3205        return NGX_CONF_ERROR;
3206    }
3207
3208    save = *cf;
3209    cf->ctx = ctx;
3210    cf->cmd_type = NGX_HTTP_LOC_CONF;
3211
3212    rv = ngx_conf_parse(cf, NULL);
3213
3214    *cf = save;
3215
3216    return rv;
3217}
3218
3219
3220static ngx_int_t
3221ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
3222    ngx_str_t *regex, ngx_uint_t caseless)
3223{
3224#if (NGX_PCRE)
3225    ngx_regex_compile_t  rc;
3226    u_char               errstr[NGX_MAX_CONF_ERRSTR];
3227
3228    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
3229
3230    rc.pattern = *regex;
3231    rc.err.len = NGX_MAX_CONF_ERRSTR;
3232    rc.err.data = errstr;
3233
3234#if (NGX_HAVE_CASELESS_FILESYSTEM)
3235    rc.options = NGX_REGEX_CASELESS;
3236#else
3237    rc.options = caseless ? NGX_REGEX_CASELESS : 0;
3238#endif
3239
3240    clcf->regex = ngx_http_regex_compile(cf, &rc);
3241    if (clcf->regex == NULL) {
3242        return NGX_ERROR;
3243    }
3244
3245    clcf->name = *regex;
3246
3247    return NGX_OK;
3248
3249#else
3250
3251    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3252                       "using regex \"%V\" requires PCRE library",
3253                       regex);
3254    return NGX_ERROR;
3255
3256#endif
3257}
3258
3259
3260static char *
3261ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3262{
3263    ngx_http_core_loc_conf_t *clcf = conf;
3264
3265    char        *rv;
3266    ngx_conf_t   save;
3267
3268    if (clcf->types == NULL) {
3269        clcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
3270        if (clcf->types == NULL) {
3271            return NGX_CONF_ERROR;
3272        }
3273    }
3274
3275    save = *cf;
3276    cf->handler = ngx_http_core_type;
3277    cf->handler_conf = conf;
3278
3279    rv = ngx_conf_parse(cf, NULL);
3280
3281    *cf = save;
3282
3283    return rv;
3284}
3285
3286
3287static char *
3288ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
3289{
3290    ngx_http_core_loc_conf_t *clcf = conf;
3291
3292    ngx_str_t       *value, *content_type, *old;
3293    ngx_uint_t       i, n, hash;
3294    ngx_hash_key_t  *type;
3295
3296    value = cf->args->elts;
3297
3298    if (ngx_strcmp(value[0].data, "include") == 0) {
3299        if (cf->args->nelts != 2) {
3300            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3301                               "invalid number of arguments"
3302                               " in \"include\" directive");
3303            return NGX_CONF_ERROR;
3304        }
3305
3306        return ngx_conf_include(cf, dummy, conf);
3307    }
3308
3309    content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
3310    if (content_type == NULL) {
3311        return NGX_CONF_ERROR;
3312    }
3313
3314    *content_type = value[0];
3315
3316    for (i = 1; i < cf->args->nelts; i++) {
3317
3318        hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
3319
3320        type = clcf->types->elts;
3321        for (n = 0; n < clcf->types->nelts; n++) {
3322            if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
3323                old = type[n].value;
3324                type[n].value = content_type;
3325
3326                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3327                                   "duplicate extension \"%V\", "
3328                                   "content type: \"%V\", "
3329                                   "previous content type: \"%V\"",
3330                                   &value[i], content_type, old);
3331                goto next;
3332            }
3333        }
3334
3335
3336        type = ngx_array_push(clcf->types);
3337        if (type == NULL) {
3338            return NGX_CONF_ERROR;
3339        }
3340
3341        type->key = value[i];
3342        type->key_hash = hash;
3343        type->value = content_type;
3344
3345    next:
3346        continue;
3347    }
3348
3349    return NGX_CONF_OK;
3350}
3351
3352
3353static ngx_int_t
3354ngx_http_core_preconfiguration(ngx_conf_t *cf)
3355{
3356    return ngx_http_variables_add_core_vars(cf);
3357}
3358
3359
3360static ngx_int_t
3361ngx_http_core_postconfiguration(ngx_conf_t *cf)
3362{
3363    ngx_http_top_request_body_filter = ngx_http_request_body_save_filter;
3364
3365    return NGX_OK;
3366}
3367
3368
3369static void *
3370ngx_http_core_create_main_conf(ngx_conf_t *cf)
3371{
3372    ngx_http_core_main_conf_t  *cmcf;
3373
3374    cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
3375    if (cmcf == NULL) {
3376        return NULL;
3377    }
3378
3379    if (ngx_array_init(&cmcf->servers, cf->pool, 4,
3380                       sizeof(ngx_http_core_srv_conf_t *))
3381        != NGX_OK)
3382    {
3383        return NULL;
3384    }
3385
3386    cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
3387    cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
3388
3389    cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
3390    cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
3391
3392    return cmcf;
3393}
3394
3395
3396static char *
3397ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
3398{
3399    ngx_http_core_main_conf_t *cmcf = conf;
3400
3401    ngx_conf_init_uint_value(cmcf->server_names_hash_max_size, 512);
3402    ngx_conf_init_uint_value(cmcf->server_names_hash_bucket_size,
3403                             ngx_cacheline_size);
3404
3405    cmcf->server_names_hash_bucket_size =
3406            ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
3407
3408
3409    ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
3410    ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);
3411
3412    cmcf->variables_hash_bucket_size =
3413               ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
3414
3415    if (cmcf->ncaptures) {
3416        cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
3417    }
3418
3419    return NGX_CONF_OK;
3420}
3421
3422
3423static void *
3424ngx_http_core_create_srv_conf(ngx_conf_t *cf)
3425{
3426    ngx_http_core_srv_conf_t  *cscf;
3427
3428    cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
3429    if (cscf == NULL) {
3430        return NULL;
3431    }
3432
3433    /*
3434     * set by ngx_pcalloc():
3435     *
3436     *     conf->client_large_buffers.num = 0;
3437     */
3438
3439    if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
3440                       sizeof(ngx_http_server_name_t))
3441        != NGX_OK)
3442    {
3443        return NULL;
3444    }
3445
3446    cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
3447    cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
3448    cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
3449    cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
3450    cscf->ignore_invalid_headers = NGX_CONF_UNSET;
3451    cscf->merge_slashes = NGX_CONF_UNSET;
3452    cscf->underscores_in_headers = NGX_CONF_UNSET;
3453
3454    return cscf;
3455}
3456
3457
3458static char *
3459ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
3460{
3461    ngx_http_core_srv_conf_t *prev = parent;
3462    ngx_http_core_srv_conf_t *conf = child;
3463
3464    ngx_str_t                name;
3465    ngx_http_server_name_t  *sn;
3466
3467    /* TODO: it does not merge, it inits only */
3468
3469    ngx_conf_merge_size_value(conf->connection_pool_size,
3470                              prev->connection_pool_size, 64 * sizeof(void *));
3471    ngx_conf_merge_size_value(conf->request_pool_size,
3472                              prev->request_pool_size, 4096);
3473    ngx_conf_merge_msec_value(conf->client_header_timeout,
3474                              prev->client_header_timeout, 60000);
3475    ngx_conf_merge_size_value(conf->client_header_buffer_size,
3476                              prev->client_header_buffer_size, 1024);
3477    ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
3478                              prev->large_client_header_buffers,
3479                              4, 8192);
3480
3481    if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
3482        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3483                           "the \"large_client_header_buffers\" size must be "
3484                           "equal to or greater than \"connection_pool_size\"");
3485        return NGX_CONF_ERROR;
3486    }
3487
3488    ngx_conf_merge_value(conf->ignore_invalid_headers,
3489                              prev->ignore_invalid_headers, 1);
3490
3491    ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
3492
3493    ngx_conf_merge_value(conf->underscores_in_headers,
3494                              prev->underscores_in_headers, 0);
3495
3496    if (conf->server_names.nelts == 0) {
3497        /* the array has 4 empty preallocated elements, so push cannot fail */
3498        sn = ngx_array_push(&conf->server_names);
3499#if (NGX_PCRE)
3500        sn->regex = NULL;
3501#endif
3502        sn->server = conf;
3503        ngx_str_set(&sn->name, "");
3504    }
3505
3506    sn = conf->server_names.elts;
3507    name = sn[0].name;
3508
3509#if (NGX_PCRE)
3510    if (sn->regex) {
3511        name.len++;
3512        name.data--;
3513    } else
3514#endif
3515
3516    if (name.data[0] == '.') {
3517        name.len--;
3518        name.data++;
3519    }
3520
3521    conf->server_name.len = name.len;
3522    conf->server_name.data = ngx_pstrdup(cf->pool, &name);
3523    if (conf->server_name.data == NULL) {
3524        return NGX_CONF_ERROR;
3525    }
3526
3527    return NGX_CONF_OK;
3528}
3529
3530
3531static void *
3532ngx_http_core_create_loc_conf(ngx_conf_t *cf)
3533{
3534    ngx_http_core_loc_conf_t  *clcf;
3535
3536    clcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
3537    if (clcf == NULL) {
3538        return NULL;
3539    }
3540
3541    /*
3542     * set by ngx_pcalloc():
3543     *
3544     *     clcf->root = { 0, NULL };
3545     *     clcf->limit_except = 0;
3546     *     clcf->post_action = { 0, NULL };
3547     *     clcf->types = NULL;
3548     *     clcf->default_type = { 0, NULL };
3549     *     clcf->error_log = NULL;
3550     *     clcf->error_pages = NULL;
3551     *     clcf->try_files = NULL;
3552     *     clcf->client_body_path = NULL;
3553     *     clcf->regex = NULL;
3554     *     clcf->exact_match = 0;
3555     *     clcf->auto_redirect = 0;
3556     *     clcf->alias = 0;
3557     *     clcf->gzip_proxied = 0;
3558     *     clcf->keepalive_disable = 0;
3559     */
3560
3561    clcf->client_max_body_size = NGX_CONF_UNSET;
3562    clcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
3563    clcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
3564    clcf->satisfy = NGX_CONF_UNSET_UINT;
3565    clcf->if_modified_since = NGX_CONF_UNSET_UINT;
3566    clcf->max_ranges = NGX_CONF_UNSET_UINT;
3567    clcf->client_body_in_file_only = NGX_CONF_UNSET_UINT;
3568    clcf->client_body_in_single_buffer = NGX_CONF_UNSET;
3569    clcf->internal = NGX_CONF_UNSET;
3570    clcf->sendfile = NGX_CONF_UNSET;
3571    clcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
3572    clcf->aio = NGX_CONF_UNSET;
3573    clcf->aio_write = NGX_CONF_UNSET;
3574#if (NGX_THREADS)
3575    clcf->thread_pool = NGX_CONF_UNSET_PTR;
3576    clcf->thread_pool_value = NGX_CONF_UNSET_PTR;
3577#endif
3578    clcf->read_ahead = NGX_CONF_UNSET_SIZE;
3579    clcf->directio = NGX_CONF_UNSET;
3580    clcf->directio_alignment = NGX_CONF_UNSET;
3581    clcf->tcp_nopush = NGX_CONF_UNSET;
3582    clcf->tcp_nodelay = NGX_CONF_UNSET;
3583    clcf->send_timeout = NGX_CONF_UNSET_MSEC;
3584    clcf->send_lowat = NGX_CONF_UNSET_SIZE;
3585    clcf->postpone_output = NGX_CONF_UNSET_SIZE;
3586    clcf->limit_rate = NGX_CONF_UNSET_SIZE;
3587    clcf->limit_rate_after = NGX_CONF_UNSET_SIZE;
3588    clcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
3589    clcf->keepalive_header = NGX_CONF_UNSET;
3590    clcf->keepalive_requests = NGX_CONF_UNSET_UINT;
3591    clcf->lingering_close = NGX_CONF_UNSET_UINT;
3592    clcf->lingering_time = NGX_CONF_UNSET_MSEC;
3593    clcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
3594    clcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
3595    clcf->reset_timedout_connection = NGX_CONF_UNSET;
3596    clcf->absolute_redirect = NGX_CONF_UNSET;
3597    clcf->server_name_in_redirect = NGX_CONF_UNSET;
3598    clcf->port_in_redirect = NGX_CONF_UNSET;
3599    clcf->msie_padding = NGX_CONF_UNSET;
3600    clcf->msie_refresh = NGX_CONF_UNSET;
3601    clcf->log_not_found = NGX_CONF_UNSET;
3602    clcf->log_subrequest = NGX_CONF_UNSET;
3603    clcf->recursive_error_pages = NGX_CONF_UNSET;
3604    clcf->chunked_transfer_encoding = NGX_CONF_UNSET;
3605    clcf->etag = NGX_CONF_UNSET;
3606    clcf->server_tokens = NGX_CONF_UNSET_UINT;
3607    clcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
3608    clcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
3609
3610    clcf->open_file_cache = NGX_CONF_UNSET_PTR;
3611    clcf->open_file_cache_valid = NGX_CONF_UNSET;
3612    clcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
3613    clcf->open_file_cache_errors = NGX_CONF_UNSET;
3614    clcf->open_file_cache_events = NGX_CONF_UNSET;
3615
3616#if (NGX_HTTP_GZIP)
3617    clcf->gzip_vary = NGX_CONF_UNSET;
3618    clcf->gzip_http_version = NGX_CONF_UNSET_UINT;
3619#if (NGX_PCRE)
3620    clcf->gzip_disable = NGX_CONF_UNSET_PTR;
3621#endif
3622    clcf->gzip_disable_msie6 = 3;
3623#if (NGX_HTTP_DEGRADATION)
3624    clcf->gzip_disable_degradation = 3;
3625#endif
3626#endif
3627
3628#if (NGX_HAVE_OPENAT)
3629    clcf->disable_symlinks = NGX_CONF_UNSET_UINT;
3630    clcf->disable_symlinks_from = NGX_CONF_UNSET_PTR;
3631#endif
3632
3633    return clcf;
3634}
3635
3636
3637static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
3638static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
3639static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
3640
3641static ngx_hash_key_t  ngx_http_core_default_types[] = {
3642    { ngx_string("html"), 0, &ngx_http_core_text_html_type },
3643    { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
3644    { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
3645    { ngx_null_string, 0, NULL }
3646};
3647
3648
3649static char *
3650ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
3651{
3652    ngx_http_core_loc_conf_t *prev = parent;
3653    ngx_http_core_loc_conf_t *conf = child;
3654
3655    ngx_uint_t        i;
3656    ngx_hash_key_t   *type;
3657    ngx_hash_init_t   types_hash;
3658
3659    if (conf->root.data == NULL) {
3660
3661        conf->alias = prev->alias;
3662        conf->root = prev->root;
3663        conf->root_lengths = prev->root_lengths;
3664        conf->root_values = prev->root_values;
3665
3666        if (prev->root.data == NULL) {
3667            ngx_str_set(&conf->root, "html");
3668
3669            if (ngx_conf_full_name(cf->cycle, &conf->root, 0) != NGX_OK) {
3670                return NGX_CONF_ERROR;
3671            }
3672        }
3673    }
3674
3675    if (conf->post_action.data == NULL) {
3676        conf->post_action = prev->post_action;
3677    }
3678
3679    ngx_conf_merge_uint_value(conf->types_hash_max_size,
3680                              prev->types_hash_max_size, 1024);
3681
3682    ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
3683                              prev->types_hash_bucket_size, 64);
3684
3685    conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
3686                                             ngx_cacheline_size);
3687
3688    /*
3689     * the special handling of the "types" directive in the "http" section
3690     * to inherit the http's conf->types_hash to all servers
3691     */
3692
3693    if (prev->types && prev->types_hash.buckets == NULL) {
3694
3695        types_hash.hash = &prev->types_hash;
3696        types_hash.key = ngx_hash_key_lc;
3697        types_hash.max_size = conf->types_hash_max_size;
3698        types_hash.bucket_size = conf->types_hash_bucket_size;
3699        types_hash.name = "types_hash";
3700        types_hash.pool = cf->pool;
3701        types_hash.temp_pool = NULL;
3702
3703        if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
3704            != NGX_OK)
3705        {
3706            return NGX_CONF_ERROR;
3707        }
3708    }
3709
3710    if (conf->types == NULL) {
3711        conf->types = prev->types;
3712        conf->types_hash = prev->types_hash;
3713    }
3714
3715    if (conf->types == NULL) {
3716        conf->types = ngx_array_create(cf->pool, 3, sizeof(ngx_hash_key_t));
3717        if (conf->types == NULL) {
3718            return NGX_CONF_ERROR;
3719        }
3720
3721        for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
3722            type = ngx_array_push(conf->types);
3723            if (type == NULL) {
3724                return NGX_CONF_ERROR;
3725            }
3726
3727            type->key = ngx_http_core_default_types[i].key;
3728            type->key_hash =
3729                       ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3730                                       ngx_http_core_default_types[i].key.len);
3731            type->value = ngx_http_core_default_types[i].value;
3732        }
3733    }
3734
3735    if (conf->types_hash.buckets == NULL) {
3736
3737        types_hash.hash = &conf->types_hash;
3738        types_hash.key = ngx_hash_key_lc;
3739        types_hash.max_size = conf->types_hash_max_size;
3740        types_hash.bucket_size = conf->types_hash_bucket_size;
3741        types_hash.name = "types_hash";
3742        types_hash.pool = cf->pool;
3743        types_hash.temp_pool = NULL;
3744
3745        if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3746            != NGX_OK)
3747        {
3748            return NGX_CONF_ERROR;
3749        }
3750    }
3751
3752    if (conf->error_log == NULL) {
3753        if (prev->error_log) {
3754            conf->error_log = prev->error_log;
3755        } else {
3756            conf->error_log = &cf->cycle->new_log;
3757        }
3758    }
3759
3760    if (conf->error_pages == NULL && prev->error_pages) {
3761        conf->error_pages = prev->error_pages;
3762    }
3763
3764    ngx_conf_merge_str_value(conf->default_type,
3765                              prev->default_type, "text/plain");
3766
3767    ngx_conf_merge_off_value(conf->client_max_body_size,
3768                              prev->client_max_body_size, 1 * 1024 * 1024);
3769    ngx_conf_merge_size_value(conf->client_body_buffer_size,
3770                              prev->client_body_buffer_size,
3771                              (size_t) 2 * ngx_pagesize);
3772    ngx_conf_merge_msec_value(conf->client_body_timeout,
3773                              prev->client_body_timeout, 60000);
3774
3775    ngx_conf_merge_bitmask_value(conf->keepalive_disable,
3776                              prev->keepalive_disable,
3777                              (NGX_CONF_BITMASK_SET
3778                               |NGX_HTTP_KEEPALIVE_DISABLE_MSIE6));
3779    ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3780                              NGX_HTTP_SATISFY_ALL);
3781    ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3782                              NGX_HTTP_IMS_EXACT);
3783    ngx_conf_merge_uint_value(conf->max_ranges, prev->max_ranges,
3784                              NGX_MAX_INT32_VALUE);
3785    ngx_conf_merge_uint_value(conf->client_body_in_file_only,
3786                              prev->client_body_in_file_only,
3787                              NGX_HTTP_REQUEST_BODY_FILE_OFF);
3788    ngx_conf_merge_value(conf->client_body_in_single_buffer,
3789                              prev->client_body_in_single_buffer, 0);
3790    ngx_conf_merge_value(conf->internal, prev->internal, 0);
3791    ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3792    ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3793                              prev->sendfile_max_chunk, 0);
3794    ngx_conf_merge_value(conf->aio, prev->aio, NGX_HTTP_AIO_OFF);
3795    ngx_conf_merge_value(conf->aio_write, prev->aio_write, 0);
3796#if (NGX_THREADS)
3797    ngx_conf_merge_ptr_value(conf->thread_pool, prev->thread_pool, NULL);
3798    ngx_conf_merge_ptr_value(conf->thread_pool_value, prev->thread_pool_value,
3799                             NULL);
3800#endif
3801    ngx_conf_merge_size_value(conf->read_ahead, prev->read_ahead, 0);
3802    ngx_conf_merge_off_value(conf->directio, prev->directio,
3803                              NGX_OPEN_FILE_DIRECTIO_OFF);
3804    ngx_conf_merge_off_value(conf->directio_alignment, prev->directio_alignment,
3805                              512);
3806    ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3807    ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3808
3809    ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3810    ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3811    ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3812                              1460);
3813    ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3814    ngx_conf_merge_size_value(conf->limit_rate_after, prev->limit_rate_after,
3815                              0);
3816    ngx_conf_merge_msec_value(conf->keepalive_timeout,
3817                              prev->keepalive_timeout, 75000);
3818    ngx_conf_merge_sec_value(conf->keepalive_header,
3819                              prev->keepalive_header, 0);
3820    ngx_conf_merge_uint_value(conf->keepalive_requests,
3821                              prev->keepalive_requests, 100);
3822    ngx_conf_merge_uint_value(conf->lingering_close,
3823                              prev->lingering_close, NGX_HTTP_LINGERING_ON);
3824    ngx_conf_merge_msec_value(conf->lingering_time,
3825                              prev->lingering_time, 30000);
3826    ngx_conf_merge_msec_value(conf->lingering_timeout,
3827                              prev->lingering_timeout, 5000);
3828    ngx_conf_merge_msec_value(conf->resolver_timeout,
3829                              prev->resolver_timeout, 30000);
3830
3831    if (conf->resolver == NULL) {
3832
3833        if (prev->resolver == NULL) {
3834
3835            /*
3836             * create dummy resolver in http {} context
3837             * to inherit it in all servers
3838             */
3839
3840            prev->resolver = ngx_resolver_create(cf, NULL, 0);
3841            if (prev->resolver == NULL) {
3842                return NGX_CONF_ERROR;
3843            }
3844        }
3845
3846        conf->resolver = prev->resolver;
3847    }
3848
3849    if (ngx_conf_merge_path_value(cf, &conf->client_body_temp_path,
3850                              prev->client_body_temp_path,
3851                              &ngx_http_client_temp_path)
3852        != NGX_OK)
3853    {
3854        return NGX_CONF_ERROR;
3855    }
3856
3857    ngx_conf_merge_value(conf->reset_timedout_connection,
3858                              prev->reset_timedout_connection, 0);
3859    ngx_conf_merge_value(conf->absolute_redirect,
3860                              prev->absolute_redirect, 1);
3861    ngx_conf_merge_value(conf->server_name_in_redirect,
3862                              prev->server_name_in_redirect, 0);
3863    ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3864    ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3865    ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3866    ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3867    ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3868    ngx_conf_merge_value(conf->recursive_error_pages,
3869                              prev->recursive_error_pages, 0);
3870    ngx_conf_merge_value(conf->chunked_transfer_encoding,
3871                              prev->chunked_transfer_encoding, 1);
3872    ngx_conf_merge_value(conf->etag, prev->etag, 1);
3873
3874    ngx_conf_merge_uint_value(conf->server_tokens, prev->server_tokens,
3875                              NGX_HTTP_SERVER_TOKENS_ON);
3876
3877    ngx_conf_merge_ptr_value(conf->open_file_cache,
3878                              prev->open_file_cache, NULL);
3879
3880    ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3881                              prev->open_file_cache_valid, 60);
3882
3883    ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3884                              prev->open_file_cache_min_uses, 1);
3885
3886    ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3887                              prev->open_file_cache_errors, 0);
3888
3889    ngx_conf_merge_sec_value(conf->open_file_cache_events,
3890                              prev->open_file_cache_events, 0);
3891#if (NGX_HTTP_GZIP)
3892
3893    ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3894    ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3895                              NGX_HTTP_VERSION_11);
3896    ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3897                              (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3898
3899#if (NGX_PCRE)
3900    ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3901#endif
3902
3903    if (conf->gzip_disable_msie6 == 3) {
3904        conf->gzip_disable_msie6 =
3905            (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3906    }
3907
3908#if (NGX_HTTP_DEGRADATION)
3909
3910    if (conf->gzip_disable_degradation == 3) {
3911        conf->gzip_disable_degradation =
3912            (prev->gzip_disable_degradation == 3) ?
3913                 0 : prev->gzip_disable_degradation;
3914    }
3915
3916#endif
3917#endif
3918
3919#if (NGX_HAVE_OPENAT)
3920    ngx_conf_merge_uint_value(conf->disable_symlinks, prev->disable_symlinks,
3921                              NGX_DISABLE_SYMLINKS_OFF);
3922    ngx_conf_merge_ptr_value(conf->disable_symlinks_from,
3923                             prev->disable_symlinks_from, NULL);
3924#endif
3925
3926    return NGX_CONF_OK;
3927}
3928
3929
3930static char *
3931ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3932{
3933    ngx_http_core_srv_conf_t *cscf = conf;
3934
3935    ngx_str_t              *value, size;
3936    ngx_url_t               u;
3937    ngx_uint_t              n;
3938    ngx_http_listen_opt_t   lsopt;
3939
3940    cscf->listen = 1;
3941
3942    value = cf->args->elts;
3943
3944    ngx_memzero(&u, sizeof(ngx_url_t));
3945
3946    u.url = value[1];
3947    u.listen = 1;
3948    u.default_port = 80;
3949
3950    if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3951        if (u.err) {
3952            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3953                               "%s in \"%V\" of the \"listen\" directive",
3954                               u.err, &u.url);
3955        }
3956
3957        return NGX_CONF_ERROR;
3958    }
3959
3960    ngx_memzero(&lsopt, sizeof(ngx_http_listen_opt_t));
3961
3962    ngx_memcpy(&lsopt.sockaddr.sockaddr, &u.sockaddr, u.socklen);
3963
3964    lsopt.socklen = u.socklen;
3965    lsopt.backlog = NGX_LISTEN_BACKLOG;
3966    lsopt.rcvbuf = -1;
3967    lsopt.sndbuf = -1;
3968#if (NGX_HAVE_SETFIB)
3969    lsopt.setfib = -1;
3970#endif
3971#if (NGX_HAVE_TCP_FASTOPEN)
3972    lsopt.fastopen = -1;
3973#endif
3974    lsopt.wildcard = u.wildcard;
3975#if (NGX_HAVE_INET6)
3976    lsopt.ipv6only = 1;
3977#endif
3978
3979    (void) ngx_sock_ntop(&lsopt.sockaddr.sockaddr, lsopt.socklen, lsopt.addr,
3980                         NGX_SOCKADDR_STRLEN, 1);
3981
3982    for (n = 2; n < cf->args->nelts; n++) {
3983
3984        if (ngx_strcmp(value[n].data, "default_server") == 0
3985            || ngx_strcmp(value[n].data, "default") == 0)
3986        {
3987            lsopt.default_server = 1;
3988            continue;
3989        }
3990
3991        if (ngx_strcmp(value[n].data, "bind") == 0) {
3992            lsopt.set = 1;
3993            lsopt.bind = 1;
3994            continue;
3995        }
3996
3997#if (NGX_HAVE_SETFIB)
3998        if (ngx_strncmp(value[n].data, "setfib=", 7) == 0) {
3999            lsopt.setfib = ngx_atoi(value[n].data + 7, value[n].len - 7);
4000            lsopt.set = 1;
4001            lsopt.bind = 1;
4002
4003            if (lsopt.setfib == NGX_ERROR) {
4004                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4005                                   "invalid setfib \"%V\"", &value[n]);
4006                return NGX_CONF_ERROR;
4007            }
4008
4009            continue;
4010        }
4011#endif
4012
4013#if (NGX_HAVE_TCP_FASTOPEN)
4014        if (ngx_strncmp(value[n].data, "fastopen=", 9) == 0) {
4015            lsopt.fastopen = ngx_atoi(value[n].data + 9, value[n].len - 9);
4016            lsopt.set = 1;
4017            lsopt.bind = 1;
4018
4019            if (lsopt.fastopen == NGX_ERROR) {
4020                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4021                                   "invalid fastopen \"%V\"", &value[n]);
4022                return NGX_CONF_ERROR;
4023            }
4024
4025            continue;
4026        }
4027#endif
4028
4029        if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
4030            lsopt.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
4031            lsopt.set = 1;
4032            lsopt.bind = 1;
4033
4034            if (lsopt.backlog == NGX_ERROR || lsopt.backlog == 0) {
4035                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4036                                   "invalid backlog \"%V\"", &value[n]);
4037                return NGX_CONF_ERROR;
4038            }
4039
4040            continue;
4041        }
4042
4043        if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
4044            size.len = value[n].len - 7;
4045            size.data = value[n].data + 7;
4046
4047            lsopt.rcvbuf = ngx_parse_size(&size);
4048            lsopt.set = 1;
4049            lsopt.bind = 1;
4050
4051            if (lsopt.rcvbuf == NGX_ERROR) {
4052                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4053                                   "invalid rcvbuf \"%V\"", &value[n]);
4054                return NGX_CONF_ERROR;
4055            }
4056
4057            continue;
4058        }
4059
4060        if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
4061            size.len = value[n].len - 7;
4062            size.data = value[n].data + 7;
4063
4064            lsopt.sndbuf = ngx_parse_size(&size);
4065            lsopt.set = 1;
4066            lsopt.bind = 1;
4067
4068            if (lsopt.sndbuf == NGX_ERROR) {
4069                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4070                                   "invalid sndbuf \"%V\"", &value[n]);
4071                return NGX_CONF_ERROR;
4072            }
4073
4074            continue;
4075        }
4076
4077        if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
4078#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
4079            lsopt.accept_filter = (char *) &value[n].data[14];
4080            lsopt.set = 1;
4081            lsopt.bind = 1;
4082#else
4083            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4084                               "accept filters \"%V\" are not supported "
4085                               "on this platform, ignored",
4086                               &value[n]);
4087#endif
4088            continue;
4089        }
4090
4091        if (ngx_strcmp(value[n].data, "deferred") == 0) {
4092#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
4093            lsopt.deferred_accept = 1;
4094            lsopt.set = 1;
4095            lsopt.bind = 1;
4096#else
4097            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4098                               "the deferred accept is not supported "
4099                               "on this platform, ignored");
4100#endif
4101            continue;
4102        }
4103
4104        if (ngx_strncmp(value[n].data, "ipv6only=o", 10) == 0) {
4105#if (NGX_HAVE_INET6 && defined IPV6_V6ONLY)
4106            struct sockaddr  *sa;
4107
4108            sa = &lsopt.sockaddr.sockaddr;
4109
4110            if (sa->sa_family == AF_INET6) {
4111
4112                if (ngx_strcmp(&value[n].data[10], "n") == 0) {
4113                    lsopt.ipv6only = 1;
4114
4115                } else if (ngx_strcmp(&value[n].data[10], "ff") == 0) {
4116                    lsopt.ipv6only = 0;
4117
4118                } else {
4119                    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4120                                       "invalid ipv6only flags \"%s\"",
4121                                       &value[n].data[9]);
4122                    return NGX_CONF_ERROR;
4123                }
4124
4125                lsopt.set = 1;
4126                lsopt.bind = 1;
4127
4128            } else {
4129                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4130                                   "ipv6only is not supported "
4131                                   "on addr \"%s\", ignored", lsopt.addr);
4132            }
4133
4134            continue;
4135#else
4136            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4137                               "ipv6only is not supported "
4138                               "on this platform");
4139            return NGX_CONF_ERROR;
4140#endif
4141        }
4142
4143        if (ngx_strcmp(value[n].data, "reuseport") == 0) {
4144#if (NGX_HAVE_REUSEPORT)
4145            lsopt.reuseport = 1;
4146            lsopt.set = 1;
4147            lsopt.bind = 1;
4148#else
4149            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4150                               "reuseport is not supported "
4151                               "on this platform, ignored");
4152#endif
4153            continue;
4154        }
4155
4156        if (ngx_strcmp(value[n].data, "ssl") == 0) {
4157#if (NGX_HTTP_SSL)
4158            lsopt.ssl = 1;
4159            continue;
4160#else
4161            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4162                               "the \"ssl\" parameter requires "
4163                               "ngx_http_ssl_module");
4164            return NGX_CONF_ERROR;
4165#endif
4166        }
4167
4168        if (ngx_strcmp(value[n].data, "http2") == 0) {
4169#if (NGX_HTTP_V2)
4170            lsopt.http2 = 1;
4171            continue;
4172#else
4173            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4174                               "the \"http2\" parameter requires "
4175                               "ngx_http_v2_module");
4176            return NGX_CONF_ERROR;
4177#endif
4178        }
4179
4180        if (ngx_strcmp(value[n].data, "spdy") == 0) {
4181            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4182                               "invalid parameter \"spdy\": "
4183                               "ngx_http_spdy_module was superseded "
4184                               "by ngx_http_v2_module");
4185            continue;
4186        }
4187
4188        if (ngx_strncmp(value[n].data, "so_keepalive=", 13) == 0) {
4189
4190            if (ngx_strcmp(&value[n].data[13], "on") == 0) {
4191                lsopt.so_keepalive = 1;
4192
4193            } else if (ngx_strcmp(&value[n].data[13], "off") == 0) {
4194                lsopt.so_keepalive = 2;
4195
4196            } else {
4197
4198#if (NGX_HAVE_KEEPALIVE_TUNABLE)
4199                u_char     *p, *end;
4200                ngx_str_t   s;
4201
4202                end = value[n].data + value[n].len;
4203                s.data = value[n].data + 13;
4204
4205                p = ngx_strlchr(s.data, end, ':');
4206                if (p == NULL) {
4207                    p = end;
4208                }
4209
4210                if (p > s.data) {
4211                    s.len = p - s.data;
4212
4213                    lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
4214                    if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) {
4215                        goto invalid_so_keepalive;
4216                    }
4217                }
4218
4219                s.data = (p < end) ? (p + 1) : end;
4220
4221                p = ngx_strlchr(s.data, end, ':');
4222                if (p == NULL) {
4223                    p = end;
4224                }
4225
4226                if (p > s.data) {
4227                    s.len = p - s.data;
4228
4229                    lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
4230                    if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) {
4231                        goto invalid_so_keepalive;
4232                    }
4233                }
4234
4235                s.data = (p < end) ? (p + 1) : end;
4236
4237                if (s.data < end) {
4238                    s.len = end - s.data;
4239
4240                    lsopt.tcp_keepcnt = ngx_atoi(s.data, s.len);
4241                    if (lsopt.tcp_keepcnt == NGX_ERROR) {
4242                        goto invalid_so_keepalive;
4243                    }
4244                }
4245
4246                if (lsopt.tcp_keepidle == 0 && lsopt.tcp_keepintvl == 0
4247                    && lsopt.tcp_keepcnt == 0)
4248                {
4249                    goto invalid_so_keepalive;
4250                }
4251
4252                lsopt.so_keepalive = 1;
4253
4254#else
4255
4256                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4257                                   "the \"so_keepalive\" parameter accepts "
4258                                   "only \"on\" or \"off\" on this platform");
4259                return NGX_CONF_ERROR;
4260
4261#endif
4262            }
4263
4264            lsopt.set = 1;
4265            lsopt.bind = 1;
4266
4267            continue;
4268
4269#if (NGX_HAVE_KEEPALIVE_TUNABLE)
4270        invalid_so_keepalive:
4271
4272            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4273                               "invalid so_keepalive value: \"%s\"",
4274                               &value[n].data[13]);
4275            return NGX_CONF_ERROR;
4276#endif
4277        }
4278
4279        if (ngx_strcmp(value[n].data, "proxy_protocol") == 0) {
4280            lsopt.proxy_protocol = 1;
4281            continue;
4282        }
4283
4284        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4285                           "invalid parameter \"%V\"", &value[n]);
4286        return NGX_CONF_ERROR;
4287    }
4288
4289    if (ngx_http_add_listen(cf, cscf, &lsopt) == NGX_OK) {
4290        return NGX_CONF_OK;
4291    }
4292
4293    return NGX_CONF_ERROR;
4294}
4295
4296
4297static char *
4298ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4299{
4300    ngx_http_core_srv_conf_t *cscf = conf;
4301
4302    u_char                   ch;
4303    ngx_str_t               *value;
4304    ngx_uint_t               i;
4305    ngx_http_server_name_t  *sn;
4306
4307    value = cf->args->elts;
4308
4309    for (i = 1; i < cf->args->nelts; i++) {
4310
4311        ch = value[i].data[0];
4312
4313        if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
4314            || (ch == '.' && value[i].len < 2))
4315        {
4316            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4317                               "server name \"%V\" is invalid", &value[i]);
4318            return NGX_CONF_ERROR;
4319        }
4320
4321        if (ngx_strchr(value[i].data, '/')) {
4322            ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4323                               "server name \"%V\" has suspicious symbols",
4324                               &value[i]);
4325        }
4326
4327        sn = ngx_array_push(&cscf->server_names);
4328        if (sn == NULL) {
4329            return NGX_CONF_ERROR;
4330        }
4331
4332#if (NGX_PCRE)
4333        sn->regex = NULL;
4334#endif
4335        sn->server = cscf;
4336
4337        if (ngx_strcasecmp(value[i].data, (u_char *) "$hostname") == 0) {
4338            sn->name = cf->cycle->hostname;
4339
4340        } else {
4341            sn->name = value[i];
4342        }
4343
4344        if (value[i].data[0] != '~') {
4345            ngx_strlow(sn->name.data, sn->name.data, sn->name.len);
4346            continue;
4347        }
4348
4349#if (NGX_PCRE)
4350        {
4351        u_char               *p;
4352        ngx_regex_compile_t   rc;
4353        u_char                errstr[NGX_MAX_CONF_ERRSTR];
4354
4355        if (value[i].len == 1) {
4356            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4357                               "empty regex in server name \"%V\"", &value[i]);
4358            return NGX_CONF_ERROR;
4359        }
4360
4361        value[i].len--;
4362        value[i].data++;
4363
4364        ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
4365
4366        rc.pattern = value[i];
4367        rc.err.len = NGX_MAX_CONF_ERRSTR;
4368        rc.err.data = errstr;
4369
4370        for (p = value[i].data; p < value[i].data + value[i].len; p++) {
4371            if (*p >= 'A' && *p <= 'Z') {
4372                rc.options = NGX_REGEX_CASELESS;
4373                break;
4374            }
4375        }
4376
4377        sn->regex = ngx_http_regex_compile(cf, &rc);
4378        if (sn->regex == NULL) {
4379            return NGX_CONF_ERROR;
4380        }
4381
4382        sn->name = value[i];
4383        cscf->captures = (rc.captures > 0);
4384        }
4385#else
4386        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4387                           "using regex \"%V\" "
4388                           "requires PCRE library", &value[i]);
4389
4390        return NGX_CONF_ERROR;
4391#endif
4392    }
4393
4394    return NGX_CONF_OK;
4395}
4396
4397
4398static char *
4399ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4400{
4401    ngx_http_core_loc_conf_t *clcf = conf;
4402
4403    ngx_str_t                  *value;
4404    ngx_int_t                   alias;
4405    ngx_uint_t                  n;
4406    ngx_http_script_compile_t   sc;
4407
4408    alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
4409
4410    if (clcf->root.data) {
4411
4412        if ((clcf->alias != 0) == alias) {
4413            return "is duplicate";
4414        }
4415
4416        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4417                           "\"%V\" directive is duplicate, "
4418                           "\"%s\" directive was specified earlier",
4419                           &cmd->name, clcf->alias ? "alias" : "root");
4420
4421        return NGX_CONF_ERROR;
4422    }
4423
4424    if (clcf->named && alias) {
4425        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4426                           "the \"alias\" directive cannot be used "
4427                           "inside the named location");
4428
4429        return NGX_CONF_ERROR;
4430    }
4431
4432    value = cf->args->elts;
4433
4434    if (ngx_strstr(value[1].data, "$document_root")
4435        || ngx_strstr(value[1].data, "${document_root}"))
4436    {
4437        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4438                           "the $document_root variable cannot be used "
4439                           "in the \"%V\" directive",
4440                           &cmd->name);
4441
4442        return NGX_CONF_ERROR;
4443    }
4444
4445    if (ngx_strstr(value[1].data, "$realpath_root")
4446        || ngx_strstr(value[1].data, "${realpath_root}"))
4447    {
4448        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4449                           "the $realpath_root variable cannot be used "
4450                           "in the \"%V\" directive",
4451                           &cmd->name);
4452
4453        return NGX_CONF_ERROR;
4454    }
4455
4456    clcf->alias = alias ? clcf->name.len : 0;
4457    clcf->root = value[1];
4458
4459    if (!alias && clcf->root.len > 0
4460        && clcf->root.data[clcf->root.len - 1] == '/')
4461    {
4462        clcf->root.len--;
4463    }
4464
4465    if (clcf->root.data[0] != '$') {
4466        if (ngx_conf_full_name(cf->cycle, &clcf->root, 0) != NGX_OK) {
4467            return NGX_CONF_ERROR;
4468        }
4469    }
4470
4471    n = ngx_http_script_variables_count(&clcf->root);
4472
4473    ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
4474    sc.variables = n;
4475
4476#if (NGX_PCRE)
4477    if (alias && clcf->regex) {
4478        clcf->alias = NGX_MAX_SIZE_T_VALUE;
4479        n = 1;
4480    }
4481#endif
4482
4483    if (n) {
4484        sc.cf = cf;
4485        sc.source = &clcf->root;
4486        sc.lengths = &clcf->root_lengths;
4487        sc.values = &clcf->root_values;
4488        sc.complete_lengths = 1;
4489        sc.complete_values = 1;
4490
4491        if (ngx_http_script_compile(&sc) != NGX_OK) {
4492            return NGX_CONF_ERROR;
4493        }
4494    }
4495
4496    return NGX_CONF_OK;
4497}
4498
4499
4500static ngx_http_method_name_t  ngx_methods_names[] = {
4501    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
4502    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
4503    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
4504    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
4505    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
4506    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
4507    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
4508    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
4509    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
4510    { (u_char *) "PROPFIND",  (uint32_t) ~NGX_HTTP_PROPFIND },
4511    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
4512    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
4513    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
4514    { (u_char *) "PATCH",     (uint32_t) ~NGX_HTTP_PATCH },
4515    { NULL, 0 }
4516};
4517
4518
4519static char *
4520ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4521{
4522    ngx_http_core_loc_conf_t *pclcf = conf;
4523
4524    char                      *rv;
4525    void                      *mconf;
4526    ngx_str_t                 *value;
4527    ngx_uint_t                 i;
4528    ngx_conf_t                 save;
4529    ngx_http_module_t         *module;
4530    ngx_http_conf_ctx_t       *ctx, *pctx;
4531    ngx_http_method_name_t    *name;
4532    ngx_http_core_loc_conf_t  *clcf;
4533
4534    if (pclcf->limit_except) {
4535        return "is duplicate";
4536    }
4537
4538    pclcf->limit_except = 0xffffffff;
4539
4540    value = cf->args->elts;
4541
4542    for (i = 1; i < cf->args->nelts; i++) {
4543        for (name = ngx_methods_names; name->name; name++) {
4544
4545            if (ngx_strcasecmp(value[i].data, name->name) == 0) {
4546                pclcf->limit_except &= name->method;
4547                goto next;
4548            }
4549        }
4550
4551        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4552                           "invalid method \"%V\"", &value[i]);
4553        return NGX_CONF_ERROR;
4554
4555    next:
4556        continue;
4557    }
4558
4559    if (!(pclcf->limit_except & NGX_HTTP_GET)) {
4560        pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
4561    }
4562
4563    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
4564    if (ctx == NULL) {
4565        return NGX_CONF_ERROR;
4566    }
4567
4568    pctx = cf->ctx;
4569    ctx->main_conf = pctx->main_conf;
4570    ctx->srv_conf = pctx->srv_conf;
4571
4572    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
4573    if (ctx->loc_conf == NULL) {
4574        return NGX_CONF_ERROR;
4575    }
4576
4577    for (i = 0; cf->cycle->modules[i]; i++) {
4578        if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) {
4579            continue;
4580        }
4581
4582        module = cf->cycle->modules[i]->ctx;
4583
4584        if (module->create_loc_conf) {
4585
4586            mconf = module->create_loc_conf(cf);
4587            if (mconf == NULL) {
4588                return NGX_CONF_ERROR;
4589            }
4590
4591            ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf;
4592        }
4593    }
4594
4595
4596    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
4597    pclcf->limit_except_loc_conf = ctx->loc_conf;
4598    clcf->loc_conf = ctx->loc_conf;
4599    clcf->name = pclcf->name;
4600    clcf->noname = 1;
4601    clcf->lmt_excpt = 1;
4602
4603    if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
4604        return NGX_CONF_ERROR;
4605    }
4606
4607    save = *cf;
4608    cf->ctx = ctx;
4609    cf->cmd_type = NGX_HTTP_LMT_CONF;
4610
4611    rv = ngx_conf_parse(cf, NULL);
4612
4613    *cf = save;
4614
4615    return rv;
4616}
4617
4618
4619static char *
4620ngx_http_core_set_aio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4621{
4622    ngx_http_core_loc_conf_t *clcf = conf;
4623
4624    ngx_str_t  *value;
4625
4626    if (clcf->aio != NGX_CONF_UNSET) {
4627        return "is duplicate";
4628    }
4629
4630#if (NGX_THREADS)
4631    clcf->thread_pool = NULL;
4632    clcf->thread_pool_value = NULL;
4633#endif
4634
4635    value = cf->args->elts;
4636
4637    if (ngx_strcmp(value[1].data, "off") == 0) {
4638        clcf->aio = NGX_HTTP_AIO_OFF;
4639        return NGX_CONF_OK;
4640    }
4641
4642    if (ngx_strcmp(value[1].data, "on") == 0) {
4643#if (NGX_HAVE_FILE_AIO)
4644        clcf->aio = NGX_HTTP_AIO_ON;
4645        return NGX_CONF_OK;
4646#else
4647        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4648                           "\"aio on\" "
4649                           "is unsupported on this platform");
4650        return NGX_CONF_ERROR;
4651#endif
4652    }
4653
4654#if (NGX_HAVE_AIO_SENDFILE)
4655
4656    if (ngx_strcmp(value[1].data, "sendfile") == 0) {
4657        clcf->aio = NGX_HTTP_AIO_ON;
4658
4659        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4660                           "the \"sendfile\" parameter of "
4661                           "the \"aio\" directive is deprecated");
4662        return NGX_CONF_OK;
4663    }
4664
4665#endif
4666
4667    if (ngx_strncmp(value[1].data, "threads", 7) == 0
4668        && (value[1].len == 7 || value[1].data[7] == '='))
4669    {
4670#if (NGX_THREADS)
4671        ngx_str_t                          name;
4672        ngx_thread_pool_t                 *tp;
4673        ngx_http_complex_value_t           cv;
4674        ngx_http_compile_complex_value_t   ccv;
4675
4676        clcf->aio = NGX_HTTP_AIO_THREADS;
4677
4678        if (value[1].len >= 8) {
4679            name.len = value[1].len - 8;
4680            name.data = value[1].data + 8;
4681
4682            ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4683
4684            ccv.cf = cf;
4685            ccv.value = &name;
4686            ccv.complex_value = &cv;
4687
4688            if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4689                return NGX_CONF_ERROR;
4690            }
4691
4692            if (cv.lengths != NULL) {
4693                clcf->thread_pool_value = ngx_palloc(cf->pool,
4694                                    sizeof(ngx_http_complex_value_t));
4695                if (clcf->thread_pool_value == NULL) {
4696                    return NGX_CONF_ERROR;
4697                }
4698
4699                *clcf->thread_pool_value = cv;
4700
4701                return NGX_CONF_OK;
4702            }
4703
4704            tp = ngx_thread_pool_add(cf, &name);
4705
4706        } else {
4707            tp = ngx_thread_pool_add(cf, NULL);
4708        }
4709
4710        if (tp == NULL) {
4711            return NGX_CONF_ERROR;
4712        }
4713
4714        clcf->thread_pool = tp;
4715
4716        return NGX_CONF_OK;
4717#else
4718        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4719                           "\"aio threads\" "
4720                           "is unsupported on this platform");
4721        return NGX_CONF_ERROR;
4722#endif
4723    }
4724
4725    return "invalid value";
4726}
4727
4728
4729static char *
4730ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4731{
4732    ngx_http_core_loc_conf_t *clcf = conf;
4733
4734    ngx_str_t  *value;
4735
4736    if (clcf->directio != NGX_CONF_UNSET) {
4737        return "is duplicate";
4738    }
4739
4740    value = cf->args->elts;
4741
4742    if (ngx_strcmp(value[1].data, "off") == 0) {
4743        clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
4744        return NGX_CONF_OK;
4745    }
4746
4747    clcf->directio = ngx_parse_offset(&value[1]);
4748    if (clcf->directio == (off_t) NGX_ERROR) {
4749        return "invalid value";
4750    }
4751
4752    return NGX_CONF_OK;
4753}
4754
4755
4756static char *
4757ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4758{
4759    ngx_http_core_loc_conf_t *clcf = conf;
4760
4761    u_char                            *p;
4762    ngx_int_t                          overwrite;
4763    ngx_str_t                         *value, uri, args;
4764    ngx_uint_t                         i, n;
4765    ngx_http_err_page_t               *err;
4766    ngx_http_complex_value_t           cv;
4767    ngx_http_compile_complex_value_t   ccv;
4768
4769    if (clcf->error_pages == NULL) {
4770        clcf->error_pages = ngx_array_create(cf->pool, 4,
4771                                             sizeof(ngx_http_err_page_t));
4772        if (clcf->error_pages == NULL) {
4773            return NGX_CONF_ERROR;
4774        }
4775    }
4776
4777    value = cf->args->elts;
4778
4779    i = cf->args->nelts - 2;
4780
4781    if (value[i].data[0] == '=') {
4782        if (i == 1) {
4783            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4784                               "invalid value \"%V\"", &value[i]);
4785            return NGX_CONF_ERROR;
4786        }
4787
4788        if (value[i].len > 1) {
4789            overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
4790
4791            if (overwrite == NGX_ERROR) {
4792                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4793                                   "invalid value \"%V\"", &value[i]);
4794                return NGX_CONF_ERROR;
4795            }
4796
4797        } else {
4798            overwrite = 0;
4799        }
4800
4801        n = 2;
4802
4803    } else {
4804        overwrite = -1;
4805        n = 1;
4806    }
4807
4808    uri = value[cf->args->nelts - 1];
4809
4810    ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
4811
4812    ccv.cf = cf;
4813    ccv.value = &uri;
4814    ccv.complex_value = &cv;
4815
4816    if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
4817        return NGX_CONF_ERROR;
4818    }
4819
4820    ngx_str_null(&args);
4821
4822    if (cv.lengths == NULL && uri.len && uri.data[0] == '/') {
4823        p = (u_char *) ngx_strchr(uri.data, '?');
4824
4825        if (p) {
4826            cv.value.len = p - uri.data;
4827            cv.value.data = uri.data;
4828            p++;
4829            args.len = (uri.data + uri.len) - p;
4830            args.data = p;
4831        }
4832    }
4833
4834    for (i = 1; i < cf->args->nelts - n; i++) {
4835        err = ngx_array_push(clcf->error_pages);
4836        if (err == NULL) {
4837            return NGX_CONF_ERROR;
4838        }
4839
4840        err->status = ngx_atoi(value[i].data, value[i].len);
4841
4842        if (err->status == NGX_ERROR || err->status == 499) {
4843            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4844                               "invalid value \"%V\"", &value[i]);
4845            return NGX_CONF_ERROR;
4846        }
4847
4848        if (err->status < 300 || err->status > 599) {
4849            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4850                               "value \"%V\" must be between 300 and 599",
4851                               &value[i]);
4852            return NGX_CONF_ERROR;
4853        }
4854
4855        err->overwrite = overwrite;
4856
4857        if (overwrite == -1) {
4858            switch (err->status) {
4859                case NGX_HTTP_TO_HTTPS:
4860                case NGX_HTTPS_CERT_ERROR:
4861                case NGX_HTTPS_NO_CERT:
4862                    err->overwrite = NGX_HTTP_BAD_REQUEST;
4863            }
4864        }
4865
4866        err->value = cv;
4867        err->args = args;
4868    }
4869
4870    return NGX_CONF_OK;
4871}
4872
4873
4874static char *
4875ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4876{
4877    ngx_http_core_loc_conf_t *clcf = conf;
4878
4879    ngx_str_t                  *value;
4880    ngx_int_t                   code;
4881    ngx_uint_t                  i, n;
4882    ngx_http_try_file_t        *tf;
4883    ngx_http_script_compile_t   sc;
4884    ngx_http_core_main_conf_t  *cmcf;
4885
4886    if (clcf->try_files) {
4887        return "is duplicate";
4888    }
4889
4890    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
4891
4892    cmcf->try_files = 1;
4893
4894    tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
4895    if (tf == NULL) {
4896        return NGX_CONF_ERROR;
4897    }
4898
4899    clcf->try_files = tf;
4900
4901    value = cf->args->elts;
4902
4903    for (i = 0; i < cf->args->nelts - 1; i++) {
4904
4905        tf[i].name = value[i + 1];
4906
4907        if (tf[i].name.len > 0
4908            && tf[i].name.data[tf[i].name.len - 1] == '/'
4909            && i + 2 < cf->args->nelts)
4910        {
4911            tf[i].test_dir = 1;
4912            tf[i].name.len--;
4913            tf[i].name.data[tf[i].name.len] = '\0';
4914        }
4915
4916        n = ngx_http_script_variables_count(&tf[i].name);
4917
4918        if (n) {
4919            ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
4920
4921            sc.cf = cf;
4922            sc.source = &tf[i].name;
4923            sc.lengths = &tf[i].lengths;
4924            sc.values = &tf[i].values;
4925            sc.variables = n;
4926            sc.complete_lengths = 1;
4927            sc.complete_values = 1;
4928
4929            if (ngx_http_script_compile(&sc) != NGX_OK) {
4930                return NGX_CONF_ERROR;
4931            }
4932
4933        } else {
4934            /* add trailing '\0' to length */
4935            tf[i].name.len++;
4936        }
4937    }
4938
4939    if (tf[i - 1].name.data[0] == '=') {
4940
4941        code = ngx_atoi(tf[i - 1].name.data + 1, tf[i - 1].name.len - 2);
4942
4943        if (code == NGX_ERROR || code > 999) {
4944            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4945                               "invalid code \"%*s\"",
4946                               tf[i - 1].name.len - 1, tf[i - 1].name.data);
4947            return NGX_CONF_ERROR;
4948        }
4949
4950        tf[i].code = code;
4951    }
4952
4953    return NGX_CONF_OK;
4954}
4955
4956
4957static char *
4958ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4959{
4960    ngx_http_core_loc_conf_t *clcf = conf;
4961
4962    time_t       inactive;
4963    ngx_str_t   *value, s;
4964    ngx_int_t    max;
4965    ngx_uint_t   i;
4966
4967    if (clcf->open_file_cache != NGX_CONF_UNSET_PTR) {
4968        return "is duplicate";
4969    }
4970
4971    value = cf->args->elts;
4972
4973    max = 0;
4974    inactive = 60;
4975
4976    for (i = 1; i < cf->args->nelts; i++) {
4977
4978        if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
4979
4980            max = ngx_atoi(value[i].data + 4, value[i].len - 4);
4981            if (max <= 0) {
4982                goto failed;
4983            }
4984
4985            continue;
4986        }
4987
4988        if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
4989
4990            s.len = value[i].len - 9;
4991            s.data = value[i].data + 9;
4992
4993            inactive = ngx_parse_time(&s, 1);
4994            if (inactive == (time_t) NGX_ERROR) {
4995                goto failed;
4996            }
4997
4998            continue;
4999        }
5000
5001        if (ngx_strcmp(value[i].data, "off") == 0) {
5002
5003            clcf->open_file_cache = NULL;
5004
5005            continue;
5006        }
5007
5008    failed:
5009
5010        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5011                           "invalid \"open_file_cache\" parameter \"%V\"",
5012                           &value[i]);
5013        return NGX_CONF_ERROR;
5014    }
5015
5016    if (clcf->open_file_cache == NULL) {
5017        return NGX_CONF_OK;
5018    }
5019
5020    if (max == 0) {
5021        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5022                        "\"open_file_cache\" must have the \"max\" parameter");
5023        return NGX_CONF_ERROR;
5024    }
5025
5026    clcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
5027    if (clcf->open_file_cache) {
5028        return NGX_CONF_OK;
5029    }
5030
5031    return NGX_CONF_ERROR;
5032}
5033
5034
5035static char *
5036ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5037{
5038    ngx_http_core_loc_conf_t *clcf = conf;
5039
5040    return ngx_log_set_log(cf, &clcf->error_log);
5041}
5042
5043
5044static char *
5045ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5046{
5047    ngx_http_core_loc_conf_t *clcf = conf;
5048
5049    ngx_str_t  *value;
5050
5051    if (clcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
5052        return "is duplicate";
5053    }
5054
5055    value = cf->args->elts;
5056
5057    clcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
5058
5059    if (clcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
5060        return "invalid value";
5061    }
5062
5063    if (cf->args->nelts == 2) {
5064        return NGX_CONF_OK;
5065    }
5066
5067    clcf->keepalive_header = ngx_parse_time(&value[2], 1);
5068
5069    if (clcf->keepalive_header == (time_t) NGX_ERROR) {
5070        return "invalid value";
5071    }
5072
5073    return NGX_CONF_OK;
5074}
5075
5076
5077static char *
5078ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5079{
5080    ngx_http_core_loc_conf_t *clcf = conf;
5081
5082    if (clcf->internal != NGX_CONF_UNSET) {
5083        return "is duplicate";
5084    }
5085
5086    clcf->internal = 1;
5087
5088    return NGX_CONF_OK;
5089}
5090
5091
5092static char *
5093ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5094{
5095    ngx_http_core_loc_conf_t  *clcf = conf;
5096
5097    ngx_str_t  *value;
5098
5099    if (clcf->resolver) {
5100        return "is duplicate";
5101    }
5102
5103    value = cf->args->elts;
5104
5105    clcf->resolver = ngx_resolver_create(cf, &value[1], cf->args->nelts - 1);
5106    if (clcf->resolver == NULL) {
5107        return NGX_CONF_ERROR;
5108    }
5109
5110    return NGX_CONF_OK;
5111}
5112
5113
5114#if (NGX_HTTP_GZIP)
5115
5116static char *
5117ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5118{
5119    ngx_http_core_loc_conf_t  *clcf = conf;
5120
5121#if (NGX_PCRE)
5122
5123    ngx_str_t            *value;
5124    ngx_uint_t            i;
5125    ngx_regex_elt_t      *re;
5126    ngx_regex_compile_t   rc;
5127    u_char                errstr[NGX_MAX_CONF_ERRSTR];
5128
5129    if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
5130        clcf->gzip_disable = ngx_array_create(cf->pool, 2,
5131                                              sizeof(ngx_regex_elt_t));
5132        if (clcf->gzip_disable == NULL) {
5133            return NGX_CONF_ERROR;
5134        }
5135    }
5136
5137    value = cf->args->elts;
5138
5139    ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
5140
5141    rc.pool = cf->pool;
5142    rc.err.len = NGX_MAX_CONF_ERRSTR;
5143    rc.err.data = errstr;
5144
5145    for (i = 1; i < cf->args->nelts; i++) {
5146
5147        if (ngx_strcmp(value[i].data, "msie6") == 0) {
5148            clcf->gzip_disable_msie6 = 1;
5149            continue;
5150        }
5151
5152#if (NGX_HTTP_DEGRADATION)
5153
5154        if (ngx_strcmp(value[i].data, "degradation") == 0) {
5155            clcf->gzip_disable_degradation = 1;
5156            continue;
5157        }
5158
5159#endif
5160
5161        re = ngx_array_push(clcf->gzip_disable);
5162        if (re == NULL) {
5163            return NGX_CONF_ERROR;
5164        }
5165
5166        rc.pattern = value[i];
5167        rc.options = NGX_REGEX_CASELESS;
5168
5169        if (ngx_regex_compile(&rc) != NGX_OK) {
5170            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
5171            return NGX_CONF_ERROR;
5172        }
5173
5174        re->regex = rc.regex;
5175        re->name = value[i].data;
5176    }
5177
5178    return NGX_CONF_OK;
5179
5180#else
5181    ngx_str_t   *value;
5182    ngx_uint_t   i;
5183
5184    value = cf->args->elts;
5185
5186    for (i = 1; i < cf->args->nelts; i++) {
5187        if (ngx_strcmp(value[i].data, "msie6") == 0) {
5188            clcf->gzip_disable_msie6 = 1;
5189            continue;
5190        }
5191
5192#if (NGX_HTTP_DEGRADATION)
5193
5194        if (ngx_strcmp(value[i].data, "degradation") == 0) {
5195            clcf->gzip_disable_degradation = 1;
5196            continue;
5197        }
5198
5199#endif
5200
5201        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5202                           "without PCRE library \"gzip_disable\" supports "
5203                           "builtin \"msie6\" and \"degradation\" mask only");
5204
5205        return NGX_CONF_ERROR;
5206    }
5207
5208    return NGX_CONF_OK;
5209
5210#endif
5211}
5212
5213#endif
5214
5215
5216#if (NGX_HAVE_OPENAT)
5217
5218static char *
5219ngx_http_disable_symlinks(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
5220{
5221    ngx_http_core_loc_conf_t *clcf = conf;
5222
5223    ngx_str_t                         *value;
5224    ngx_uint_t                         i;
5225    ngx_http_compile_complex_value_t   ccv;
5226
5227    if (clcf->disable_symlinks != NGX_CONF_UNSET_UINT) {
5228        return "is duplicate";
5229    }
5230
5231    value = cf->args->elts;
5232
5233    for (i = 1; i < cf->args->nelts; i++) {
5234
5235        if (ngx_strcmp(value[i].data, "off") == 0) {
5236            clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_OFF;
5237            continue;
5238        }
5239
5240        if (ngx_strcmp(value[i].data, "if_not_owner") == 0) {
5241            clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_NOTOWNER;
5242            continue;
5243        }
5244
5245        if (ngx_strcmp(value[i].data, "on") == 0) {
5246            clcf->disable_symlinks = NGX_DISABLE_SYMLINKS_ON;
5247            continue;
5248        }
5249
5250        if (ngx_strncmp(value[i].data, "from=", 5) == 0) {
5251            value[i].len -= 5;
5252            value[i].data += 5;
5253
5254            ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
5255
5256            ccv.cf = cf;
5257            ccv.value = &value[i];
5258            ccv.complex_value = ngx_palloc(cf->pool,
5259                                           sizeof(ngx_http_complex_value_t));
5260            if (ccv.complex_value == NULL) {
5261                return NGX_CONF_ERROR;
5262            }
5263
5264            if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
5265                return NGX_CONF_ERROR;
5266            }
5267
5268            clcf->disable_symlinks_from = ccv.complex_value;
5269
5270            continue;
5271        }
5272
5273        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5274                           "invalid parameter \"%V\"", &value[i]);
5275        return NGX_CONF_ERROR;
5276    }
5277
5278    if (clcf->disable_symlinks == NGX_CONF_UNSET_UINT) {
5279        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5280                           "\"%V\" must have \"off\", \"on\" "
5281                           "or \"if_not_owner\" parameter",
5282                           &cmd->name);
5283        return NGX_CONF_ERROR;
5284    }
5285
5286    if (cf->args->nelts == 2) {
5287        clcf->disable_symlinks_from = NULL;
5288        return NGX_CONF_OK;
5289    }
5290
5291    if (clcf->disable_symlinks_from == NGX_CONF_UNSET_PTR) {
5292        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5293                           "duplicate parameters \"%V %V\"",
5294                           &value[1], &value[2]);
5295        return NGX_CONF_ERROR;
5296    }
5297
5298    if (clcf->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
5299        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5300                           "\"from=\" cannot be used with \"off\" parameter");
5301        return NGX_CONF_ERROR;
5302    }
5303
5304    return NGX_CONF_OK;
5305}
5306
5307#endif
5308
5309
5310static char *
5311ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
5312{
5313#if (NGX_FREEBSD)
5314    ssize_t *np = data;
5315
5316    if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
5317        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5318                           "\"send_lowat\" must be less than %d "
5319                           "(sysctl net.inet.tcp.sendspace)",
5320                           ngx_freebsd_net_inet_tcp_sendspace);
5321
5322        return NGX_CONF_ERROR;
5323    }
5324
5325#elif !(NGX_HAVE_SO_SNDLOWAT)
5326    ssize_t *np = data;
5327
5328    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
5329                       "\"send_lowat\" is not supported, ignored");
5330
5331    *np = 0;
5332
5333#endif
5334
5335    return NGX_CONF_OK;
5336}
5337
5338
5339static char *
5340ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
5341{
5342    size_t *sp = data;
5343
5344    if (*sp < NGX_MIN_POOL_SIZE) {
5345        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5346                           "the pool size must be no less than %uz",
5347                           NGX_MIN_POOL_SIZE);
5348        return NGX_CONF_ERROR;
5349    }
5350
5351    if (*sp % NGX_POOL_ALIGNMENT) {
5352        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
5353                           "the pool size must be a multiple of %uz",
5354                           NGX_POOL_ALIGNMENT);
5355        return NGX_CONF_ERROR;
5356    }
5357
5358    return NGX_CONF_OK;
5359}
5360