comparison src/http/ngx_http_core_module.c @ 0:f0b350454894 NGINX_0_1_0

nginx 0.1.0 *) The first public version.
author Igor Sysoev <http://sysoev.ru>
date Mon, 04 Oct 2004 00:00:00 +0400
parents
children cc9f381affaa
comparison
equal deleted inserted replaced
-1:000000000000 0:f0b350454894
1
2 /*
3 * Copyright (C) Igor Sysoev
4 */
5
6
7 #include <ngx_config.h>
8 #include <ngx_core.h>
9 #include <ngx_event.h>
10 #include <ngx_http.h>
11 #include <nginx.h>
12
13 /* STUB */
14 #define NGX_HTTP_LOCATION_EXACT 1
15 #define NGX_HTTP_LOCATION_AUTO_REDIRECT 2
16 #define NGX_HTTP_LOCATION_REGEX 3
17
18
19 static void ngx_http_phase_event_handler(ngx_event_t *rev);
20 static void ngx_http_run_phases(ngx_http_request_t *r);
21 static ngx_int_t ngx_http_find_location(ngx_http_request_t *r,
22 ngx_array_t *locations, size_t len);
23
24 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
25 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
26 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
27 static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf,
28 void *parent, void *child);
29 static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf);
30 static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
31 void *parent, void *child);
32
33 static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy);
34 static int ngx_cmp_locations(const void *first, const void *second);
35 static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd,
36 void *dummy);
37 static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
38 static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
39 static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
40 static char *ngx_set_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
41 void *conf);
42 static char *ngx_set_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
43 static char *ngx_set_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
44 static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
45 static char *ngx_set_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
46
47 static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data);
48
49 static ngx_conf_post_t ngx_http_lowat_post = { ngx_http_lowat_check } ;
50
51
52 static ngx_conf_enum_t ngx_http_restrict_host_names[] = {
53 { ngx_string("off"), NGX_HTTP_RESTRICT_HOST_OFF },
54 { ngx_string("on"), NGX_HTTP_RESTRICT_HOST_ON },
55 { ngx_string("close"), NGX_HTTP_RESTRICT_HOST_CLOSE },
56 { ngx_null_string, 0 }
57 };
58
59
60 static ngx_command_t ngx_http_core_commands[] = {
61
62 { ngx_string("server"),
63 NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
64 ngx_server_block,
65 0,
66 0,
67 NULL },
68
69 { ngx_string("connection_pool_size"),
70 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
71 ngx_conf_set_size_slot,
72 NGX_HTTP_SRV_CONF_OFFSET,
73 offsetof(ngx_http_core_srv_conf_t, connection_pool_size),
74 NULL },
75
76 { ngx_string("post_accept_timeout"),
77 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
78 ngx_conf_set_msec_slot,
79 NGX_HTTP_SRV_CONF_OFFSET,
80 offsetof(ngx_http_core_srv_conf_t, post_accept_timeout),
81 NULL },
82
83 { ngx_string("request_pool_size"),
84 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
85 ngx_conf_set_size_slot,
86 NGX_HTTP_SRV_CONF_OFFSET,
87 offsetof(ngx_http_core_srv_conf_t, request_pool_size),
88 NULL },
89
90 { ngx_string("client_header_timeout"),
91 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
92 ngx_conf_set_msec_slot,
93 NGX_HTTP_SRV_CONF_OFFSET,
94 offsetof(ngx_http_core_srv_conf_t, client_header_timeout),
95 NULL },
96
97 { ngx_string("client_header_buffer_size"),
98 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
99 ngx_conf_set_size_slot,
100 NGX_HTTP_SRV_CONF_OFFSET,
101 offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size),
102 NULL },
103
104 { ngx_string("large_client_header_buffers"),
105 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
106 ngx_conf_set_bufs_slot,
107 NGX_HTTP_SRV_CONF_OFFSET,
108 offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
109 NULL },
110
111 { ngx_string("restrict_host_names"),
112 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
113 ngx_conf_set_enum_slot,
114 NGX_HTTP_SRV_CONF_OFFSET,
115 offsetof(ngx_http_core_srv_conf_t, restrict_host_names),
116 &ngx_http_restrict_host_names },
117
118 { ngx_string("location"),
119 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
120 ngx_location_block,
121 NGX_HTTP_SRV_CONF_OFFSET,
122 0,
123 NULL },
124
125 { ngx_string("listen"),
126 #if 0
127 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
128 #else
129 NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
130 #endif
131 ngx_set_listen,
132 NGX_HTTP_SRV_CONF_OFFSET,
133 0,
134 NULL },
135
136 { ngx_string("server_name"),
137 NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
138 ngx_set_server_name,
139 NGX_HTTP_SRV_CONF_OFFSET,
140 0,
141 NULL },
142
143 { ngx_string("types"),
144 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
145 |NGX_CONF_BLOCK|NGX_CONF_NOARGS,
146 ngx_types_block,
147 NGX_HTTP_LOC_CONF_OFFSET,
148 0,
149 NULL },
150
151 { ngx_string("default_type"),
152 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
153 ngx_conf_set_str_slot,
154 NGX_HTTP_LOC_CONF_OFFSET,
155 offsetof(ngx_http_core_loc_conf_t, default_type),
156 NULL },
157
158 { ngx_string("root"),
159 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
160 ngx_set_root,
161 NGX_HTTP_LOC_CONF_OFFSET,
162 0,
163 NULL },
164
165 { ngx_string("alias"),
166 NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
167 ngx_set_root,
168 NGX_HTTP_LOC_CONF_OFFSET,
169 0,
170 NULL },
171
172 { ngx_string("client_max_body_size"),
173 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
174 ngx_conf_set_size_slot,
175 NGX_HTTP_LOC_CONF_OFFSET,
176 offsetof(ngx_http_core_loc_conf_t, client_max_body_size),
177 NULL },
178
179 { ngx_string("client_body_buffer_size"),
180 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
181 ngx_conf_set_size_slot,
182 NGX_HTTP_LOC_CONF_OFFSET,
183 offsetof(ngx_http_core_loc_conf_t, client_body_buffer_size),
184 NULL },
185
186 { ngx_string("client_body_timeout"),
187 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
188 ngx_conf_set_msec_slot,
189 NGX_HTTP_LOC_CONF_OFFSET,
190 offsetof(ngx_http_core_loc_conf_t, client_body_timeout),
191 NULL },
192
193 { ngx_string("sendfile"),
194 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
195 ngx_conf_set_flag_slot,
196 NGX_HTTP_LOC_CONF_OFFSET,
197 offsetof(ngx_http_core_loc_conf_t, sendfile),
198 NULL },
199
200 { ngx_string("tcp_nopush"),
201 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
202 ngx_conf_set_flag_slot,
203 NGX_HTTP_LOC_CONF_OFFSET,
204 offsetof(ngx_http_core_loc_conf_t, tcp_nopush),
205 NULL },
206
207 { ngx_string("send_timeout"),
208 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
209 ngx_conf_set_msec_slot,
210 NGX_HTTP_LOC_CONF_OFFSET,
211 offsetof(ngx_http_core_loc_conf_t, send_timeout),
212 NULL },
213
214 { ngx_string("send_lowat"),
215 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
216 ngx_conf_set_size_slot,
217 NGX_HTTP_LOC_CONF_OFFSET,
218 offsetof(ngx_http_core_loc_conf_t, send_lowat),
219 &ngx_http_lowat_post },
220
221 { ngx_string("postpone_output"),
222 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
223 ngx_conf_set_size_slot,
224 NGX_HTTP_LOC_CONF_OFFSET,
225 offsetof(ngx_http_core_loc_conf_t, postpone_output),
226 NULL },
227
228 { ngx_string("limit_rate"),
229 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
230 ngx_conf_set_size_slot,
231 NGX_HTTP_LOC_CONF_OFFSET,
232 offsetof(ngx_http_core_loc_conf_t, limit_rate),
233 NULL },
234
235 { ngx_string("keepalive_timeout"),
236 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
237 ngx_set_keepalive,
238 NGX_HTTP_LOC_CONF_OFFSET,
239 0,
240 NULL },
241
242 { ngx_string("lingering_time"),
243 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
244 ngx_conf_set_msec_slot,
245 NGX_HTTP_LOC_CONF_OFFSET,
246 offsetof(ngx_http_core_loc_conf_t, lingering_time),
247 NULL },
248
249 { ngx_string("lingering_timeout"),
250 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
251 ngx_conf_set_msec_slot,
252 NGX_HTTP_LOC_CONF_OFFSET,
253 offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
254 NULL },
255
256 { ngx_string("reset_timedout_connection"),
257 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
258 ngx_conf_set_flag_slot,
259 NGX_HTTP_LOC_CONF_OFFSET,
260 offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
261 NULL },
262
263 { ngx_string("msie_padding"),
264 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
265 ngx_conf_set_flag_slot,
266 NGX_HTTP_LOC_CONF_OFFSET,
267 offsetof(ngx_http_core_loc_conf_t, msie_padding),
268 NULL },
269
270 { ngx_string("error_page"),
271 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
272 ngx_set_error_page,
273 NGX_HTTP_LOC_CONF_OFFSET,
274 0,
275 NULL },
276
277 { ngx_string("error_log"),
278 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
279 ngx_set_error_log,
280 NGX_HTTP_LOC_CONF_OFFSET,
281 0,
282 NULL },
283
284 #if (NGX_HTTP_CACHE)
285
286 { ngx_string("open_file_cache"),
287 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE4,
288 ngx_http_set_cache_slot,
289 NGX_HTTP_LOC_CONF_OFFSET,
290 offsetof(ngx_http_core_loc_conf_t, open_files),
291 NULL },
292
293 #endif
294
295 ngx_null_command
296 };
297
298
299 ngx_http_module_t ngx_http_core_module_ctx = {
300 NULL, /* pre conf */
301
302 ngx_http_core_create_main_conf, /* create main configuration */
303 ngx_http_core_init_main_conf, /* init main configuration */
304
305 ngx_http_core_create_srv_conf, /* create server configuration */
306 ngx_http_core_merge_srv_conf, /* merge server configuration */
307
308 ngx_http_core_create_loc_conf, /* create location configuration */
309 ngx_http_core_merge_loc_conf /* merge location configuration */
310 };
311
312
313 ngx_module_t ngx_http_core_module = {
314 NGX_MODULE,
315 &ngx_http_core_module_ctx, /* module context */
316 ngx_http_core_commands, /* module directives */
317 NGX_HTTP_MODULE, /* module type */
318 NULL, /* init module */
319 NULL /* init process */
320 };
321
322
323 void ngx_http_handler(ngx_http_request_t *r)
324 {
325 ngx_http_log_ctx_t *lcx;
326
327 r->connection->unexpected_eof = 0;
328
329 lcx = r->connection->log->data;
330 lcx->action = NULL;
331
332 switch (r->headers_in.connection_type) {
333 case 0:
334 if (r->http_version > NGX_HTTP_VERSION_10) {
335 r->keepalive = 1;
336 } else {
337 r->keepalive = 0;
338 }
339 break;
340
341 case NGX_HTTP_CONNECTION_CLOSE:
342 r->keepalive = 0;
343 break;
344
345 case NGX_HTTP_CONNECTION_KEEP_ALIVE:
346 r->keepalive = 1;
347 break;
348 }
349
350 if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
351
352 /*
353 * MSIE may wait for some time if the response for the POST request
354 * is sent over the keepalive connection
355 */
356
357 r->keepalive = 0;
358 }
359
360 #if 0
361 /* TEST STUB */ r->http_version = NGX_HTTP_VERSION_10;
362 /* TEST STUB */ r->keepalive = 0;
363 #endif
364
365 if (r->headers_in.content_length_n > 0) {
366 r->lingering_close = 1;
367
368 } else {
369 r->lingering_close = 0;
370 }
371
372 #if 0
373 /* TEST STUB */ r->lingering_close = 1;
374 #endif
375
376 r->connection->write->event_handler = ngx_http_phase_event_handler;
377
378 ngx_http_run_phases(r);
379
380 return;
381 }
382
383
384 static void ngx_http_phase_event_handler(ngx_event_t *ev)
385 {
386 ngx_connection_t *c;
387 ngx_http_request_t *r;
388
389 c = ev->data;
390 r = c->data;
391
392 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0, "phase event handler");
393
394 ngx_http_run_phases(r);
395
396 return;
397 }
398
399
400 static void ngx_http_run_phases(ngx_http_request_t *r)
401 {
402 char *path;
403 ngx_int_t rc;
404 ngx_http_handler_pt *h;
405 ngx_http_core_loc_conf_t *clcf;
406 ngx_http_core_main_conf_t *cmcf;
407
408 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
409
410 for (/* void */; r->phase < NGX_HTTP_LAST_PHASE; r->phase++) {
411
412 if (r->phase == NGX_HTTP_CONTENT_PHASE && r->content_handler) {
413 r->connection->write->event_handler = ngx_http_empty_handler;
414 rc = r->content_handler(r);
415 ngx_http_finalize_request(r, rc);
416 return;
417 }
418
419 h = cmcf->phases[r->phase].handlers.elts;
420 for (r->phase_handler = cmcf->phases[r->phase].handlers.nelts - 1;
421 r->phase_handler >= 0;
422 r->phase_handler--)
423 {
424 rc = h[r->phase_handler](r);
425
426 if (rc == NGX_DONE) {
427
428 /*
429 * we should never use r here because
430 * it could point to already freed data
431 */
432
433 return;
434 }
435
436 if (rc == NGX_DECLINED) {
437 continue;
438 }
439
440 if (rc >= NGX_HTTP_SPECIAL_RESPONSE || rc == NGX_ERROR) {
441 ngx_http_finalize_request(r, rc);
442 return;
443 }
444
445 if (r->phase == NGX_HTTP_CONTENT_PHASE) {
446 ngx_http_finalize_request(r, rc);
447 return;
448 }
449
450 if (rc == NGX_AGAIN) {
451 return;
452 }
453
454 if (rc == NGX_OK && cmcf->phases[r->phase].type == NGX_OK) {
455 break;
456 }
457 }
458 }
459
460
461 if (r->uri.data[r->uri.len - 1] == '/') {
462
463 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
464
465 if (!(path = ngx_palloc(r->pool, clcf->root.len + r->uri.len))) {
466 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
467 return;
468 }
469
470 ngx_cpystrn(ngx_cpymem(path, clcf->root.data, clcf->root.len),
471 r->uri.data, r->uri.len + 1);
472
473 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
474 "directory index of \"%s\" is forbidden", path);
475
476 ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
477 return;
478 }
479
480 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
481
482 ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
483 return;
484 }
485
486
487 ngx_int_t ngx_http_find_location_config(ngx_http_request_t *r)
488 {
489 ngx_int_t rc;
490 ngx_http_core_loc_conf_t *clcf;
491 ngx_http_core_srv_conf_t *cscf;
492
493 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
494
495 rc = ngx_http_find_location(r, &cscf->locations, 0);
496
497 if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) {
498 return rc;
499 }
500
501 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
502
503 r->connection->log->file = clcf->err_log->file;
504 if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
505 r->connection->log->log_level = clcf->err_log->log_level;
506 }
507
508 if (!(ngx_io.flags & NGX_IO_SENDFILE) || !clcf->sendfile) {
509 r->sendfile = 0;
510
511 } else {
512 r->sendfile = 1;
513 }
514
515 if (!clcf->tcp_nopush) {
516 /* disable TCP_NOPUSH/TCP_CORK use */
517 r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
518 }
519
520
521 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
522 "http cl: " SIZE_T_FMT " max: " SIZE_T_FMT,
523 r->headers_in.content_length_n,
524 clcf->client_max_body_size);
525
526 if (r->headers_in.content_length_n != -1
527 && clcf->client_max_body_size
528 && clcf->client_max_body_size < (size_t) r->headers_in.content_length_n)
529 {
530 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
531 "client intented to send too large body: "
532 SIZE_T_FMT " bytes",
533 r->headers_in.content_length_n);
534
535 return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE;
536 }
537
538
539 if (rc == NGX_HTTP_LOCATION_AUTO_REDIRECT) {
540 r->headers_out.location = ngx_list_push(&r->headers_out.headers);
541 if (r->headers_out.location == NULL) {
542 return NGX_HTTP_INTERNAL_SERVER_ERROR;
543 }
544
545 r->headers_out.location->value = clcf->name;
546
547 return NGX_HTTP_MOVED_PERMANENTLY;
548 }
549
550 if (clcf->handler) {
551 r->content_handler = clcf->handler;
552 }
553
554 return NGX_OK;
555 }
556
557
558 static ngx_int_t ngx_http_find_location(ngx_http_request_t *r,
559 ngx_array_t *locations, size_t len)
560 {
561 ngx_int_t n, rc;
562 ngx_uint_t i, found;
563 ngx_http_core_loc_conf_t *clcf, **clcfp;
564
565 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "find location");
566
567 found = 0;
568
569 clcfp = locations->elts;
570 for (i = 0; i < locations->nelts; i++) {
571
572 #if (HAVE_PCRE)
573 if (clcfp[i]->regex) {
574 break;
575 }
576 #endif
577
578 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
579 "find location: %s\"%s\"",
580 clcfp[i]->exact_match ? "= " : "",
581 clcfp[i]->name.data);
582
583 if (clcfp[i]->auto_redirect
584 && r->uri.len == clcfp[i]->name.len - 1
585 && ngx_strncmp(r->uri.data, clcfp[i]->name.data,
586 clcfp[i]->name.len - 1) == 0)
587 {
588 /* the locations are lexicographically sorted */
589
590 r->loc_conf = clcfp[i]->loc_conf;
591
592 return NGX_HTTP_LOCATION_AUTO_REDIRECT;
593 }
594
595 if (r->uri.len < clcfp[i]->name.len) {
596 continue;
597 }
598
599 n = ngx_strncmp(r->uri.data, clcfp[i]->name.data, clcfp[i]->name.len);
600
601 if (n < 0) {
602 /* the locations are lexicographically sorted */
603 break;
604 }
605
606 if (n == 0) {
607 if (clcfp[i]->exact_match && r->uri.len == clcfp[i]->name.len) {
608 r->loc_conf = clcfp[i]->loc_conf;
609 return NGX_HTTP_LOCATION_EXACT;
610 }
611
612 if (len > clcfp[i]->name.len) {
613 /* the previous match is longer */
614 break;
615 }
616
617 r->loc_conf = clcfp[i]->loc_conf;
618 found = 1;
619 }
620 }
621
622 if (found) {
623 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
624
625 if (clcf->locations.nelts) {
626 rc = ngx_http_find_location(r, &clcf->locations, len);
627
628 if (rc != NGX_OK) {
629 return rc;
630 }
631 }
632 }
633
634 #if (HAVE_PCRE)
635
636 /* regex matches */
637
638 for (/* void */; i < locations->nelts; i++) {
639
640 if (!clcfp[i]->regex) {
641 continue;
642 }
643
644 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
645 "find location: ~ \"%s\"",
646 clcfp[i]->name.data);
647
648 n = ngx_regex_exec(clcfp[i]->regex, &r->uri, NULL, 0);
649
650 if (n == NGX_DECLINED) {
651 continue;
652 }
653
654 if (n < 0) {
655 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
656 ngx_regex_exec_n
657 " failed: %d on \"%s\" using \"%s\"",
658 n, r->uri.data, clcfp[i]->name.data);
659 return NGX_HTTP_INTERNAL_SERVER_ERROR;
660 }
661
662 /* match */
663
664 r->loc_conf = clcfp[i]->loc_conf;
665
666 return NGX_HTTP_LOCATION_REGEX;
667 }
668
669 #endif /* HAVE_PCRE */
670
671 return NGX_OK;
672 }
673
674
675 ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r)
676 {
677 uint32_t key;
678 ngx_uint_t i;
679 ngx_http_type_t *type;
680 ngx_http_core_loc_conf_t *clcf;
681
682 r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
683 if (r->headers_out.content_type == NULL) {
684 return NGX_HTTP_INTERNAL_SERVER_ERROR;
685 }
686
687 r->headers_out.content_type->key.len = 0;
688 r->headers_out.content_type->key.data = NULL;
689 r->headers_out.content_type->value.len = 0;
690 r->headers_out.content_type->value.data = NULL;
691
692 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
693
694 if (r->exten.len) {
695 #if 0
696 key = ngx_crc(r->exten.data, r->exten.key);
697 #endif
698 ngx_http_types_hash_key(key, r->exten);
699
700 type = clcf->types[key].elts;
701 for (i = 0; i < clcf->types[key].nelts; i++) {
702 if (r->exten.len != type[i].exten.len) {
703 continue;
704 }
705
706 if (ngx_memcmp(r->exten.data, type[i].exten.data, r->exten.len)
707 == 0)
708 {
709 r->headers_out.content_type->value = type[i].type;
710 break;
711 }
712 }
713 }
714
715 if (r->headers_out.content_type->value.len == 0) {
716 r->headers_out.content_type->value = clcf->default_type;
717 }
718
719 return NGX_OK;
720 }
721
722
723 ngx_int_t ngx_http_send_header(ngx_http_request_t *r)
724 {
725 if (r->main) {
726 return NGX_OK;
727 }
728
729 if (r->err_ctx) {
730 r->headers_out.status = r->err_status;
731 r->headers_out.status_line.len = 0;
732 }
733
734 return (*ngx_http_top_header_filter)(r);
735 }
736
737
738 ngx_int_t ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
739 {
740 ngx_int_t rc;
741
742 if (r->connection->write->error) {
743 return NGX_ERROR;
744 }
745
746 rc = ngx_http_top_body_filter(r, in);
747
748 if (rc == NGX_ERROR) {
749
750 /* NGX_ERROR could be returned by any filter */
751
752 r->connection->write->error = 1;
753 }
754
755 return rc;
756 }
757
758
759 int ngx_http_redirect(ngx_http_request_t *r, int redirect)
760 {
761 /* STUB */
762
763 /* log request */
764
765 ngx_http_close_request(r, 0);
766 return NGX_OK;
767 }
768
769
770 ngx_int_t ngx_http_set_exten(ngx_http_request_t *r)
771 {
772 ngx_int_t i;
773
774 r->exten.len = 0;
775 r->exten.data = NULL;
776
777 for (i = r->uri.len - 1; i > 1; i--) {
778 if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
779 r->exten.len = r->uri.len - i - 1;
780
781 if (r->exten.len > 0) {
782 if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
783 return NGX_ERROR;
784 }
785
786 ngx_cpystrn(r->exten.data, &r->uri.data[i + 1],
787 r->exten.len + 1);
788 }
789
790 break;
791
792 } else if (r->uri.data[i] == '/') {
793 break;
794 }
795 }
796
797 return NGX_OK;
798 }
799
800
801 ngx_int_t ngx_http_internal_redirect(ngx_http_request_t *r,
802 ngx_str_t *uri, ngx_str_t *args)
803 {
804 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
805 "internal redirect: \"%s\"", uri->data);
806
807 r->uri.len = uri->len;
808 r->uri.data = uri->data;
809
810 if (args) {
811 r->args.len = args->len;
812 r->args.data = args->data;
813 }
814
815 if (ngx_http_set_exten(r) != NGX_OK) {
816 return NGX_HTTP_INTERNAL_SERVER_ERROR;
817 }
818
819 if (r->err_ctx) {
820
821 /* allocate the new modules contexts */
822
823 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
824 if (r->ctx == NULL) {
825 return NGX_HTTP_INTERNAL_SERVER_ERROR;
826 }
827
828 } else {
829
830 /* clear the modules contexts */
831
832 ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
833 }
834
835 r->phase = 0;
836 r->phase_handler = 0;
837
838 ngx_http_handler(r);
839
840 return NGX_DONE;
841 }
842
843
844 #if 0 /* STUB: test the delay http handler */
845
846 int ngx_http_delay_handler(ngx_http_request_t *r)
847 {
848 static int on;
849
850 if (on++ == 0) {
851 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
852 "http set delay");
853 ngx_add_timer(r->connection->write, 10000);
854 return NGX_AGAIN;
855 }
856
857 r->connection->write->timedout = 0;
858 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
859 "http reset delay");
860 return NGX_DECLINED;
861 }
862
863 #endif
864
865
866 #if 0
867
868 static ngx_int_t ngx_http_core_init_process(ngx_cycle_t *cycle)
869 {
870 ngx_uint_t i;
871 ngx_http_core_srv_conf_t **cscfp;
872 ngx_http_core_main_conf_t *cmcf;
873
874 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
875
876 #if 0
877 ngx_http_core_init_module:
878
879 ngx_http_handler_pt *h;
880
881 ngx_test_null(h, ngx_push_array(
882 &cmcf->phases[NGX_HTTP_TRANSLATE_PHASE].handlers),
883 NGX_ERROR);
884 *h = ngx_http_delay_handler;
885 #endif
886
887 cscfp = cmcf->servers.elts;
888
889 for (i = 0; i < cmcf->servers.nelts; i++) {
890 if (cscfp[i]->recv == NULL) {
891 cscfp[i]->recv = ngx_io.recv;
892 cscfp[i]->send_chain = ngx_io.send_chain;
893 }
894 }
895
896 return NGX_OK;
897 }
898
899 #endif
900
901
902 static char *ngx_server_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
903 {
904 int m;
905 char *rv;
906 ngx_http_module_t *module;
907 ngx_conf_t pvcf;
908 ngx_http_conf_ctx_t *ctx, *http_ctx;
909 ngx_http_core_main_conf_t *cmcf;
910 ngx_http_core_srv_conf_t *cscf, **cscfp;
911
912 ngx_test_null(ctx,
913 ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
914 NGX_CONF_ERROR);
915
916 http_ctx = cf->ctx;
917 ctx->main_conf = http_ctx->main_conf;
918
919 /* the server{}'s srv_conf */
920
921 ngx_test_null(ctx->srv_conf,
922 ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
923 NGX_CONF_ERROR);
924
925 /* the server{}'s loc_conf */
926
927 ngx_test_null(ctx->loc_conf,
928 ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
929 NGX_CONF_ERROR);
930
931 for (m = 0; ngx_modules[m]; m++) {
932 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
933 continue;
934 }
935
936 module = ngx_modules[m]->ctx;
937
938 if (module->create_srv_conf) {
939 ngx_test_null(ctx->srv_conf[ngx_modules[m]->ctx_index],
940 module->create_srv_conf(cf),
941 NGX_CONF_ERROR);
942 }
943
944 if (module->create_loc_conf) {
945 ngx_test_null(ctx->loc_conf[ngx_modules[m]->ctx_index],
946 module->create_loc_conf(cf),
947 NGX_CONF_ERROR);
948 }
949 }
950
951 /* create links of the srv_conf's */
952
953 cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
954 cscf->ctx = ctx;
955
956 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
957 ngx_test_null(cscfp, ngx_push_array(&cmcf->servers), NGX_CONF_ERROR);
958 *cscfp = cscf;
959
960 /* parse inside server{} */
961
962 pvcf = *cf;
963 cf->ctx = ctx;
964 cf->cmd_type = NGX_HTTP_SRV_CONF;
965 rv = ngx_conf_parse(cf, NULL);
966 *cf = pvcf;
967
968 if (rv != NGX_CONF_OK) {
969 return rv;
970 }
971
972 ngx_qsort(cscf->locations.elts, (size_t) cscf->locations.nelts,
973 sizeof(ngx_http_core_loc_conf_t *), ngx_cmp_locations);
974
975 return rv;
976 }
977
978
979 static int ngx_cmp_locations(const void *one, const void *two)
980 {
981 ngx_int_t rc;
982 ngx_http_core_loc_conf_t *first, *second;
983
984 first = *(ngx_http_core_loc_conf_t **) one;
985 second = *(ngx_http_core_loc_conf_t **) two;
986
987 #if (HAVE_PCRE)
988
989 if (first->regex && !second->regex) {
990 /* shift the regex matches to the end */
991 return 1;
992 }
993
994 if (first->regex || second->regex) {
995 /* do not sort the regex matches */
996 return 0;
997 }
998
999 #endif
1000
1001 rc = ngx_strcmp(first->name.data, second->name.data);
1002
1003 if (rc == 0 && second->exact_match) {
1004 /* an exact match must be before the same inclusive one */
1005 return 1;
1006 }
1007
1008 return rc;
1009 }
1010
1011
1012 static char *ngx_location_block(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
1013 {
1014 char *rv;
1015 ngx_int_t m;
1016 ngx_str_t *value;
1017 ngx_conf_t pcf;
1018 ngx_http_module_t *module;
1019 ngx_http_conf_ctx_t *ctx, *pctx;
1020 ngx_http_core_srv_conf_t *cscf;
1021 ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp;
1022 #if (HAVE_PCRE)
1023 ngx_str_t err;
1024 u_char errstr[NGX_MAX_CONF_ERRSTR];
1025 #endif
1026
1027 if (!(ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)))) {
1028 return NGX_CONF_ERROR;
1029 }
1030
1031 pctx = cf->ctx;
1032 ctx->main_conf = pctx->main_conf;
1033 ctx->srv_conf = pctx->srv_conf;
1034
1035 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
1036 if (ctx->loc_conf == NULL) {
1037 return NGX_CONF_ERROR;
1038 }
1039
1040 for (m = 0; ngx_modules[m]; m++) {
1041 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
1042 continue;
1043 }
1044
1045 module = ngx_modules[m]->ctx;
1046
1047 if (module->create_loc_conf) {
1048 ctx->loc_conf[ngx_modules[m]->ctx_index] =
1049 module->create_loc_conf(cf);
1050 if (ctx->loc_conf[ngx_modules[m]->ctx_index] == NULL) {
1051 return NGX_CONF_ERROR;
1052 }
1053 }
1054 }
1055
1056 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
1057 clcf->loc_conf = ctx->loc_conf;
1058
1059 value = cf->args->elts;
1060
1061 if (cf->args->nelts == 3) {
1062 if (value[1].len == 1 && value[1].data[0] == '=') {
1063 clcf->name.len = value[2].len;
1064 clcf->name.data = value[2].data;
1065 clcf->exact_match = 1;
1066
1067 } else if ((value[1].len == 1 && value[1].data[0] == '~')
1068 || (value[1].len == 2
1069 && value[1].data[0] == '~'
1070 && value[1].data[1] == '*'))
1071 {
1072 #if (HAVE_PCRE)
1073 err.len = NGX_MAX_CONF_ERRSTR;
1074 err.data = errstr;
1075
1076 clcf->regex = ngx_regex_compile(&value[2],
1077 value[1].len == 2 ? NGX_REGEX_CASELESS: 0,
1078 cf->pool, &err);
1079
1080 if (clcf->regex == NULL) {
1081 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
1082 return NGX_CONF_ERROR;
1083 }
1084
1085 clcf->name = value[2];
1086 #else
1087 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1088 "the using of the regex \"%s\" "
1089 "requires PCRE library",
1090 value[2].data);
1091 return NGX_CONF_ERROR;
1092 #endif
1093
1094 } else {
1095 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1096 "invalid location modifier \"%s\"",
1097 value[1].data);
1098 return NGX_CONF_ERROR;
1099 }
1100
1101 } else {
1102 clcf->name.len = value[1].len;
1103 clcf->name.data = value[1].data;
1104 }
1105
1106 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
1107
1108 if (pclcf->name.len == 0) {
1109 cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
1110 if (!(clcfp = ngx_push_array(&cscf->locations))) {
1111 return NGX_CONF_ERROR;
1112 }
1113
1114 } else {
1115 clcf->prev_location = pclcf;
1116
1117 if (pclcf->exact_match) {
1118 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1119 "location \"%s\" could not be inside "
1120 "the exact location \"%s\"",
1121 clcf->name.data, pclcf->name.data);
1122 return NGX_CONF_ERROR;
1123 }
1124
1125 #if (HAVE_PCRE)
1126 if (clcf->regex == NULL
1127 && ngx_strncmp(clcf->name.data, pclcf->name.data, pclcf->name.len)
1128 != 0)
1129 #else
1130 if (ngx_strncmp(clcf->name.data, pclcf->name.data, pclcf->name.len)
1131 != 0)
1132 #endif
1133 {
1134 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1135 "location \"%s\" is outside location \"%s\"",
1136 clcf->name.data, pclcf->name.data);
1137 return NGX_CONF_ERROR;
1138 }
1139
1140 if (pclcf->locations.elts == NULL) {
1141 ngx_init_array(pclcf->locations, cf->pool, 5, sizeof(void *),
1142 NGX_CONF_ERROR);
1143 }
1144
1145 if (!(clcfp = ngx_push_array(&pclcf->locations))) {
1146 return NGX_CONF_ERROR;
1147 }
1148 }
1149
1150 *clcfp = clcf;
1151
1152 pcf = *cf;
1153 cf->ctx = ctx;
1154 cf->cmd_type = NGX_HTTP_LOC_CONF;
1155 rv = ngx_conf_parse(cf, NULL);
1156 *cf = pcf;
1157
1158 return rv;
1159 }
1160
1161
1162 static char *ngx_types_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1163 {
1164 char *rv;
1165 ngx_conf_t pcf;
1166
1167 pcf = *cf;
1168 cf->handler = ngx_set_type;
1169 cf->handler_conf = conf;
1170 rv = ngx_conf_parse(cf, NULL);
1171 *cf = pcf;
1172
1173 return rv;
1174 }
1175
1176
1177 static char *ngx_set_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
1178 {
1179 ngx_http_core_loc_conf_t *lcf = conf;
1180
1181 uint32_t key;
1182 ngx_uint_t i;
1183 ngx_str_t *args;
1184 ngx_http_type_t *type;
1185
1186 if (lcf->types == NULL) {
1187 lcf->types = ngx_palloc(cf->pool, NGX_HTTP_TYPES_HASH_PRIME
1188 * sizeof(ngx_array_t));
1189 if (lcf->types == NULL) {
1190 return NGX_CONF_ERROR;
1191 }
1192
1193 for (i = 0; i < NGX_HTTP_TYPES_HASH_PRIME; i++) {
1194 if (ngx_array_init(&lcf->types[i], cf->pool, 5,
1195 sizeof(ngx_http_type_t)) == NGX_ERROR)
1196 {
1197 return NGX_CONF_ERROR;
1198 }
1199 }
1200 }
1201
1202 args = (ngx_str_t *) cf->args->elts;
1203
1204 for (i = 1; i < cf->args->nelts; i++) {
1205 ngx_http_types_hash_key(key, args[i]);
1206
1207 if (!(type = ngx_array_push(&lcf->types[key]))) {
1208 return NGX_CONF_ERROR;
1209 }
1210
1211 type->exten = args[i];
1212 type->type = args[0];
1213 }
1214
1215 return NGX_CONF_OK;
1216 }
1217
1218
1219 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf)
1220 {
1221 ngx_http_core_main_conf_t *cmcf;
1222
1223 ngx_test_null(cmcf,
1224 ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t)),
1225 NGX_CONF_ERROR);
1226
1227 ngx_init_array(cmcf->servers, cf->pool,
1228 5, sizeof(ngx_http_core_srv_conf_t *),
1229 NGX_CONF_ERROR);
1230
1231 return cmcf;
1232 }
1233
1234
1235 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
1236 {
1237 #if 0
1238 ngx_http_core_main_conf_t *cmcf = conf;
1239
1240 /* TODO: remove it if no directives */
1241 #endif
1242
1243 return NGX_CONF_OK;
1244 }
1245
1246
1247 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf)
1248 {
1249 ngx_http_core_srv_conf_t *cscf;
1250
1251 ngx_test_null(cscf,
1252 ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t)),
1253 NGX_CONF_ERROR);
1254
1255 /*
1256
1257 set by ngx_pcalloc():
1258
1259 conf->client_large_buffers.num = 0;
1260
1261 */
1262
1263
1264 ngx_init_array(cscf->locations, cf->pool,
1265 5, sizeof(void *), NGX_CONF_ERROR);
1266 ngx_init_array(cscf->listen, cf->pool, 5, sizeof(ngx_http_listen_t),
1267 NGX_CONF_ERROR);
1268 ngx_init_array(cscf->server_names, cf->pool,
1269 5, sizeof(ngx_http_server_name_t), NGX_CONF_ERROR);
1270
1271 cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
1272 cscf->post_accept_timeout = NGX_CONF_UNSET_MSEC;
1273 cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
1274 cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
1275 cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
1276 cscf->restrict_host_names = NGX_CONF_UNSET_UINT;
1277
1278 return cscf;
1279 }
1280
1281
1282 static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf,
1283 void *parent, void *child)
1284 {
1285 ngx_http_core_srv_conf_t *prev = parent;
1286 ngx_http_core_srv_conf_t *conf = child;
1287
1288 ngx_http_listen_t *l;
1289 ngx_http_server_name_t *n;
1290 ngx_http_core_main_conf_t *cmcf;
1291
1292 /* TODO: it does not merge, it inits only */
1293
1294 if (conf->listen.nelts == 0) {
1295 ngx_test_null(l, ngx_push_array(&conf->listen), NGX_CONF_ERROR);
1296 l->addr = INADDR_ANY;
1297 #if (WIN32)
1298 l->port = 80;
1299 #else
1300 /* STUB: getuid() should be cached */
1301 l->port = (getuid() == 0) ? 80 : 8000;
1302 #endif
1303 l->family = AF_INET;
1304 }
1305
1306 if (conf->server_names.nelts == 0) {
1307 ngx_test_null(n, ngx_push_array(&conf->server_names), NGX_CONF_ERROR);
1308 ngx_test_null(n->name.data, ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN),
1309 NGX_CONF_ERROR);
1310
1311 if (gethostname((char *) n->name.data, NGX_MAXHOSTNAMELEN) == -1) {
1312 ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
1313 "gethostname() failed");
1314 return NGX_CONF_ERROR;
1315 }
1316
1317 n->name.len = ngx_strlen(n->name.data);
1318 n->core_srv_conf = conf;
1319
1320 #if 0
1321 ctx = (ngx_http_conf_ctx_t *)
1322 cf->cycle->conf_ctx[ngx_http_module.index];
1323 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
1324 #endif
1325 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1326
1327 if (cmcf->max_server_name_len < n->name.len) {
1328 cmcf->max_server_name_len = n->name.len;
1329 }
1330 }
1331
1332 ngx_conf_merge_size_value(conf->connection_pool_size,
1333 prev->connection_pool_size, 256);
1334 ngx_conf_merge_msec_value(conf->post_accept_timeout,
1335 prev->post_accept_timeout, 60000);
1336 ngx_conf_merge_size_value(conf->request_pool_size,
1337 prev->request_pool_size, 4096);
1338 ngx_conf_merge_msec_value(conf->client_header_timeout,
1339 prev->client_header_timeout, 60000);
1340 ngx_conf_merge_size_value(conf->client_header_buffer_size,
1341 prev->client_header_buffer_size, 1024);
1342 ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
1343 prev->large_client_header_buffers,
1344 4, ngx_pagesize);
1345
1346 if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
1347 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1348 "the \"large_client_header_buffers\" size must be "
1349 "equal to or bigger than \"connection_pool_size\"");
1350 return NGX_CONF_ERROR;
1351 }
1352
1353 ngx_conf_merge_unsigned_value(conf->restrict_host_names,
1354 prev->restrict_host_names, 0);
1355
1356 return NGX_CONF_OK;
1357 }
1358
1359
1360 static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf)
1361 {
1362 ngx_http_core_loc_conf_t *lcf;
1363
1364 ngx_test_null(lcf,
1365 ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t)),
1366 NGX_CONF_ERROR);
1367
1368 /* set by ngx_pcalloc():
1369
1370 lcf->root.len = 0;
1371 lcf->root.data = NULL;
1372 lcf->types = NULL;
1373 lcf->default_type.len = 0;
1374 lcf->default_type.data = NULL;
1375 lcf->err_log = NULL;
1376 lcf->error_pages = NULL;
1377
1378 lcf->regex = NULL;
1379 lcf->exact_match = 0;
1380 lcf->auto_redirect = 0;
1381 lcf->alias = 0;
1382
1383 */
1384
1385 lcf->client_max_body_size = NGX_CONF_UNSET_SIZE;
1386 lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
1387 lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
1388 lcf->sendfile = NGX_CONF_UNSET;
1389 lcf->tcp_nopush = NGX_CONF_UNSET;
1390 lcf->send_timeout = NGX_CONF_UNSET_MSEC;
1391 lcf->send_lowat = NGX_CONF_UNSET_SIZE;
1392 lcf->postpone_output = NGX_CONF_UNSET_SIZE;
1393 lcf->limit_rate = NGX_CONF_UNSET_SIZE;
1394 lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
1395 lcf->keepalive_header = NGX_CONF_UNSET;
1396 lcf->lingering_time = NGX_CONF_UNSET_MSEC;
1397 lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
1398 lcf->reset_timedout_connection = NGX_CONF_UNSET;
1399 lcf->msie_padding = NGX_CONF_UNSET;
1400
1401 return lcf;
1402 }
1403
1404
1405 static ngx_http_type_t default_types[] = {
1406 { ngx_string("html"), ngx_string("text/html") },
1407 { ngx_string("gif"), ngx_string("image/gif") },
1408 { ngx_string("jpg"), ngx_string("image/jpeg") },
1409 { ngx_null_string, ngx_null_string }
1410 };
1411
1412
1413 static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
1414 void *parent, void *child)
1415 {
1416 ngx_http_core_loc_conf_t *prev = parent;
1417 ngx_http_core_loc_conf_t *conf = child;
1418
1419 int i, key;
1420 ngx_http_type_t *t;
1421
1422 ngx_conf_merge_str_value(conf->root, prev->root, "html");
1423
1424 if (ngx_conf_full_name(cf->cycle, &conf->root) == NGX_ERROR) {
1425 return NGX_CONF_ERROR;
1426 }
1427
1428 if (conf->types == NULL) {
1429 if (prev->types) {
1430 conf->types = prev->types;
1431
1432 } else {
1433 ngx_test_null(conf->types,
1434 ngx_palloc(cf->pool, NGX_HTTP_TYPES_HASH_PRIME
1435 * sizeof(ngx_array_t)),
1436 NGX_CONF_ERROR);
1437
1438 for (i = 0; i < NGX_HTTP_TYPES_HASH_PRIME; i++) {
1439 ngx_init_array(conf->types[i], cf->pool,
1440 5, sizeof(ngx_http_type_t), NGX_CONF_ERROR);
1441 }
1442
1443 for (i = 0; default_types[i].exten.len; i++) {
1444 ngx_http_types_hash_key(key, default_types[i].exten);
1445
1446 ngx_test_null(t, ngx_push_array(&conf->types[key]),
1447 NGX_CONF_ERROR);
1448 t->exten.len = default_types[i].exten.len;
1449 t->exten.data = default_types[i].exten.data;
1450 t->type.len = default_types[i].type.len;
1451 t->type.data = default_types[i].type.data;
1452 }
1453 }
1454 }
1455
1456 if (conf->err_log == NULL) {
1457 if (prev->err_log) {
1458 conf->err_log = prev->err_log;
1459 } else {
1460 conf->err_log = cf->cycle->new_log;
1461 }
1462 }
1463
1464 if (conf->error_pages == NULL && prev->error_pages) {
1465 conf->error_pages = prev->error_pages;
1466 }
1467
1468 ngx_conf_merge_str_value(conf->default_type,
1469 prev->default_type, "text/plain");
1470
1471 ngx_conf_merge_size_value(conf->client_max_body_size,
1472 prev->client_max_body_size, 1 * 1024 * 1024);
1473 ngx_conf_merge_size_value(conf->client_body_buffer_size,
1474 prev->client_body_buffer_size,
1475 (size_t) 2 * ngx_pagesize);
1476 ngx_conf_merge_msec_value(conf->client_body_timeout,
1477 prev->client_body_timeout, 60000);
1478 ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
1479 ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
1480 ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
1481 ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
1482 ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
1483 1460);
1484 ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
1485 ngx_conf_merge_msec_value(conf->keepalive_timeout,
1486 prev->keepalive_timeout, 75000);
1487 ngx_conf_merge_sec_value(conf->keepalive_header,
1488 prev->keepalive_header, 0);
1489 ngx_conf_merge_msec_value(conf->lingering_time,
1490 prev->lingering_time, 30000);
1491 ngx_conf_merge_msec_value(conf->lingering_timeout,
1492 prev->lingering_timeout, 5000);
1493
1494 ngx_conf_merge_value(conf->reset_timedout_connection,
1495 prev->reset_timedout_connection, 0);
1496 ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
1497
1498 if (conf->open_files == NULL) {
1499 conf->open_files = prev->open_files;
1500 }
1501
1502 return NGX_CONF_OK;
1503 }
1504
1505
1506 static char *ngx_set_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1507 {
1508 ngx_http_core_srv_conf_t *scf = conf;
1509
1510 u_char *addr;
1511 ngx_int_t port;
1512 ngx_uint_t p;
1513 struct hostent *h;
1514 ngx_str_t *args;
1515 ngx_http_listen_t *ls;
1516
1517 /*
1518 * TODO: check duplicate 'listen' directives,
1519 * add resolved name to server names ???
1520 */
1521
1522 if (!(ls = ngx_array_push(&scf->listen))) {
1523 return NGX_CONF_ERROR;
1524 }
1525
1526 /* AF_INET only */
1527
1528 ls->family = AF_INET;
1529 ls->default_server = 0;
1530 ls->file_name = cf->conf_file->file.name;
1531 ls->line = cf->conf_file->line;
1532
1533 args = cf->args->elts;
1534 addr = args[1].data;
1535
1536 for (p = 0; p < args[1].len; p++) {
1537 if (addr[p] == ':') {
1538 addr[p++] = '\0';
1539 break;
1540 }
1541 }
1542
1543 if (p == args[1].len) {
1544 /* no ":" in the "listen" */
1545 p = 0;
1546 }
1547
1548 port = ngx_atoi(&addr[p], args[1].len - p);
1549
1550 if (port == NGX_ERROR && p == 0) {
1551
1552 /* "listen host" */
1553 ls->port = 80;
1554
1555 } else if ((port == NGX_ERROR && p != 0) /* "listen host:NONNUMBER" */
1556 || (port < 1 || port > 65536)) { /* "listen 99999" */
1557
1558 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1559 "invalid port \"%s\" in \"%s\" directive, "
1560 "it must be a number between 1 and 65535",
1561 &addr[p], cmd->name.data);
1562
1563 return NGX_CONF_ERROR;
1564
1565 } else if (p == 0) {
1566 ls->addr = INADDR_ANY;
1567 ls->port = (in_port_t) port;
1568 return NGX_CONF_OK;
1569
1570 } else {
1571 ls->port = (in_port_t) port;
1572 }
1573
1574 ls->addr = inet_addr((const char *) addr);
1575 if (ls->addr == INADDR_NONE) {
1576 h = gethostbyname((const char *) addr);
1577
1578 if (h == NULL || h->h_addr_list[0] == NULL) {
1579 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1580 "can not resolve host \"%s\" "
1581 "in \"%s\" directive", addr, cmd->name.data);
1582 return NGX_CONF_ERROR;
1583 }
1584
1585 ls->addr = *(in_addr_t *)(h->h_addr_list[0]);
1586 }
1587
1588 return NGX_CONF_OK;
1589 }
1590
1591
1592 static char *ngx_set_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1593 {
1594 ngx_http_core_srv_conf_t *scf = conf;
1595
1596 ngx_uint_t i;
1597 ngx_str_t *value;
1598 ngx_http_server_name_t *sn;
1599 ngx_http_core_main_conf_t *cmcf;
1600
1601 /* TODO: several names */
1602 /* TODO: warn about duplicate 'server_name' directives */
1603
1604 #if 0
1605 ctx = (ngx_http_conf_ctx_t *) cf->cycle->conf_ctx[ngx_http_module.index];
1606 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
1607 #endif
1608 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
1609
1610 value = cf->args->elts;
1611
1612 for (i = 1; i < cf->args->nelts; i++) {
1613 if (value[i].len == 0) {
1614 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1615 "server name \"%s\" is invalid "
1616 "in \"%s\" directive",
1617 value[i].data, cmd->name.data);
1618 return NGX_CONF_ERROR;
1619 }
1620
1621 ngx_test_null(sn, ngx_push_array(&scf->server_names), NGX_CONF_ERROR);
1622
1623 sn->name.len = value[i].len;
1624 sn->name.data = value[i].data;
1625 sn->core_srv_conf = scf;
1626
1627 if (cmcf->max_server_name_len < sn->name.len) {
1628 cmcf->max_server_name_len = sn->name.len;
1629 }
1630 }
1631
1632 return NGX_CONF_OK;
1633 }
1634
1635
1636 static char *ngx_set_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1637 {
1638 ngx_http_core_loc_conf_t *lcf = conf;
1639
1640 ngx_uint_t alias;
1641 ngx_str_t *value;
1642
1643 alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
1644
1645 if (lcf->root.data) {
1646
1647 /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
1648
1649 if ((ngx_uint_t) lcf->alias == alias) {
1650 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1651 "\"%s\" directive is duplicate",
1652 cmd->name.data);
1653 } else {
1654 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1655 "\"%s\" directive is duplicate, "
1656 "\"%s\" directive is specified before",
1657 cmd->name.data, lcf->alias ? "alias" : "root");
1658 }
1659
1660 return NGX_CONF_ERROR;
1661 }
1662
1663 value = cf->args->elts;
1664
1665 lcf->alias = alias;
1666 lcf->root = value[1];
1667
1668 if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
1669 lcf->root.len--;
1670 }
1671
1672 return NGX_CONF_OK;
1673 }
1674
1675
1676 static char *ngx_set_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1677 {
1678 ngx_http_core_loc_conf_t *lcf = conf;
1679
1680 int overwrite;
1681 ngx_uint_t i, n;
1682 ngx_str_t *value;
1683 ngx_http_err_page_t *err;
1684
1685 if (lcf->error_pages == NULL) {
1686 lcf->error_pages = ngx_create_array(cf->pool, 5,
1687 sizeof(ngx_http_err_page_t));
1688 if (lcf->error_pages == NULL) {
1689 return NGX_CONF_ERROR;
1690 }
1691 }
1692
1693 value = cf->args->elts;
1694
1695 i = cf->args->nelts - 2;
1696
1697 if (value[i].data[0] == '=') {
1698 if (i == 1) {
1699 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1700 "invalid value \"%s\"", value[i].data);
1701 return NGX_CONF_ERROR;
1702 }
1703
1704 overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
1705
1706 if (overwrite == NGX_ERROR) {
1707 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1708 "invalid value \"%s\"", value[i].data);
1709 return NGX_CONF_ERROR;
1710 }
1711
1712 n = 2;
1713
1714 } else {
1715 overwrite = 0;
1716 n = 1;
1717 }
1718
1719 for (i = 1; i < cf->args->nelts - n; i++) {
1720 if (!(err = ngx_push_array(lcf->error_pages))) {
1721 return NGX_CONF_ERROR;
1722 }
1723
1724 err->status = ngx_atoi(value[i].data, value[i].len);
1725 if (err->status == NGX_ERROR) {
1726 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1727 "invalid value \"%s\"", value[i].data);
1728 return NGX_CONF_ERROR;
1729 }
1730
1731 if (err->status < 400 || err->status > 599) {
1732 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1733 "value \"%s\" must be between 400 and 599",
1734 value[i].data);
1735 return NGX_CONF_ERROR;
1736 }
1737
1738 err->overwrite = overwrite;
1739 err->uri = value[cf->args->nelts - 1];
1740 }
1741
1742 return NGX_CONF_OK;
1743 }
1744
1745
1746 static char *ngx_set_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1747 {
1748 ngx_http_core_loc_conf_t *lcf = conf;
1749
1750 ngx_str_t *value;
1751
1752 if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
1753 return "is duplicate";
1754 }
1755
1756 value = cf->args->elts;
1757
1758 lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
1759 if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
1760 return "invalid value";
1761 }
1762
1763 if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
1764 return "value must be less than 597 hours";
1765 }
1766
1767 if (cf->args->nelts == 2) {
1768 return NGX_CONF_OK;
1769 }
1770
1771 lcf->keepalive_header = ngx_parse_time(&value[2], 1);
1772 if (lcf->keepalive_header == NGX_ERROR) {
1773 return "invalid value";
1774 }
1775
1776 if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
1777 return "value must be less than 68 years";
1778 }
1779
1780 return NGX_CONF_OK;
1781 }
1782
1783
1784 static char *ngx_set_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
1785 {
1786 ngx_http_core_loc_conf_t *lcf = conf;
1787
1788 if (!(lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args))) {
1789 return NGX_CONF_ERROR;
1790 }
1791
1792 return ngx_set_error_log_levels(cf, lcf->err_log);
1793 }
1794
1795
1796 static char *ngx_http_lowat_check(ngx_conf_t *cf, void *post, void *data)
1797 {
1798 #if (HAVE_LOWAT_EVENT)
1799
1800 ssize_t *np = data;
1801
1802 if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
1803 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
1804 "\"send_lowat\" must be less than %d "
1805 "(sysctl net.inet.tcp.sendspace)",
1806 ngx_freebsd_net_inet_tcp_sendspace);
1807
1808 return NGX_CONF_ERROR;
1809 }
1810
1811 #else
1812
1813 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
1814 "\"send_lowat\" is not supported, ignored");
1815
1816 #endif
1817
1818 return NGX_CONF_OK;
1819 }