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