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