comparison src/http/ngx_http.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 4b2dafa26fe2
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
12
13 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
14 static char *ngx_http_merge_locations(ngx_conf_t *cf,
15 ngx_array_t *locations,
16 void **loc_conf,
17 ngx_http_module_t *module,
18 ngx_uint_t ctx_index);
19
20 int ngx_http_max_module;
21
22 ngx_uint_t ngx_http_total_requests;
23 uint64_t ngx_http_total_sent;
24
25
26 ngx_int_t (*ngx_http_top_header_filter) (ngx_http_request_t *r);
27 ngx_int_t (*ngx_http_top_body_filter) (ngx_http_request_t *r, ngx_chain_t *ch);
28
29
30 static ngx_command_t ngx_http_commands[] = {
31
32 {ngx_string("http"),
33 NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS,
34 ngx_http_block,
35 0,
36 0,
37 NULL},
38
39 ngx_null_command
40 };
41
42
43 static ngx_core_module_t ngx_http_module_ctx = {
44 ngx_string("http"),
45 NULL,
46 NULL
47 };
48
49
50 ngx_module_t ngx_http_module = {
51 NGX_MODULE,
52 &ngx_http_module_ctx, /* module context */
53 ngx_http_commands, /* module directives */
54 NGX_CORE_MODULE, /* module type */
55 NULL, /* init module */
56 NULL /* init child */
57 };
58
59
60 static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
61 {
62 char *rv;
63 ngx_uint_t mi, m, s, l, p, a, n;
64 ngx_uint_t port_found, addr_found, virtual_names;
65 ngx_conf_t pcf;
66 ngx_array_t in_ports;
67 ngx_listening_t *ls;
68 ngx_http_listen_t *lscf;
69 ngx_http_module_t *module;
70 ngx_http_handler_pt *h;
71 ngx_http_conf_ctx_t *ctx;
72 ngx_http_in_port_t *in_port, *inport;
73 ngx_http_in_addr_t *in_addr, *inaddr;
74 ngx_http_server_name_t *s_name, *name;
75 ngx_http_core_srv_conf_t **cscfp, *cscf;
76 ngx_http_core_loc_conf_t *clcf;
77 ngx_http_core_main_conf_t *cmcf;
78 #if (WIN32)
79 ngx_iocp_conf_t *iocpcf;
80 #endif
81
82 /* the main http context */
83 ngx_test_null(ctx,
84 ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)),
85 NGX_CONF_ERROR);
86
87 *(ngx_http_conf_ctx_t **) conf = ctx;
88
89 /* count the number of the http modules and set up their indices */
90
91 ngx_http_max_module = 0;
92 for (m = 0; ngx_modules[m]; m++) {
93 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
94 continue;
95 }
96
97 ngx_modules[m]->ctx_index = ngx_http_max_module++;
98 }
99
100 /* the main http main_conf, it's the same in the all http contexts */
101 ngx_test_null(ctx->main_conf,
102 ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
103 NGX_CONF_ERROR);
104
105 /* the http null srv_conf, it's used to merge the server{}s' srv_conf's */
106 ngx_test_null(ctx->srv_conf,
107 ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
108 NGX_CONF_ERROR);
109
110 /* the http null loc_conf, it's used to merge the server{}s' loc_conf's */
111 ngx_test_null(ctx->loc_conf,
112 ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module),
113 NGX_CONF_ERROR);
114
115
116 /* create the main_conf, srv_conf and loc_conf in all http modules */
117
118 for (m = 0; ngx_modules[m]; m++) {
119 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
120 continue;
121 }
122
123 module = ngx_modules[m]->ctx;
124 mi = ngx_modules[m]->ctx_index;
125
126 if (module->pre_conf) {
127 if (module->pre_conf(cf) != NGX_OK) {
128 return NGX_CONF_ERROR;
129 }
130 }
131
132 if (module->create_main_conf) {
133 ngx_test_null(ctx->main_conf[mi], module->create_main_conf(cf),
134 NGX_CONF_ERROR);
135 }
136
137 if (module->create_srv_conf) {
138 ngx_test_null(ctx->srv_conf[mi], module->create_srv_conf(cf),
139 NGX_CONF_ERROR);
140 }
141
142 if (module->create_loc_conf) {
143 ngx_test_null(ctx->loc_conf[mi], module->create_loc_conf(cf),
144 NGX_CONF_ERROR);
145 }
146 }
147
148 /* parse inside the http{} block */
149
150 pcf = *cf;
151 cf->ctx = ctx;
152 cf->module_type = NGX_HTTP_MODULE;
153 cf->cmd_type = NGX_HTTP_MAIN_CONF;
154 rv = ngx_conf_parse(cf, NULL);
155
156 if (rv != NGX_CONF_OK) {
157 *cf = pcf;
158 return rv;
159 }
160
161 /*
162 * init http{} main_conf's, merge the server{}s' srv_conf's
163 * and its location{}s' loc_conf's
164 */
165
166 cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
167 cscfp = cmcf->servers.elts;
168
169 for (m = 0; ngx_modules[m]; m++) {
170 if (ngx_modules[m]->type != NGX_HTTP_MODULE) {
171 continue;
172 }
173
174 module = ngx_modules[m]->ctx;
175 mi = ngx_modules[m]->ctx_index;
176
177 /* init http{} main_conf's */
178
179 if (module->init_main_conf) {
180 rv = module->init_main_conf(cf, ctx->main_conf[mi]);
181 if (rv != NGX_CONF_OK) {
182 *cf = pcf;
183 return rv;
184 }
185 }
186
187 for (s = 0; s < cmcf->servers.nelts; s++) {
188
189 /* merge the server{}s' srv_conf's */
190
191 if (module->merge_srv_conf) {
192 rv = module->merge_srv_conf(cf,
193 ctx->srv_conf[mi],
194 cscfp[s]->ctx->srv_conf[mi]);
195 if (rv != NGX_CONF_OK) {
196 *cf = pcf;
197 return rv;
198 }
199 }
200
201 if (module->merge_loc_conf) {
202
203 /* merge the server{}'s loc_conf */
204
205 rv = module->merge_loc_conf(cf,
206 ctx->loc_conf[mi],
207 cscfp[s]->ctx->loc_conf[mi]);
208 if (rv != NGX_CONF_OK) {
209 *cf = pcf;
210 return rv;
211 }
212
213 /* merge the locations{}' loc_conf's */
214
215 rv = ngx_http_merge_locations(cf, &cscfp[s]->locations,
216 cscfp[s]->ctx->loc_conf,
217 module, mi);
218 if (rv != NGX_CONF_OK) {
219 *cf = pcf;
220 return rv;
221 }
222
223 #if 0
224 clcfp = (ngx_http_core_loc_conf_t **) cscfp[s]->locations.elts;
225
226 for (l = 0; l < cscfp[s]->locations.nelts; l++) {
227 rv = module->merge_loc_conf(cf,
228 cscfp[s]->ctx->loc_conf[mi],
229 clcfp[l]->loc_conf[mi]);
230 if (rv != NGX_CONF_OK) {
231 *cf = pcf;
232 return rv;
233 }
234 }
235 #endif
236 }
237 }
238 }
239
240 /* we needed "http"'s cf->ctx while merging configuration */
241 *cf = pcf;
242
243 /* init lists of the handlers */
244
245 ngx_init_array(cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
246 cf->cycle->pool, 10, sizeof(ngx_http_handler_pt),
247 NGX_CONF_ERROR);
248 cmcf->phases[NGX_HTTP_REWRITE_PHASE].type = NGX_OK;
249
250
251 /* the special find config phase for single handler */
252
253 ngx_init_array(cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers,
254 cf->cycle->pool, 1, sizeof(ngx_http_handler_pt),
255 NGX_CONF_ERROR);
256 cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].type = NGX_OK;
257
258 ngx_test_null(h, ngx_push_array(
259 &cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers),
260 NGX_CONF_ERROR);
261 *h = ngx_http_find_location_config;
262
263
264 ngx_init_array(cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
265 cf->cycle->pool, 10, sizeof(ngx_http_handler_pt),
266 NGX_CONF_ERROR);
267 cmcf->phases[NGX_HTTP_ACCESS_PHASE].type = NGX_DECLINED;
268
269
270 ngx_init_array(cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
271 cf->cycle->pool, 10, sizeof(ngx_http_handler_pt),
272 NGX_CONF_ERROR);
273 cmcf->phases[NGX_HTTP_CONTENT_PHASE].type = NGX_OK;
274
275
276 /*
277 * create the lists of the ports, the addresses and the server names
278 * to allow quickly find the server core module configuration at run-time
279 */
280
281 ngx_init_array(in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t),
282 NGX_CONF_ERROR);
283
284 /* "server" directives */
285 cscfp = cmcf->servers.elts;
286 for (s = 0; s < cmcf->servers.nelts; s++) {
287
288 /* "listen" directives */
289 lscf = cscfp[s]->listen.elts;
290 for (l = 0; l < cscfp[s]->listen.nelts; l++) {
291
292 port_found = 0;
293
294 /* AF_INET only */
295
296 in_port = in_ports.elts;
297 for (p = 0; p < in_ports.nelts; p++) {
298
299 if (lscf[l].port == in_port[p].port) {
300
301 /* the port is already in the port list */
302
303 port_found = 1;
304 addr_found = 0;
305
306 in_addr = in_port[p].addrs.elts;
307 for (a = 0; a < in_port[p].addrs.nelts; a++) {
308
309 if (lscf[l].addr == in_addr[a].addr) {
310
311 /* the address is already bound to this port */
312
313 /* "server_name" directives */
314 s_name = cscfp[s]->server_names.elts;
315 for (n = 0; n < cscfp[s]->server_names.nelts; n++) {
316
317 /*
318 * add the server name and server core module
319 * configuration to the address:port
320 */
321
322 /* TODO: duplicate names can be checked here */
323
324 ngx_test_null(name,
325 ngx_push_array(&in_addr[a].names),
326 NGX_CONF_ERROR);
327
328 name->name = s_name[n].name;
329 name->core_srv_conf = s_name[n].core_srv_conf;
330 }
331
332 /*
333 * check duplicate "default" server that
334 * serves this address:port
335 */
336
337 if (lscf[l].default_server) {
338 if (in_addr[a].default_server) {
339 ngx_log_error(NGX_LOG_ERR, cf->log, 0,
340 "duplicate default server in %s:%d",
341 lscf[l].file_name.data,
342 lscf[l].line);
343
344 return NGX_CONF_ERROR;
345 }
346
347 in_addr[a].core_srv_conf = cscfp[s];
348 in_addr[a].default_server = 1;
349 }
350
351 addr_found = 1;
352
353 break;
354
355 } else if (in_addr[a].addr == INADDR_ANY) {
356
357 /*
358 * "*:port" must be the last resort so move it
359 * to the end of the address list and add
360 * the new address at its place
361 */
362
363 ngx_test_null(inaddr,
364 ngx_push_array(&in_port[p].addrs),
365 NGX_CONF_ERROR);
366
367 ngx_memcpy(inaddr, &in_addr[a],
368 sizeof(ngx_http_in_addr_t));
369
370 in_addr[a].addr = lscf[l].addr;
371 in_addr[a].default_server = lscf[l].default_server;
372 in_addr[a].core_srv_conf = cscfp[s];
373
374 /*
375 * create the empty list of the server names that
376 * can be served on this address:port
377 */
378
379 ngx_init_array(inaddr->names, cf->pool, 10,
380 sizeof(ngx_http_server_name_t),
381 NGX_CONF_ERROR);
382
383 addr_found = 1;
384
385 break;
386 }
387 }
388
389 if (!addr_found) {
390
391 /*
392 * add the address to the addresses list that
393 * bound to this port
394 */
395
396 ngx_test_null(inaddr,
397 ngx_push_array(&in_port[p].addrs),
398 NGX_CONF_ERROR);
399
400 inaddr->addr = lscf[l].addr;
401 inaddr->default_server = lscf[l].default_server;
402 inaddr->core_srv_conf = cscfp[s];
403
404 /*
405 * create the empty list of the server names that
406 * can be served on this address:port
407 */
408
409 ngx_init_array(inaddr->names, cf->pool, 10,
410 sizeof(ngx_http_server_name_t),
411 NGX_CONF_ERROR);
412 }
413 }
414 }
415
416 if (!port_found) {
417
418 /* add the port to the in_port list */
419
420 ngx_test_null(in_port,
421 ngx_push_array(&in_ports),
422 NGX_CONF_ERROR);
423
424 in_port->port = lscf[l].port;
425
426 ngx_test_null(in_port->port_text.data, ngx_palloc(cf->pool, 7),
427 NGX_CONF_ERROR);
428 in_port->port_text.len = ngx_snprintf((char *)
429 in_port->port_text.data,
430 7, ":%d",
431 in_port->port);
432
433 /* create list of the addresses that bound to this port ... */
434
435 ngx_init_array(in_port->addrs, cf->pool, 10,
436 sizeof(ngx_http_in_addr_t),
437 NGX_CONF_ERROR);
438
439 ngx_test_null(inaddr, ngx_push_array(&in_port->addrs),
440 NGX_CONF_ERROR);
441
442 /* ... and add the address to this list */
443
444 inaddr->addr = lscf[l].addr;
445 inaddr->default_server = lscf[l].default_server;
446 inaddr->core_srv_conf = cscfp[s];
447
448 /*
449 * create the empty list of the server names that
450 * can be served on this address:port
451 */
452
453 ngx_init_array(inaddr->names, cf->pool, 10,
454 sizeof(ngx_http_server_name_t),
455 NGX_CONF_ERROR);
456 }
457 }
458 }
459
460 /* optimize the lists of the ports, the addresses and the server names */
461
462 /* AF_INET only */
463
464 in_port = in_ports.elts;
465 for (p = 0; p < in_ports.nelts; p++) {
466
467 /* check whether the all server names point to the same server */
468
469 in_addr = in_port[p].addrs.elts;
470 for (a = 0; a < in_port[p].addrs.nelts; a++) {
471
472 virtual_names = 0;
473
474 name = in_addr[a].names.elts;
475 for (n = 0; n < in_addr[a].names.nelts; n++) {
476 if (in_addr[a].core_srv_conf != name[n].core_srv_conf) {
477 virtual_names = 1;
478 break;
479 }
480 }
481
482 /*
483 * if the all server names point to the same server
484 * then we do not need to check them at run-time
485 */
486
487 if (!virtual_names) {
488 in_addr[a].names.nelts = 0;
489 }
490 }
491
492 /*
493 * if there's the binding to "*:port" then we need to bind()
494 * to "*:port" only and ignore the other bindings
495 */
496
497 if (in_addr[a - 1].addr == INADDR_ANY) {
498 a--;
499
500 } else {
501 a = 0;
502 }
503
504 in_addr = in_port[p].addrs.elts;
505 while (a < in_port[p].addrs.nelts) {
506
507 ls = ngx_listening_inet_stream_socket(cf, in_addr[a].addr,
508 in_port[p].port);
509 if (ls == NULL) {
510 return NGX_CONF_ERROR;
511 }
512
513 ls->backlog = -1;
514 #if 0
515 #if 0
516 ls->nonblocking = 1;
517 #else
518 ls->nonblocking = 0;
519 #endif
520 #endif
521 ls->addr_ntop = 1;
522
523 ls->handler = ngx_http_init_connection;
524
525 cscf = in_addr[a].core_srv_conf;
526 ls->pool_size = cscf->connection_pool_size;
527 ls->post_accept_timeout = cscf->post_accept_timeout;
528
529 clcf = cscf->ctx->loc_conf[ngx_http_core_module.ctx_index];
530 ls->log = clcf->err_log;
531
532 #if (WIN32)
533 iocpcf = ngx_event_get_conf(cf->cycle->conf_ctx, ngx_iocp_module);
534 if (iocpcf->acceptex_read) {
535 ls->post_accept_buffer_size = cscf->client_header_buffer_size;
536 }
537 #endif
538
539 ls->ctx = ctx;
540
541 if (in_port[p].addrs.nelts > 1) {
542
543 in_addr = in_port[p].addrs.elts;
544 if (in_addr[in_port[p].addrs.nelts - 1].addr != INADDR_ANY) {
545
546 /*
547 * if this port has not the "*:port" binding then create
548 * the separate ngx_http_in_port_t for the all bindings
549 */
550
551 ngx_test_null(inport,
552 ngx_palloc(cf->pool,
553 sizeof(ngx_http_in_port_t)),
554 NGX_CONF_ERROR);
555
556 inport->port = in_port[p].port;
557 inport->port_text = in_port[p].port_text;
558
559 /* init list of the addresses ... */
560
561 ngx_init_array(inport->addrs, cf->pool, 1,
562 sizeof(ngx_http_in_addr_t),
563 NGX_CONF_ERROR);
564
565 /* ... and set up it with the first address */
566
567 inport->addrs.nelts = 1;
568 inport->addrs.elts = in_port[p].addrs.elts;
569
570 ls->servers = inport;
571
572 /* prepare for the next cycle */
573
574 in_port[p].addrs.elts = (char *) in_port[p].addrs.elts
575 + in_port[p].addrs.size;
576 in_port[p].addrs.nelts--;
577
578 in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
579 a = 0;
580
581 continue;
582 }
583 }
584
585 ls->servers = &in_port[p];
586 a++;
587 }
588 }
589
590 #if (NGX_DEBUG)
591 in_port = in_ports.elts;
592 for (p = 0; p < in_ports.nelts; p++) {
593 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
594 "port: %d %08x", in_port[p].port, &in_port[p]);
595 in_addr = in_port[p].addrs.elts;
596 for (a = 0; a < in_port[p].addrs.nelts; a++) {
597 u_char ip[20];
598 ngx_inet_ntop(AF_INET, &in_addr[a].addr, ip, 20);
599 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
600 "%s %08x", ip, in_addr[a].core_srv_conf);
601 s_name = in_addr[a].names.elts;
602 for (n = 0; n < in_addr[a].names.nelts; n++) {
603 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, cf->log, 0,
604 "%s %08x", s_name[n].name.data,
605 s_name[n].core_srv_conf);
606 }
607 }
608 }
609 #endif
610
611 return NGX_CONF_OK;
612 }
613
614
615 static char *ngx_http_merge_locations(ngx_conf_t *cf,
616 ngx_array_t *locations,
617 void **loc_conf,
618 ngx_http_module_t *module,
619 ngx_uint_t ctx_index)
620 {
621 char *rv;
622 ngx_uint_t i;
623 ngx_http_core_loc_conf_t **clcfp;
624
625 clcfp = /* (ngx_http_core_loc_conf_t **) */ locations->elts;
626
627 for (i = 0; i < locations->nelts; i++) {
628 rv = module->merge_loc_conf(cf, loc_conf[ctx_index],
629 clcfp[i]->loc_conf[ctx_index]);
630 if (rv != NGX_CONF_OK) {
631 return rv;
632 }
633
634 rv = ngx_http_merge_locations(cf, &clcfp[i]->locations,
635 clcfp[i]->loc_conf, module, ctx_index);
636 if (rv != NGX_CONF_OK) {
637 return rv;
638 }
639 }
640
641 return NGX_CONF_OK;
642 }