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 static void ngx_http_wait_request_handler(ngx_event_t *ev);
14 static void ngx_http_process_request_line(ngx_event_t *rev);
15 static void ngx_http_process_request_headers(ngx_event_t *rev);
16 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
17 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
18 ngx_uint_t request_line);
19
20 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
21 ngx_table_elt_t *h, ngx_uint_t offset);
22 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
23 ngx_table_elt_t *h, ngx_uint_t offset);
24 static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
25 ngx_table_elt_t *h, ngx_uint_t offset);
26 static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
27 ngx_table_elt_t *h, ngx_uint_t offset);
28 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
29 ngx_table_elt_t *h, ngx_uint_t offset);
30 static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
31 ngx_table_elt_t *h, ngx_uint_t offset);
32
33 static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
34 ngx_uint_t alloc);
35 static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
36 ngx_str_t *host);
37 static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
38 ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
39 ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
40
41 static void ngx_http_request_handler(ngx_event_t *ev);
42 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
43 static void ngx_http_terminate_handler(ngx_http_request_t *r);
44 static void ngx_http_finalize_connection(ngx_http_request_t *r);
45 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
46 static void ngx_http_writer(ngx_http_request_t *r);
47 static void ngx_http_request_finalizer(ngx_http_request_t *r);
48
49 static void ngx_http_set_keepalive(ngx_http_request_t *r);
50 static void ngx_http_keepalive_handler(ngx_event_t *ev);
51 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
52 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
53 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
54 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
55 static void ngx_http_log_request(ngx_http_request_t *r);
56
57 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
58 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
59 ngx_http_request_t *sr, u_char *buf, size_t len);
60
61 #if (NGX_HTTP_SSL)
62 static void ngx_http_ssl_handshake(ngx_event_t *rev);
63 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
64 #endif
65
66
67 static char *ngx_http_client_errors[] = {
68
69 /* NGX_HTTP_PARSE_INVALID_METHOD */
70 "client sent invalid method",
71
72 /* NGX_HTTP_PARSE_INVALID_REQUEST */
73 "client sent invalid request",
74
75 /* NGX_HTTP_PARSE_INVALID_09_METHOD */
76 "client sent invalid method in HTTP/0.9 request"
77 };
78
79
80 ngx_http_header_t ngx_http_headers_in[] = {
81 { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
82 ngx_http_process_host },
83
84 { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
85 ngx_http_process_connection },
86
87 { ngx_string("If-Modified-Since"),
88 offsetof(ngx_http_headers_in_t, if_modified_since),
89 ngx_http_process_unique_header_line },
90
91 { ngx_string("If-Unmodified-Since"),
92 offsetof(ngx_http_headers_in_t, if_unmodified_since),
93 ngx_http_process_unique_header_line },
94
95 { ngx_string("If-Match"),
96 offsetof(ngx_http_headers_in_t, if_match),
97 ngx_http_process_unique_header_line },
98
99 { ngx_string("If-None-Match"),
100 offsetof(ngx_http_headers_in_t, if_none_match),
101 ngx_http_process_unique_header_line },
102
103 { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
104 ngx_http_process_user_agent },
105
106 { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
107 ngx_http_process_header_line },
108
109 { ngx_string("Content-Length"),
110 offsetof(ngx_http_headers_in_t, content_length),
111 ngx_http_process_unique_header_line },
112
113 { ngx_string("Content-Type"),
114 offsetof(ngx_http_headers_in_t, content_type),
115 ngx_http_process_header_line },
116
117 { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
118 ngx_http_process_header_line },
119
120 { ngx_string("If-Range"),
121 offsetof(ngx_http_headers_in_t, if_range),
122 ngx_http_process_unique_header_line },
123
124 { ngx_string("Transfer-Encoding"),
125 offsetof(ngx_http_headers_in_t, transfer_encoding),
126 ngx_http_process_header_line },
127
128 { ngx_string("Expect"),
129 offsetof(ngx_http_headers_in_t, expect),
130 ngx_http_process_unique_header_line },
131
132 { ngx_string("Upgrade"),
133 offsetof(ngx_http_headers_in_t, upgrade),
134 ngx_http_process_header_line },
135
136 #if (NGX_HTTP_GZIP)
137 { ngx_string("Accept-Encoding"),
138 offsetof(ngx_http_headers_in_t, accept_encoding),
139 ngx_http_process_header_line },
140
141 { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
142 ngx_http_process_header_line },
143 #endif
144
145 { ngx_string("Authorization"),
146 offsetof(ngx_http_headers_in_t, authorization),
147 ngx_http_process_unique_header_line },
148
149 { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
150 ngx_http_process_header_line },
151
152 #if (NGX_HTTP_X_FORWARDED_FOR)
153 { ngx_string("X-Forwarded-For"),
154 offsetof(ngx_http_headers_in_t, x_forwarded_for),
155 ngx_http_process_multi_header_lines },
156 #endif
157
158 #if (NGX_HTTP_REALIP)
159 { ngx_string("X-Real-IP"),
160 offsetof(ngx_http_headers_in_t, x_real_ip),
161 ngx_http_process_header_line },
162 #endif
163
164 #if (NGX_HTTP_HEADERS)
165 { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
166 ngx_http_process_header_line },
167
168 { ngx_string("Accept-Language"),
169 offsetof(ngx_http_headers_in_t, accept_language),
170 ngx_http_process_header_line },
171 #endif
172
173 #if (NGX_HTTP_DAV)
174 { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
175 ngx_http_process_header_line },
176
177 { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
178 ngx_http_process_header_line },
179
180 { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
181 ngx_http_process_header_line },
182
183 { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
184 ngx_http_process_header_line },
185 #endif
186
187 { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
188 ngx_http_process_multi_header_lines },
189
190 { ngx_null_string, 0, NULL }
191 };
192
193
194 void
195 ngx_http_init_connection(ngx_connection_t *c)
196 {
197 ngx_uint_t i;
198 ngx_event_t *rev;
199 struct sockaddr_in *sin;
200 ngx_http_port_t *port;
201 ngx_http_in_addr_t *addr;
202 ngx_http_log_ctx_t *ctx;
203 ngx_http_connection_t *hc;
204 #if (NGX_HAVE_INET6)
205 struct sockaddr_in6 *sin6;
206 ngx_http_in6_addr_t *addr6;
207 #endif
208
209 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
210 if (hc == NULL) {
211 ngx_http_close_connection(c);
212 return;
213 }
214
215 c->data = hc;
216
217 /* find the server configuration for the address:port */
218
219 port = c->listening->servers;
220
221 if (port->naddrs > 1) {
222
223 /*
224 * there are several addresses on this port and one of them
225 * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
226 * is required to determine a server address
227 */
228
229 if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
230 ngx_http_close_connection(c);
231 return;
232 }
233
234 switch (c->local_sockaddr->sa_family) {
235
236 #if (NGX_HAVE_INET6)
237 case AF_INET6:
238 sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
239
240 addr6 = port->addrs;
241
242 /* the last address is "*" */
243
244 for (i = 0; i < port->naddrs - 1; i++) {
245 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
246 break;
247 }
248 }
249
250 hc->addr_conf = &addr6[i].conf;
251
252 break;
253 #endif
254
255 default: /* AF_INET */
256 sin = (struct sockaddr_in *) c->local_sockaddr;
257
258 addr = port->addrs;
259
260 /* the last address is "*" */
261
262 for (i = 0; i < port->naddrs - 1; i++) {
263 if (addr[i].addr == sin->sin_addr.s_addr) {
264 break;
265 }
266 }
267
268 hc->addr_conf = &addr[i].conf;
269
270 break;
271 }
272
273 } else {
274
275 switch (c->local_sockaddr->sa_family) {
276
277 #if (NGX_HAVE_INET6)
278 case AF_INET6:
279 addr6 = port->addrs;
280 hc->addr_conf = &addr6[0].conf;
281 break;
282 #endif
283
284 default: /* AF_INET */
285 addr = port->addrs;
286 hc->addr_conf = &addr[0].conf;
287 break;
288 }
289 }
290
291 /* the default server configuration for the address:port */
292 hc->conf_ctx = hc->addr_conf->default_server->ctx;
293
294 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
295 if (ctx == NULL) {
296 ngx_http_close_connection(c);
297 return;
298 }
299
300 ctx->connection = c;
301 ctx->request = NULL;
302 ctx->current_request = NULL;
303
304 c->log->connection = c->number;
305 c->log->handler = ngx_http_log_error;
306 c->log->data = ctx;
307 c->log->action = "waiting for request";
308
309 c->log_error = NGX_ERROR_INFO;
310
311 rev = c->read;
312 rev->handler = ngx_http_wait_request_handler;
313 c->write->handler = ngx_http_empty_handler;
314
315 #if (NGX_HTTP_SPDY)
316 if (hc->addr_conf->spdy) {
317 rev->handler = ngx_http_spdy_init;
318 }
319 #endif
320
321 #if (NGX_HTTP_SSL)
322 {
323 ngx_http_ssl_srv_conf_t *sscf;
324
325 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
326
327 if (sscf->enable || hc->addr_conf->ssl) {
328
329 c->log->action = "SSL handshaking";
330
331 if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
332 ngx_log_error(NGX_LOG_ERR, c->log, 0,
333 "no \"ssl_certificate\" is defined "
334 "in server listening on SSL port");
335 ngx_http_close_connection(c);
336 return;
337 }
338
339 hc->ssl = 1;
340
341 rev->handler = ngx_http_ssl_handshake;
342 }
343 }
344 #endif
345
346 if (rev->ready) {
347 /* the deferred accept(), rtsig, aio, iocp */
348
349 if (ngx_use_accept_mutex) {
350 ngx_post_event(rev, &ngx_posted_events);
351 return;
352 }
353
354 rev->handler(rev);
355 return;
356 }
357
358 ngx_add_timer(rev, c->listening->post_accept_timeout);
359 ngx_reusable_connection(c, 1);
360
361 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
362 ngx_http_close_connection(c);
363 return;
364 }
365 }
366
367
368 static void
369 ngx_http_wait_request_handler(ngx_event_t *rev)
370 {
371 size_t size;
372 ssize_t n;
373 ngx_buf_t *b;
374 ngx_connection_t *c;
375 ngx_http_connection_t *hc;
376 ngx_http_core_srv_conf_t *cscf;
377
378 c = rev->data;
379
380 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
381
382 if (rev->timedout) {
383 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
384 ngx_http_close_connection(c);
385 return;
386 }
387
388 if (c->close) {
389 ngx_http_close_connection(c);
390 return;
391 }
392
393 hc = c->data;
394 cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
395
396 size = cscf->client_header_buffer_size;
397
398 b = c->buffer;
399
400 if (b == NULL) {
401 b = ngx_create_temp_buf(c->pool, size);
402 if (b == NULL) {
403 ngx_http_close_connection(c);
404 return;
405 }
406
407 c->buffer = b;
408
409 } else if (b->start == NULL) {
410
411 b->start = ngx_palloc(c->pool, size);
412 if (b->start == NULL) {
413 ngx_http_close_connection(c);
414 return;
415 }
416
417 b->pos = b->start;
418 b->last = b->start;
419 b->end = b->last + size;
420 }
421
422 n = c->recv(c, b->last, size);
423
424 if (n == NGX_AGAIN) {
425
426 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
427 if (c->listening->deferred_accept
428 #if (NGX_HTTP_SSL)
429 && c->ssl == NULL
430 #endif
431 )
432 {
433 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
434 "client timed out in deferred accept");
435 ngx_http_close_connection(c);
436 return;
437 }
438 #endif
439
440 if (!rev->timer_set) {
441 ngx_add_timer(rev, c->listening->post_accept_timeout);
442 ngx_reusable_connection(c, 1);
443 }
444
445 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
446 ngx_http_close_connection(c);
447 return;
448 }
449
450 /*
451 * We are trying to not hold c->buffer's memory for an idle connection.
452 */
453
454 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
455 b->start = NULL;
456 }
457
458 return;
459 }
460
461 if (n == NGX_ERROR) {
462 ngx_http_close_connection(c);
463 return;
464 }
465
466 if (n == 0) {
467 ngx_log_error(NGX_LOG_INFO, c->log, 0,
468 "client closed connection");
469 ngx_http_close_connection(c);
470 return;
471 }
472
473 b->last += n;
474
475 c->log->action = "reading client request line";
476
477 ngx_reusable_connection(c, 0);
478
479 c->data = ngx_http_create_request(c);
480 if (c->data == NULL) {
481 ngx_http_close_connection(c);
482 return;
483 }
484
485 rev->handler = ngx_http_process_request_line;
486 ngx_http_process_request_line(rev);
487 }
488
489
490 ngx_http_request_t *
491 ngx_http_create_request(ngx_connection_t *c)
492 {
493 ngx_pool_t *pool;
494 ngx_time_t *tp;
495 ngx_http_request_t *r;
496 ngx_http_log_ctx_t *ctx;
497 ngx_http_connection_t *hc;
498 ngx_http_core_srv_conf_t *cscf;
499 ngx_http_core_loc_conf_t *clcf;
500 ngx_http_core_main_conf_t *cmcf;
501
502 c->requests++;
503
504 hc = c->data;
505
506 cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
507
508 pool = ngx_create_pool(cscf->request_pool_size, c->log);
509 if (pool == NULL) {
510 return NULL;
511 }
512
513 r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
514 if (r == NULL) {
515 ngx_destroy_pool(pool);
516 return NULL;
517 }
518
519 r->pool = pool;
520
521 r->http_connection = hc;
522 r->signature = NGX_HTTP_MODULE;
523 r->connection = c;
524
525 r->main_conf = hc->conf_ctx->main_conf;
526 r->srv_conf = hc->conf_ctx->srv_conf;
527 r->loc_conf = hc->conf_ctx->loc_conf;
528
529 r->read_event_handler = ngx_http_block_reading;
530
531 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
532
533 ngx_http_set_connection_log(r->connection, clcf->error_log);
534
535 r->header_in = hc->nbusy ? hc->busy[0] : c->buffer;
536
537 if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
538 sizeof(ngx_table_elt_t))
539 != NGX_OK)
540 {
541 ngx_destroy_pool(r->pool);
542 return NULL;
543 }
544
545 r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
546 if (r->ctx == NULL) {
547 ngx_destroy_pool(r->pool);
548 return NULL;
549 }
550
551 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
552
553 r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
554 * sizeof(ngx_http_variable_value_t));
555 if (r->variables == NULL) {
556 ngx_destroy_pool(r->pool);
557 return NULL;
558 }
559
560 #if (NGX_HTTP_SSL)
561 if (c->ssl) {
562 r->main_filter_need_in_memory = 1;
563 }
564 #endif
565
566 r->main = r;
567 r->count = 1;
568
569 tp = ngx_timeofday();
570 r->start_sec = tp->sec;
571 r->start_msec = tp->msec;
572
573 r->method = NGX_HTTP_UNKNOWN;
574
575 r->headers_in.content_length_n = -1;
576 r->headers_in.keep_alive_n = -1;
577 r->headers_out.content_length_n = -1;
578 r->headers_out.last_modified_time = -1;
579
580 r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
581 r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
582
583 r->http_state = NGX_HTTP_READING_REQUEST_STATE;
584
585 ctx = c->log->data;
586 ctx->request = r;
587 ctx->current_request = r;
588 r->log_handler = ngx_http_log_error_handler;
589
590 #if (NGX_STAT_STUB)
591 (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
592 r->stat_reading = 1;
593 (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
594 #endif
595
596 return r;
597 }
598
599
600 #if (NGX_HTTP_SSL)
601
602 static void
603 ngx_http_ssl_handshake(ngx_event_t *rev)
604 {
605 u_char buf[1];
606 ssize_t n;
607 ngx_err_t err;
608 ngx_int_t rc;
609 ngx_connection_t *c;
610 ngx_http_connection_t *hc;
611 ngx_http_ssl_srv_conf_t *sscf;
612
613 c = rev->data;
614
615 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
616 "http check ssl handshake");
617
618 if (rev->timedout) {
619 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
620 ngx_http_close_connection(c);
621 return;
622 }
623
624 if (c->close) {
625 ngx_http_close_connection(c);
626 return;
627 }
628
629 n = recv(c->fd, (char *) buf, 1, MSG_PEEK);
630
631 err = ngx_socket_errno;
632
633 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %d", n);
634
635 if (n == -1) {
636 if (err == NGX_EAGAIN) {
637
638 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
639 if (c->listening->deferred_accept) {
640 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
641 "client timed out in deferred accept");
642 ngx_http_close_connection(c);
643 return;
644 }
645 #endif
646
647 if (!rev->timer_set) {
648 ngx_add_timer(rev, c->listening->post_accept_timeout);
649 ngx_reusable_connection(c, 1);
650 }
651
652 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
653 ngx_http_close_connection(c);
654 }
655
656 return;
657 }
658
659 ngx_connection_error(c, err, "recv() failed");
660 ngx_http_close_connection(c);
661
662 return;
663 }
664
665 if (n == 1) {
666 if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
667 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
668 "https ssl handshake: 0x%02Xd", buf[0]);
669
670 hc = c->data;
671 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
672 ngx_http_ssl_module);
673
674 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
675 != NGX_OK)
676 {
677 ngx_http_close_connection(c);
678 return;
679 }
680
681 rc = ngx_ssl_handshake(c);
682
683 if (rc == NGX_AGAIN) {
684
685 if (!rev->timer_set) {
686 ngx_add_timer(rev, c->listening->post_accept_timeout);
687 }
688
689 ngx_reusable_connection(c, 0);
690
691 c->ssl->handler = ngx_http_ssl_handshake_handler;
692 return;
693 }
694
695 ngx_http_ssl_handshake_handler(c);
696
697 return;
698 }
699
700 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
701
702 c->log->action = "waiting for request";
703
704 rev->handler = ngx_http_wait_request_handler;
705 ngx_http_wait_request_handler(rev);
706
707 return;
708 }
709
710 ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
711 ngx_http_close_connection(c);
712 }
713
714
715 static void
716 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
717 {
718 if (c->ssl->handshaked) {
719
720 /*
721 * The majority of browsers do not send the "close notify" alert.
722 * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
723 * and Links. And what is more, MSIE ignores the server's alert.
724 *
725 * Opera and recent Mozilla send the alert.
726 */
727
728 c->ssl->no_wait_shutdown = 1;
729
730 #if (NGX_HTTP_SPDY && defined TLSEXT_TYPE_next_proto_neg)
731 {
732 unsigned int len;
733 const unsigned char *data;
734 static const ngx_str_t spdy = ngx_string(NGX_SPDY_NPN_NEGOTIATED);
735
736 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
737
738 if (len == spdy.len && ngx_strncmp(data, spdy.data, spdy.len) == 0) {
739 ngx_http_spdy_init(c->read);
740 return;
741 }
742 }
743 #endif
744
745 c->log->action = "waiting for request";
746
747 c->read->handler = ngx_http_wait_request_handler;
748 /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
749
750 ngx_reusable_connection(c, 1);
751
752 ngx_http_wait_request_handler(c->read);
753
754 return;
755 }
756
757 if (c->read->timedout) {
758 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
759 }
760
761 ngx_http_close_connection(c);
762 }
763
764 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
765
766 int
767 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
768 {
769 ngx_str_t host;
770 const char *servername;
771 ngx_connection_t *c;
772 ngx_http_connection_t *hc;
773 ngx_http_ssl_srv_conf_t *sscf;
774 ngx_http_core_loc_conf_t *clcf;
775 ngx_http_core_srv_conf_t *cscf;
776
777 servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
778
779 if (servername == NULL) {
780 return SSL_TLSEXT_ERR_NOACK;
781 }
782
783 c = ngx_ssl_get_connection(ssl_conn);
784
785 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
786 "SSL server name: \"%s\"", servername);
787
788 host.len = ngx_strlen(servername);
789
790 if (host.len == 0) {
791 return SSL_TLSEXT_ERR_NOACK;
792 }
793
794 host.data = (u_char *) servername;
795
796 if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) {
797 return SSL_TLSEXT_ERR_NOACK;
798 }
799
800 hc = c->data;
801
802 if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
803 NULL, &cscf)
804 != NGX_OK)
805 {
806 return SSL_TLSEXT_ERR_NOACK;
807 }
808
809 hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
810 if (hc->ssl_servername == NULL) {
811 return SSL_TLSEXT_ERR_NOACK;
812 }
813
814 *hc->ssl_servername = host;
815
816 hc->conf_ctx = cscf->ctx;
817
818 clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
819
820 ngx_http_set_connection_log(c, clcf->error_log);
821
822 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
823
824 if (sscf->ssl.ctx) {
825 SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
826
827 /*
828 * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
829 * adjust other things we care about
830 */
831
832 SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
833 SSL_CTX_get_verify_callback(sscf->ssl.ctx));
834
835 SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
836
837 #ifdef SSL_CTRL_CLEAR_OPTIONS
838 /* only in 0.9.8m+ */
839 SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
840 ~SSL_CTX_get_options(sscf->ssl.ctx));
841 #endif
842
843 SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
844 }
845
846 return SSL_TLSEXT_ERR_OK;
847 }
848
849 #endif
850
851 #endif
852
853
854 static void
855 ngx_http_process_request_line(ngx_event_t *rev)
856 {
857 ssize_t n;
858 ngx_int_t rc, rv;
859 ngx_str_t host;
860 ngx_connection_t *c;
861 ngx_http_request_t *r;
862
863 c = rev->data;
864 r = c->data;
865
866 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
867 "http process request line");
868
869 if (rev->timedout) {
870 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
871 c->timedout = 1;
872 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
873 return;
874 }
875
876 rc = NGX_AGAIN;
877
878 for ( ;; ) {
879
880 if (rc == NGX_AGAIN) {
881 n = ngx_http_read_request_header(r);
882
883 if (n == NGX_AGAIN || n == NGX_ERROR) {
884 return;
885 }
886 }
887
888 rc = ngx_http_parse_request_line(r, r->header_in);
889
890 if (rc == NGX_OK) {
891
892 /* the request line has been parsed successfully */
893
894 r->request_line.len = r->request_end - r->request_start;
895 r->request_line.data = r->request_start;
896 r->request_length = r->header_in->pos - r->request_start;
897
898 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
899 "http request line: \"%V\"", &r->request_line);
900
901 r->method_name.len = r->method_end - r->request_start + 1;
902 r->method_name.data = r->request_line.data;
903
904 if (r->http_protocol.data) {
905 r->http_protocol.len = r->request_end - r->http_protocol.data;
906 }
907
908 if (ngx_http_process_request_uri(r) != NGX_OK) {
909 return;
910 }
911
912 if (r->host_start && r->host_end) {
913
914 host.len = r->host_end - r->host_start;
915 host.data = r->host_start;
916
917 rc = ngx_http_validate_host(&host, r->pool, 0);
918
919 if (rc == NGX_DECLINED) {
920 ngx_log_error(NGX_LOG_INFO, c->log, 0,
921 "client sent invalid host in request line");
922 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
923 return;
924 }
925
926 if (rc == NGX_ERROR) {
927 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
928 return;
929 }
930
931 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
932 return;
933 }
934
935 r->headers_in.server = host;
936 }
937
938 if (r->http_version < NGX_HTTP_VERSION_10) {
939
940 if (r->headers_in.server.len == 0
941 && ngx_http_set_virtual_server(r, &r->headers_in.server)
942 == NGX_ERROR)
943 {
944 return;
945 }
946
947 ngx_http_process_request(r);
948 return;
949 }
950
951
952 if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
953 sizeof(ngx_table_elt_t))
954 != NGX_OK)
955 {
956 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
957 return;
958 }
959
960 c->log->action = "reading client request headers";
961
962 rev->handler = ngx_http_process_request_headers;
963 ngx_http_process_request_headers(rev);
964
965 return;
966 }
967
968 if (rc != NGX_AGAIN) {
969
970 /* there was error while a request line parsing */
971
972 ngx_log_error(NGX_LOG_INFO, c->log, 0,
973 ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
974 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
975 return;
976 }
977
978 /* NGX_AGAIN: a request line parsing is still incomplete */
979
980 if (r->header_in->pos == r->header_in->end) {
981
982 rv = ngx_http_alloc_large_header_buffer(r, 1);
983
984 if (rv == NGX_ERROR) {
985 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
986 return;
987 }
988
989 if (rv == NGX_DECLINED) {
990 r->request_line.len = r->header_in->end - r->request_start;
991 r->request_line.data = r->request_start;
992
993 ngx_log_error(NGX_LOG_INFO, c->log, 0,
994 "client sent too long URI");
995 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
996 return;
997 }
998 }
999 }
1000 }
1001
1002
1003 ngx_int_t
1004 ngx_http_process_request_uri(ngx_http_request_t *r)
1005 {
1006 ngx_http_core_srv_conf_t *cscf;
1007
1008 if (r->args_start) {
1009 r->uri.len = r->args_start - 1 - r->uri_start;
1010 } else {
1011 r->uri.len = r->uri_end - r->uri_start;
1012 }
1013
1014 if (r->complex_uri || r->quoted_uri) {
1015
1016 r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
1017 if (r->uri.data == NULL) {
1018 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1019 return NGX_ERROR;
1020 }
1021
1022 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1023
1024 if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
1025 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1026 "client sent invalid request");
1027 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1028 return NGX_ERROR;
1029 }
1030
1031 } else {
1032 r->uri.data = r->uri_start;
1033 }
1034
1035 r->unparsed_uri.len = r->uri_end - r->uri_start;
1036 r->unparsed_uri.data = r->uri_start;
1037
1038 r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
1039
1040 if (r->uri_ext) {
1041 if (r->args_start) {
1042 r->exten.len = r->args_start - 1 - r->uri_ext;
1043 } else {
1044 r->exten.len = r->uri_end - r->uri_ext;
1045 }
1046
1047 r->exten.data = r->uri_ext;
1048 }
1049
1050 if (r->args_start && r->uri_end > r->args_start) {
1051 r->args.len = r->uri_end - r->args_start;
1052 r->args.data = r->args_start;
1053 }
1054
1055 #if (NGX_WIN32)
1056 {
1057 u_char *p, *last;
1058
1059 p = r->uri.data;
1060 last = r->uri.data + r->uri.len;
1061
1062 while (p < last) {
1063
1064 if (*p++ == ':') {
1065
1066 /*
1067 * this check covers "::$data", "::$index_allocation" and
1068 * ":$i30:$index_allocation"
1069 */
1070
1071 if (p < last && *p == '$') {
1072 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1073 "client sent unsafe win32 URI");
1074 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1075 return NGX_ERROR;
1076 }
1077 }
1078 }
1079
1080 p = r->uri.data + r->uri.len - 1;
1081
1082 while (p > r->uri.data) {
1083
1084 if (*p == ' ') {
1085 p--;
1086 continue;
1087 }
1088
1089 if (*p == '.') {
1090 p--;
1091 continue;
1092 }
1093
1094 break;
1095 }
1096
1097 if (p != r->uri.data + r->uri.len - 1) {
1098 r->uri.len = p + 1 - r->uri.data;
1099 ngx_http_set_exten(r);
1100 }
1101
1102 }
1103 #endif
1104
1105 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1106 "http uri: \"%V\"", &r->uri);
1107
1108 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1109 "http args: \"%V\"", &r->args);
1110
1111 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1112 "http exten: \"%V\"", &r->exten);
1113
1114 return NGX_OK;
1115 }
1116
1117
1118 static void
1119 ngx_http_process_request_headers(ngx_event_t *rev)
1120 {
1121 u_char *p;
1122 size_t len;
1123 ssize_t n;
1124 ngx_int_t rc, rv;
1125 ngx_table_elt_t *h;
1126 ngx_connection_t *c;
1127 ngx_http_header_t *hh;
1128 ngx_http_request_t *r;
1129 ngx_http_core_srv_conf_t *cscf;
1130 ngx_http_core_main_conf_t *cmcf;
1131
1132 c = rev->data;
1133 r = c->data;
1134
1135 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1136 "http process request header line");
1137
1138 if (rev->timedout) {
1139 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1140 c->timedout = 1;
1141 ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1142 return;
1143 }
1144
1145 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1146
1147 rc = NGX_AGAIN;
1148
1149 for ( ;; ) {
1150
1151 if (rc == NGX_AGAIN) {
1152
1153 if (r->header_in->pos == r->header_in->end) {
1154
1155 rv = ngx_http_alloc_large_header_buffer(r, 0);
1156
1157 if (rv == NGX_ERROR) {
1158 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1159 return;
1160 }
1161
1162 if (rv == NGX_DECLINED) {
1163 p = r->header_name_start;
1164
1165 r->lingering_close = 1;
1166
1167 if (p == NULL) {
1168 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1169 "client sent too large request");
1170 ngx_http_finalize_request(r,
1171 NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1172 return;
1173 }
1174
1175 len = r->header_in->end - p;
1176
1177 if (len > NGX_MAX_ERROR_STR - 300) {
1178 len = NGX_MAX_ERROR_STR - 300;
1179 p[len++] = '.'; p[len++] = '.'; p[len++] = '.';
1180 }
1181
1182 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1183 "client sent too long header line: \"%*s\"",
1184 len, r->header_name_start);
1185
1186 ngx_http_finalize_request(r,
1187 NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1188 return;
1189 }
1190 }
1191
1192 n = ngx_http_read_request_header(r);
1193
1194 if (n == NGX_AGAIN || n == NGX_ERROR) {
1195 return;
1196 }
1197 }
1198
1199 /* the host header could change the server configuration context */
1200 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1201
1202 rc = ngx_http_parse_header_line(r, r->header_in,
1203 cscf->underscores_in_headers);
1204
1205 if (rc == NGX_OK) {
1206
1207 r->request_length += r->header_in->pos - r->header_name_start;
1208
1209 if (r->invalid_header && cscf->ignore_invalid_headers) {
1210
1211 /* there was error while a header line parsing */
1212
1213 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1214 "client sent invalid header line: \"%*s\"",
1215 r->header_end - r->header_name_start,
1216 r->header_name_start);
1217 continue;
1218 }
1219
1220 /* a header line has been parsed successfully */
1221
1222 h = ngx_list_push(&r->headers_in.headers);
1223 if (h == NULL) {
1224 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1225 return;
1226 }
1227
1228 h->hash = r->header_hash;
1229
1230 h->key.len = r->header_name_end - r->header_name_start;
1231 h->key.data = r->header_name_start;
1232 h->key.data[h->key.len] = '\0';
1233
1234 h->value.len = r->header_end - r->header_start;
1235 h->value.data = r->header_start;
1236 h->value.data[h->value.len] = '\0';
1237
1238 h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1239 if (h->lowcase_key == NULL) {
1240 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1241 return;
1242 }
1243
1244 if (h->key.len == r->lowcase_index) {
1245 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1246
1247 } else {
1248 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1249 }
1250
1251 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1252 h->lowcase_key, h->key.len);
1253
1254 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1255 return;
1256 }
1257
1258 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1259 "http header: \"%V: %V\"",
1260 &h->key, &h->value);
1261
1262 continue;
1263 }
1264
1265 if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1266
1267 /* a whole header has been parsed successfully */
1268
1269 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1270 "http header done");
1271
1272 r->request_length += r->header_in->pos - r->header_name_start;
1273
1274 r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1275
1276 rc = ngx_http_process_request_header(r);
1277
1278 if (rc != NGX_OK) {
1279 return;
1280 }
1281
1282 ngx_http_process_request(r);
1283
1284 return;
1285 }
1286
1287 if (rc == NGX_AGAIN) {
1288
1289 /* a header line parsing is still not complete */
1290
1291 continue;
1292 }
1293
1294 /* rc == NGX_HTTP_PARSE_INVALID_HEADER: "\r" is not followed by "\n" */
1295
1296 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1297 "client sent invalid header line: \"%*s\\r...\"",
1298 r->header_end - r->header_name_start,
1299 r->header_name_start);
1300 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1301 return;
1302 }
1303 }
1304
1305
1306 static ssize_t
1307 ngx_http_read_request_header(ngx_http_request_t *r)
1308 {
1309 ssize_t n;
1310 ngx_event_t *rev;
1311 ngx_connection_t *c;
1312 ngx_http_core_srv_conf_t *cscf;
1313
1314 c = r->connection;
1315 rev = c->read;
1316
1317 n = r->header_in->last - r->header_in->pos;
1318
1319 if (n > 0) {
1320 return n;
1321 }
1322
1323 if (rev->ready) {
1324 n = c->recv(c, r->header_in->last,
1325 r->header_in->end - r->header_in->last);
1326 } else {
1327 n = NGX_AGAIN;
1328 }
1329
1330 if (n == NGX_AGAIN) {
1331 if (!rev->timer_set) {
1332 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1333 ngx_add_timer(rev, cscf->client_header_timeout);
1334 }
1335
1336 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1337 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1338 return NGX_ERROR;
1339 }
1340
1341 return NGX_AGAIN;
1342 }
1343
1344 if (n == 0) {
1345 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1346 "client prematurely closed connection");
1347 }
1348
1349 if (n == 0 || n == NGX_ERROR) {
1350 c->error = 1;
1351 c->log->action = "reading client request headers";
1352
1353 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1354 return NGX_ERROR;
1355 }
1356
1357 r->header_in->last += n;
1358
1359 return n;
1360 }
1361
1362
1363 static ngx_int_t
1364 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1365 ngx_uint_t request_line)
1366 {
1367 u_char *old, *new;
1368 ngx_buf_t *b;
1369 ngx_http_connection_t *hc;
1370 ngx_http_core_srv_conf_t *cscf;
1371
1372 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1373 "http alloc large header buffer");
1374
1375 if (request_line && r->state == 0) {
1376
1377 /* the client fills up the buffer with "\r\n" */
1378
1379 r->header_in->pos = r->header_in->start;
1380 r->header_in->last = r->header_in->start;
1381
1382 return NGX_OK;
1383 }
1384
1385 old = request_line ? r->request_start : r->header_name_start;
1386
1387 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1388
1389 if (r->state != 0
1390 && (size_t) (r->header_in->pos - old)
1391 >= cscf->large_client_header_buffers.size)
1392 {
1393 return NGX_DECLINED;
1394 }
1395
1396 hc = r->http_connection;
1397
1398 if (hc->nfree) {
1399 b = hc->free[--hc->nfree];
1400
1401 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1402 "http large header free: %p %uz",
1403 b->pos, b->end - b->last);
1404
1405 } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1406
1407 if (hc->busy == NULL) {
1408 hc->busy = ngx_palloc(r->connection->pool,
1409 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
1410 if (hc->busy == NULL) {
1411 return NGX_ERROR;
1412 }
1413 }
1414
1415 b = ngx_create_temp_buf(r->connection->pool,
1416 cscf->large_client_header_buffers.size);
1417 if (b == NULL) {
1418 return NGX_ERROR;
1419 }
1420
1421 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1422 "http large header alloc: %p %uz",
1423 b->pos, b->end - b->last);
1424
1425 } else {
1426 return NGX_DECLINED;
1427 }
1428
1429 hc->busy[hc->nbusy++] = b;
1430
1431 if (r->state == 0) {
1432 /*
1433 * r->state == 0 means that a header line was parsed successfully
1434 * and we do not need to copy incomplete header line and
1435 * to relocate the parser header pointers
1436 */
1437
1438 r->header_in = b;
1439
1440 return NGX_OK;
1441 }
1442
1443 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1444 "http large header copy: %d", r->header_in->pos - old);
1445
1446 new = b->start;
1447
1448 ngx_memcpy(new, old, r->header_in->pos - old);
1449
1450 b->pos = new + (r->header_in->pos - old);
1451 b->last = new + (r->header_in->pos - old);
1452
1453 if (request_line) {
1454 r->request_start = new;
1455
1456 if (r->request_end) {
1457 r->request_end = new + (r->request_end - old);
1458 }
1459
1460 r->method_end = new + (r->method_end - old);
1461
1462 r->uri_start = new + (r->uri_start - old);
1463 r->uri_end = new + (r->uri_end - old);
1464
1465 if (r->schema_start) {
1466 r->schema_start = new + (r->schema_start - old);
1467 r->schema_end = new + (r->schema_end - old);
1468 }
1469
1470 if (r->host_start) {
1471 r->host_start = new + (r->host_start - old);
1472 if (r->host_end) {
1473 r->host_end = new + (r->host_end - old);
1474 }
1475 }
1476
1477 if (r->port_start) {
1478 r->port_start = new + (r->port_start - old);
1479 r->port_end = new + (r->port_end - old);
1480 }
1481
1482 if (r->uri_ext) {
1483 r->uri_ext = new + (r->uri_ext - old);
1484 }
1485
1486 if (r->args_start) {
1487 r->args_start = new + (r->args_start - old);
1488 }
1489
1490 if (r->http_protocol.data) {
1491 r->http_protocol.data = new + (r->http_protocol.data - old);
1492 }
1493
1494 } else {
1495 r->header_name_start = new;
1496 r->header_name_end = new + (r->header_name_end - old);
1497 r->header_start = new + (r->header_start - old);
1498 r->header_end = new + (r->header_end - old);
1499 }
1500
1501 r->header_in = b;
1502
1503 return NGX_OK;
1504 }
1505
1506
1507 static ngx_int_t
1508 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1509 ngx_uint_t offset)
1510 {
1511 ngx_table_elt_t **ph;
1512
1513 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1514
1515 if (*ph == NULL) {
1516 *ph = h;
1517 }
1518
1519 return NGX_OK;
1520 }
1521
1522
1523 static ngx_int_t
1524 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1525 ngx_uint_t offset)
1526 {
1527 ngx_table_elt_t **ph;
1528
1529 ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1530
1531 if (*ph == NULL) {
1532 *ph = h;
1533 return NGX_OK;
1534 }
1535
1536 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1537 "client sent duplicate header line: \"%V: %V\", "
1538 "previous value: \"%V: %V\"",
1539 &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1540
1541 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1542
1543 return NGX_ERROR;
1544 }
1545
1546
1547 static ngx_int_t
1548 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1549 ngx_uint_t offset)
1550 {
1551 ngx_int_t rc;
1552 ngx_str_t host;
1553
1554 if (r->headers_in.host == NULL) {
1555 r->headers_in.host = h;
1556 }
1557
1558 host = h->value;
1559
1560 rc = ngx_http_validate_host(&host, r->pool, 0);
1561
1562 if (rc == NGX_DECLINED) {
1563 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1564 "client sent invalid host header");
1565 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1566 return NGX_ERROR;
1567 }
1568
1569 if (rc == NGX_ERROR) {
1570 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1571 return NGX_ERROR;
1572 }
1573
1574 if (r->headers_in.server.len) {
1575 return NGX_OK;
1576 }
1577
1578 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1579 return NGX_ERROR;
1580 }
1581
1582 r->headers_in.server = host;
1583
1584 return NGX_OK;
1585 }
1586
1587
1588 static ngx_int_t
1589 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1590 ngx_uint_t offset)
1591 {
1592 if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1593 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1594
1595 } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1596 r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1597 }
1598
1599 return NGX_OK;
1600 }
1601
1602
1603 static ngx_int_t
1604 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1605 ngx_uint_t offset)
1606 {
1607 u_char *user_agent, *msie;
1608
1609 if (r->headers_in.user_agent) {
1610 return NGX_OK;
1611 }
1612
1613 r->headers_in.user_agent = h;
1614
1615 /* check some widespread browsers while the header is in CPU cache */
1616
1617 user_agent = h->value.data;
1618
1619 msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1620
1621 if (msie && msie + 7 < user_agent + h->value.len) {
1622
1623 r->headers_in.msie = 1;
1624
1625 if (msie[6] == '.') {
1626
1627 switch (msie[5]) {
1628 case '4':
1629 case '5':
1630 r->headers_in.msie6 = 1;
1631 break;
1632 case '6':
1633 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1634 r->headers_in.msie6 = 1;
1635 }
1636 break;
1637 }
1638 }
1639
1640 #if 0
1641 /* MSIE ignores the SSL "close notify" alert */
1642 if (c->ssl) {
1643 c->ssl->no_send_shutdown = 1;
1644 }
1645 #endif
1646 }
1647
1648 if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1649 r->headers_in.opera = 1;
1650 r->headers_in.msie = 0;
1651 r->headers_in.msie6 = 0;
1652 }
1653
1654 if (!r->headers_in.msie && !r->headers_in.opera) {
1655
1656 if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1657 r->headers_in.gecko = 1;
1658
1659 } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1660 r->headers_in.chrome = 1;
1661
1662 } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1663 && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1664 {
1665 r->headers_in.safari = 1;
1666
1667 } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1668 r->headers_in.konqueror = 1;
1669 }
1670 }
1671
1672 return NGX_OK;
1673 }
1674
1675
1676 static ngx_int_t
1677 ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
1678 ngx_uint_t offset)
1679 {
1680 ngx_array_t *headers;
1681 ngx_table_elt_t **ph;
1682
1683 headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
1684
1685 if (headers->elts == NULL) {
1686 if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
1687 != NGX_OK)
1688 {
1689 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1690 return NGX_ERROR;
1691 }
1692 }
1693
1694 ph = ngx_array_push(headers);
1695 if (ph == NULL) {
1696 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1697 return NGX_ERROR;
1698 }
1699
1700 *ph = h;
1701 return NGX_OK;
1702 }
1703
1704
1705 ngx_int_t
1706 ngx_http_process_request_header(ngx_http_request_t *r)
1707 {
1708 if (r->headers_in.server.len == 0
1709 && ngx_http_set_virtual_server(r, &r->headers_in.server)
1710 == NGX_ERROR)
1711 {
1712 return NGX_ERROR;
1713 }
1714
1715 if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1716 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1717 "client sent HTTP/1.1 request without \"Host\" header");
1718 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1719 return NGX_ERROR;
1720 }
1721
1722 if (r->headers_in.content_length) {
1723 r->headers_in.content_length_n =
1724 ngx_atoof(r->headers_in.content_length->value.data,
1725 r->headers_in.content_length->value.len);
1726
1727 if (r->headers_in.content_length_n == NGX_ERROR) {
1728 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1729 "client sent invalid \"Content-Length\" header");
1730 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1731 return NGX_ERROR;
1732 }
1733 }
1734
1735 if (r->method & NGX_HTTP_TRACE) {
1736 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1737 "client sent TRACE method");
1738 ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1739 return NGX_ERROR;
1740 }
1741
1742 if (r->headers_in.transfer_encoding) {
1743 if (r->headers_in.transfer_encoding->value.len == 7
1744 && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1745 (u_char *) "chunked", 7) == 0)
1746 {
1747 r->headers_in.content_length = NULL;
1748 r->headers_in.content_length_n = -1;
1749 r->headers_in.chunked = 1;
1750
1751 } else if (r->headers_in.transfer_encoding->value.len != 8
1752 || ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1753 (u_char *) "identity", 8) != 0)
1754 {
1755 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1756 "client sent unknown \"Transfer-Encoding\": \"%V\"",
1757 &r->headers_in.transfer_encoding->value);
1758 ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED);
1759 return NGX_ERROR;
1760 }
1761 }
1762
1763 if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1764 if (r->headers_in.keep_alive) {
1765 r->headers_in.keep_alive_n =
1766 ngx_atotm(r->headers_in.keep_alive->value.data,
1767 r->headers_in.keep_alive->value.len);
1768 }
1769 }
1770
1771 return NGX_OK;
1772 }
1773
1774
1775 void
1776 ngx_http_process_request(ngx_http_request_t *r)
1777 {
1778 ngx_connection_t *c;
1779
1780 c = r->connection;
1781
1782 #if (NGX_HTTP_SSL)
1783
1784 if (r->http_connection->ssl) {
1785 long rc;
1786 X509 *cert;
1787 ngx_http_ssl_srv_conf_t *sscf;
1788
1789 if (c->ssl == NULL) {
1790 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1791 "client sent plain HTTP request to HTTPS port");
1792 ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1793 return;
1794 }
1795
1796 sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1797
1798 if (sscf->verify) {
1799 rc = SSL_get_verify_result(c->ssl->connection);
1800
1801 if (rc != X509_V_OK
1802 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
1803 {
1804 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1805 "client SSL certificate verify error: (%l:%s)",
1806 rc, X509_verify_cert_error_string(rc));
1807
1808 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1809 (SSL_get0_session(c->ssl->connection)));
1810
1811 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1812 return;
1813 }
1814
1815 if (sscf->verify == 1) {
1816 cert = SSL_get_peer_certificate(c->ssl->connection);
1817
1818 if (cert == NULL) {
1819 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1820 "client sent no required SSL certificate");
1821
1822 ngx_ssl_remove_cached_session(sscf->ssl.ctx,
1823 (SSL_get0_session(c->ssl->connection)));
1824
1825 ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1826 return;
1827 }
1828
1829 X509_free(cert);
1830 }
1831 }
1832 }
1833
1834 #endif
1835
1836 if (c->read->timer_set) {
1837 ngx_del_timer(c->read);
1838 }
1839
1840 #if (NGX_STAT_STUB)
1841 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
1842 r->stat_reading = 0;
1843 (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
1844 r->stat_writing = 1;
1845 #endif
1846
1847 c->read->handler = ngx_http_request_handler;
1848 c->write->handler = ngx_http_request_handler;
1849 r->read_event_handler = ngx_http_block_reading;
1850
1851 ngx_http_handler(r);
1852
1853 ngx_http_run_posted_requests(c);
1854 }
1855
1856
1857 static ngx_int_t
1858 ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
1859 {
1860 u_char *h, ch;
1861 size_t i, dot_pos, host_len;
1862
1863 enum {
1864 sw_usual = 0,
1865 sw_literal,
1866 sw_rest
1867 } state;
1868
1869 dot_pos = host->len;
1870 host_len = host->len;
1871
1872 h = host->data;
1873
1874 state = sw_usual;
1875
1876 for (i = 0; i < host->len; i++) {
1877 ch = h[i];
1878
1879 switch (ch) {
1880
1881 case '.':
1882 if (dot_pos == i - 1) {
1883 return NGX_DECLINED;
1884 }
1885 dot_pos = i;
1886 break;
1887
1888 case ':':
1889 if (state == sw_usual) {
1890 host_len = i;
1891 state = sw_rest;
1892 }
1893 break;
1894
1895 case '[':
1896 if (i == 0) {
1897 state = sw_literal;
1898 }
1899 break;
1900
1901 case ']':
1902 if (state == sw_literal) {
1903 host_len = i + 1;
1904 state = sw_rest;
1905 }
1906 break;
1907
1908 case '\0':
1909 return NGX_DECLINED;
1910
1911 default:
1912
1913 if (ngx_path_separator(ch)) {
1914 return NGX_DECLINED;
1915 }
1916
1917 if (ch >= 'A' && ch <= 'Z') {
1918 alloc = 1;
1919 }
1920
1921 break;
1922 }
1923 }
1924
1925 if (dot_pos == host_len - 1) {
1926 host_len--;
1927 }
1928
1929 if (host_len == 0) {
1930 return NGX_DECLINED;
1931 }
1932
1933 if (alloc) {
1934 host->data = ngx_pnalloc(pool, host_len);
1935 if (host->data == NULL) {
1936 return NGX_ERROR;
1937 }
1938
1939 ngx_strlow(host->data, h, host_len);
1940 }
1941
1942 host->len = host_len;
1943
1944 return NGX_OK;
1945 }
1946
1947
1948 static ngx_int_t
1949 ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
1950 {
1951 ngx_int_t rc;
1952 ngx_http_connection_t *hc;
1953 ngx_http_core_loc_conf_t *clcf;
1954 ngx_http_core_srv_conf_t *cscf;
1955
1956 hc = r->http_connection;
1957
1958 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1959
1960 if (hc->ssl_servername) {
1961 if (hc->ssl_servername->len == host->len
1962 && ngx_strncmp(hc->ssl_servername->data,
1963 host->data, host->len) == 0)
1964 {
1965 #if (NGX_PCRE)
1966 if (hc->ssl_servername_regex
1967 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
1968 hc->ssl_servername) != NGX_OK)
1969 {
1970 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1971 return NGX_ERROR;
1972 }
1973 #endif
1974 return NGX_OK;
1975 }
1976 }
1977
1978 #endif
1979
1980 rc = ngx_http_find_virtual_server(r->connection,
1981 hc->addr_conf->virtual_names,
1982 host, r, &cscf);
1983
1984 if (rc == NGX_ERROR) {
1985 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1986 return NGX_ERROR;
1987 }
1988
1989 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
1990
1991 if (hc->ssl_servername) {
1992 ngx_http_ssl_srv_conf_t *sscf;
1993
1994 if (rc == NGX_DECLINED) {
1995 cscf = hc->addr_conf->default_server;
1996 rc = NGX_OK;
1997 }
1998
1999 sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
2000
2001 if (sscf->verify) {
2002 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2003 "client attempted to request the server name "
2004 "different from that one was negotiated");
2005 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
2006 return NGX_ERROR;
2007 }
2008 }
2009
2010 #endif
2011
2012 if (rc == NGX_DECLINED) {
2013 return NGX_OK;
2014 }
2015
2016 r->srv_conf = cscf->ctx->srv_conf;
2017 r->loc_conf = cscf->ctx->loc_conf;
2018
2019 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2020
2021 ngx_http_set_connection_log(r->connection, clcf->error_log);
2022
2023 return NGX_OK;
2024 }
2025
2026
2027 static ngx_int_t
2028 ngx_http_find_virtual_server(ngx_connection_t *c,
2029 ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
2030 ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
2031 {
2032 ngx_http_core_srv_conf_t *cscf;
2033
2034 if (virtual_names == NULL) {
2035 return NGX_DECLINED;
2036 }
2037
2038 cscf = ngx_hash_find_combined(&virtual_names->names,
2039 ngx_hash_key(host->data, host->len),
2040 host->data, host->len);
2041
2042 if (cscf) {
2043 *cscfp = cscf;
2044 return NGX_OK;
2045 }
2046
2047 #if (NGX_PCRE)
2048
2049 if (host->len && virtual_names->nregex) {
2050 ngx_int_t n;
2051 ngx_uint_t i;
2052 ngx_http_server_name_t *sn;
2053
2054 sn = virtual_names->regex;
2055
2056 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
2057
2058 if (r == NULL) {
2059 ngx_http_connection_t *hc;
2060
2061 for (i = 0; i < virtual_names->nregex; i++) {
2062
2063 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
2064
2065 if (n == NGX_REGEX_NO_MATCHED) {
2066 continue;
2067 }
2068
2069 if (n >= 0) {
2070 hc = c->data;
2071 hc->ssl_servername_regex = sn[i].regex;
2072
2073 *cscfp = sn[i].server;
2074 return NGX_OK;
2075 }
2076
2077 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2078 ngx_regex_exec_n " failed: %i "
2079 "on \"%V\" using \"%V\"",
2080 n, host, &sn[i].regex->name);
2081
2082 return NGX_ERROR;
2083 }
2084
2085 return NGX_DECLINED;
2086 }
2087
2088 #endif /* SSL_CTRL_SET_TLSEXT_HOSTNAME */
2089
2090 for (i = 0; i < virtual_names->nregex; i++) {
2091
2092 n = ngx_http_regex_exec(r, sn[i].regex, host);
2093
2094 if (n == NGX_DECLINED) {
2095 continue;
2096 }
2097
2098 if (n == NGX_OK) {
2099 *cscfp = sn[i].server;
2100 return NGX_OK;
2101 }
2102
2103 return NGX_ERROR;
2104 }
2105 }
2106
2107 #endif /* NGX_PCRE */
2108
2109 return NGX_DECLINED;
2110 }
2111
2112
2113 static void
2114 ngx_http_request_handler(ngx_event_t *ev)
2115 {
2116 ngx_connection_t *c;
2117 ngx_http_request_t *r;
2118 ngx_http_log_ctx_t *ctx;
2119
2120 c = ev->data;
2121 r = c->data;
2122
2123 ctx = c->log->data;
2124 ctx->current_request = r;
2125
2126 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2127 "http run request: \"%V?%V\"", &r->uri, &r->args);
2128
2129 if (ev->write) {
2130 r->write_event_handler(r);
2131
2132 } else {
2133 r->read_event_handler(r);
2134 }
2135
2136 ngx_http_run_posted_requests(c);
2137 }
2138
2139
2140 void
2141 ngx_http_run_posted_requests(ngx_connection_t *c)
2142 {
2143 ngx_http_request_t *r;
2144 ngx_http_log_ctx_t *ctx;
2145 ngx_http_posted_request_t *pr;
2146
2147 for ( ;; ) {
2148
2149 if (c->destroyed) {
2150 return;
2151 }
2152
2153 r = c->data;
2154 pr = r->main->posted_requests;
2155
2156 if (pr == NULL) {
2157 return;
2158 }
2159
2160 r->main->posted_requests = pr->next;
2161
2162 r = pr->request;
2163
2164 ctx = c->log->data;
2165 ctx->current_request = r;
2166
2167 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2168 "http posted request: \"%V?%V\"", &r->uri, &r->args);
2169
2170 r->write_event_handler(r);
2171 }
2172 }
2173
2174
2175 ngx_int_t
2176 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
2177 {
2178 ngx_http_posted_request_t **p;
2179
2180 if (pr == NULL) {
2181 pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
2182 if (pr == NULL) {
2183 return NGX_ERROR;
2184 }
2185 }
2186
2187 pr->request = r;
2188 pr->next = NULL;
2189
2190 for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
2191
2192 *p = pr;
2193
2194 return NGX_OK;
2195 }
2196
2197
2198 void
2199 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2200 {
2201 ngx_connection_t *c;
2202 ngx_http_request_t *pr;
2203 ngx_http_core_loc_conf_t *clcf;
2204
2205 c = r->connection;
2206
2207 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
2208 "http finalize request: %d, \"%V?%V\" a:%d, c:%d",
2209 rc, &r->uri, &r->args, r == c->data, r->main->count);
2210
2211 if (rc == NGX_DONE) {
2212 ngx_http_finalize_connection(r);
2213 return;
2214 }
2215
2216 if (rc == NGX_OK && r->filter_finalize) {
2217 c->error = 1;
2218 }
2219
2220 if (rc == NGX_DECLINED) {
2221 r->content_handler = NULL;
2222 r->write_event_handler = ngx_http_core_run_phases;
2223 ngx_http_core_run_phases(r);
2224 return;
2225 }
2226
2227 if (r != r->main && r->post_subrequest) {
2228 rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
2229 }
2230
2231 if (rc == NGX_ERROR
2232 || rc == NGX_HTTP_REQUEST_TIME_OUT
2233 || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
2234 || c->error)
2235 {
2236 if (ngx_http_post_action(r) == NGX_OK) {
2237 return;
2238 }
2239
2240 if (r->main->blocked) {
2241 r->write_event_handler = ngx_http_request_finalizer;
2242 }
2243
2244 ngx_http_terminate_request(r, rc);
2245 return;
2246 }
2247
2248 if (rc >= NGX_HTTP_SPECIAL_RESPONSE
2249 || rc == NGX_HTTP_CREATED
2250 || rc == NGX_HTTP_NO_CONTENT)
2251 {
2252 if (rc == NGX_HTTP_CLOSE) {
2253 ngx_http_terminate_request(r, rc);
2254 return;
2255 }
2256
2257 if (r == r->main) {
2258 if (c->read->timer_set) {
2259 ngx_del_timer(c->read);
2260 }
2261
2262 if (c->write->timer_set) {
2263 ngx_del_timer(c->write);
2264 }
2265 }
2266
2267 c->read->handler = ngx_http_request_handler;
2268 c->write->handler = ngx_http_request_handler;
2269
2270 ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
2271 return;
2272 }
2273
2274 if (r != r->main) {
2275
2276 if (r->buffered || r->postponed) {
2277
2278 if (ngx_http_set_write_handler(r) != NGX_OK) {
2279 ngx_http_terminate_request(r, 0);
2280 }
2281
2282 return;
2283 }
2284
2285 pr = r->parent;
2286
2287 if (r == c->data) {
2288
2289 r->main->count--;
2290 r->main->subrequests++;
2291
2292 if (!r->logged) {
2293
2294 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2295
2296 if (clcf->log_subrequest) {
2297 ngx_http_log_request(r);
2298 }
2299
2300 r->logged = 1;
2301
2302 } else {
2303 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2304 "subrequest: \"%V?%V\" logged again",
2305 &r->uri, &r->args);
2306 }
2307
2308 r->done = 1;
2309
2310 if (pr->postponed && pr->postponed->request == r) {
2311 pr->postponed = pr->postponed->next;
2312 }
2313
2314 c->data = pr;
2315
2316 } else {
2317
2318 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2319 "http finalize non-active request: \"%V?%V\"",
2320 &r->uri, &r->args);
2321
2322 r->write_event_handler = ngx_http_request_finalizer;
2323
2324 if (r->waited) {
2325 r->done = 1;
2326 }
2327 }
2328
2329 if (ngx_http_post_request(pr, NULL) != NGX_OK) {
2330 r->main->count++;
2331 ngx_http_terminate_request(r, 0);
2332 return;
2333 }
2334
2335 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2336 "http wake parent request: \"%V?%V\"",
2337 &pr->uri, &pr->args);
2338
2339 return;
2340 }
2341
2342 if (r->buffered || c->buffered || r->postponed || r->blocked) {
2343
2344 if (ngx_http_set_write_handler(r) != NGX_OK) {
2345 ngx_http_terminate_request(r, 0);
2346 }
2347
2348 return;
2349 }
2350
2351 if (r != c->data) {
2352 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2353 "http finalize non-active request: \"%V?%V\"",
2354 &r->uri, &r->args);
2355 return;
2356 }
2357
2358 r->done = 1;
2359 r->write_event_handler = ngx_http_request_empty_handler;
2360
2361 if (!r->post_action) {
2362 r->request_complete = 1;
2363 }
2364
2365 if (ngx_http_post_action(r) == NGX_OK) {
2366 return;
2367 }
2368
2369 if (c->read->timer_set) {
2370 ngx_del_timer(c->read);
2371 }
2372
2373 if (c->write->timer_set) {
2374 c->write->delayed = 0;
2375 ngx_del_timer(c->write);
2376 }
2377
2378 if (c->read->eof) {
2379 ngx_http_close_request(r, 0);
2380 return;
2381 }
2382
2383 ngx_http_finalize_connection(r);
2384 }
2385
2386
2387 static void
2388 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2389 {
2390 ngx_http_cleanup_t *cln;
2391 ngx_http_request_t *mr;
2392 ngx_http_ephemeral_t *e;
2393
2394 mr = r->main;
2395
2396 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2397 "http terminate request count:%d", mr->count);
2398
2399 if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
2400 mr->headers_out.status = rc;
2401 }
2402
2403 cln = mr->cleanup;
2404 mr->cleanup = NULL;
2405
2406 while (cln) {
2407 if (cln->handler) {
2408 cln->handler(cln->data);
2409 }
2410
2411 cln = cln->next;
2412 }
2413
2414 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2415 "http terminate cleanup count:%d blk:%d",
2416 mr->count, mr->blocked);
2417
2418 if (mr->write_event_handler) {
2419
2420 if (mr->blocked) {
2421 return;
2422 }
2423
2424 e = ngx_http_ephemeral(mr);
2425 mr->posted_requests = NULL;
2426 mr->write_event_handler = ngx_http_terminate_handler;
2427 (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2428 return;
2429 }
2430
2431 ngx_http_close_request(mr, rc);
2432 }
2433
2434
2435 static void
2436 ngx_http_terminate_handler(ngx_http_request_t *r)
2437 {
2438 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2439 "http terminate handler count:%d", r->count);
2440
2441 r->count = 1;
2442
2443 ngx_http_close_request(r, 0);
2444 }
2445
2446
2447 static void
2448 ngx_http_finalize_connection(ngx_http_request_t *r)
2449 {
2450 ngx_http_core_loc_conf_t *clcf;
2451
2452 #if (NGX_HTTP_SPDY)
2453 if (r->spdy_stream) {
2454 ngx_http_close_request(r, 0);
2455 return;
2456 }
2457 #endif
2458
2459 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2460
2461 if (r->main->count != 1) {
2462
2463 if (r->discard_body) {
2464 r->read_event_handler = ngx_http_discarded_request_body_handler;
2465 ngx_add_timer(r->connection->read, clcf->lingering_timeout);
2466
2467 if (r->lingering_time == 0) {
2468 r->lingering_time = ngx_time()
2469 + (time_t) (clcf->lingering_time / 1000);
2470 }
2471 }
2472
2473 ngx_http_close_request(r, 0);
2474 return;
2475 }
2476
2477 if (!ngx_terminate
2478 && !ngx_exiting
2479 && r->keepalive
2480 && clcf->keepalive_timeout > 0)
2481 {
2482 ngx_http_set_keepalive(r);
2483 return;
2484 }
2485
2486 if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
2487 || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
2488 && (r->lingering_close
2489 || r->header_in->pos < r->header_in->last
2490 || r->connection->read->ready)))
2491 {
2492 ngx_http_set_lingering_close(r);
2493 return;
2494 }
2495
2496 ngx_http_close_request(r, 0);
2497 }
2498
2499
2500 static ngx_int_t
2501 ngx_http_set_write_handler(ngx_http_request_t *r)
2502 {
2503 ngx_event_t *wev;
2504 ngx_http_core_loc_conf_t *clcf;
2505
2506 r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2507
2508 r->read_event_handler = r->discard_body ?
2509 ngx_http_discarded_request_body_handler:
2510 ngx_http_test_reading;
2511 r->write_event_handler = ngx_http_writer;
2512
2513 #if (NGX_HTTP_SPDY)
2514 if (r->spdy_stream) {
2515 return NGX_OK;
2516 }
2517 #endif
2518
2519 wev = r->connection->write;
2520
2521 if (wev->ready && wev->delayed) {
2522 return NGX_OK;
2523 }
2524
2525 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2526 if (!wev->delayed) {
2527 ngx_add_timer(wev, clcf->send_timeout);
2528 }
2529
2530 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2531 ngx_http_close_request(r, 0);
2532 return NGX_ERROR;
2533 }
2534
2535 return NGX_OK;
2536 }
2537
2538
2539 static void
2540 ngx_http_writer(ngx_http_request_t *r)
2541 {
2542 int rc;
2543 ngx_event_t *wev;
2544 ngx_connection_t *c;
2545 ngx_http_core_loc_conf_t *clcf;
2546
2547 c = r->connection;
2548 wev = c->write;
2549
2550 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2551 "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2552
2553 clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2554
2555 if (wev->timedout) {
2556 if (!wev->delayed) {
2557 ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2558 "client timed out");
2559 c->timedout = 1;
2560
2561 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2562 return;
2563 }
2564
2565 wev->timedout = 0;
2566 wev->delayed = 0;
2567
2568 if (!wev->ready) {
2569 ngx_add_timer(wev, clcf->send_timeout);
2570
2571 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2572 ngx_http_close_request(r, 0);
2573 }
2574
2575 return;
2576 }
2577
2578 }
2579
2580 if (wev->delayed || r->aio) {
2581 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2582 "http writer delayed");
2583
2584 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2585 ngx_http_close_request(r, 0);
2586 }
2587
2588 return;
2589 }
2590
2591 rc = ngx_http_output_filter(r, NULL);
2592
2593 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2594 "http writer output filter: %d, \"%V?%V\"",
2595 rc, &r->uri, &r->args);
2596
2597 if (rc == NGX_ERROR) {
2598 ngx_http_finalize_request(r, rc);
2599 return;
2600 }
2601
2602 if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2603
2604 if (!wev->delayed) {
2605 ngx_add_timer(wev, clcf->send_timeout);
2606 }
2607
2608 if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2609 ngx_http_close_request(r, 0);
2610 }
2611
2612 return;
2613 }
2614
2615 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2616 "http writer done: \"%V?%V\"", &r->uri, &r->args);
2617
2618 r->write_event_handler = ngx_http_request_empty_handler;
2619
2620 ngx_http_finalize_request(r, rc);
2621 }
2622
2623
2624 static void
2625 ngx_http_request_finalizer(ngx_http_request_t *r)
2626 {
2627 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2628 "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2629
2630 ngx_http_finalize_request(r, 0);
2631 }
2632
2633
2634 void
2635 ngx_http_block_reading(ngx_http_request_t *r)
2636 {
2637 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2638 "http reading blocked");
2639
2640 /* aio does not call this handler */
2641
2642 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2643 && r->connection->read->active)
2644 {
2645 if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2646 ngx_http_close_request(r, 0);
2647 }
2648 }
2649 }
2650
2651
2652 void
2653 ngx_http_test_reading(ngx_http_request_t *r)
2654 {
2655 int n;
2656 char buf[1];
2657 ngx_err_t err;
2658 ngx_event_t *rev;
2659 ngx_connection_t *c;
2660
2661 c = r->connection;
2662 rev = c->read;
2663
2664 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2665
2666 #if (NGX_HTTP_SPDY)
2667
2668 if (r->spdy_stream) {
2669 if (c->error) {
2670 err = 0;
2671 goto closed;
2672 }
2673
2674 return;
2675 }
2676
2677 #endif
2678
2679 #if (NGX_HAVE_KQUEUE)
2680
2681 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2682
2683 if (!rev->pending_eof) {
2684 return;
2685 }
2686
2687 rev->eof = 1;
2688 c->error = 1;
2689 err = rev->kq_errno;
2690
2691 goto closed;
2692 }
2693
2694 #endif
2695
2696 n = recv(c->fd, buf, 1, MSG_PEEK);
2697
2698 if (n == 0) {
2699 rev->eof = 1;
2700 c->error = 1;
2701 err = 0;
2702
2703 goto closed;
2704
2705 } else if (n == -1) {
2706 err = ngx_socket_errno;
2707
2708 if (err != NGX_EAGAIN) {
2709 rev->eof = 1;
2710 c->error = 1;
2711
2712 goto closed;
2713 }
2714 }
2715
2716 /* aio does not call this handler */
2717
2718 if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2719
2720 if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
2721 ngx_http_close_request(r, 0);
2722 }
2723 }
2724
2725 return;
2726
2727 closed:
2728
2729 if (err) {
2730 rev->error = 1;
2731 }
2732
2733 ngx_log_error(NGX_LOG_INFO, c->log, err,
2734 "client prematurely closed connection");
2735
2736 ngx_http_finalize_request(r, 0);
2737 }
2738
2739
2740 static void
2741 ngx_http_set_keepalive(ngx_http_request_t *r)
2742 {
2743 int tcp_nodelay;
2744 ngx_int_t i;
2745 ngx_buf_t *b, *f;
2746 ngx_event_t *rev, *wev;
2747 ngx_connection_t *c;
2748 ngx_http_connection_t *hc;
2749 ngx_http_core_srv_conf_t *cscf;
2750 ngx_http_core_loc_conf_t *clcf;
2751
2752 c = r->connection;
2753 rev = c->read;
2754
2755 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2756
2757 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
2758
2759 if (r->discard_body) {
2760 r->write_event_handler = ngx_http_request_empty_handler;
2761 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2762 ngx_add_timer(rev, clcf->lingering_timeout);
2763 return;
2764 }
2765
2766 c->log->action = "closing request";
2767
2768 hc = r->http_connection;
2769 b = r->header_in;
2770
2771 if (b->pos < b->last) {
2772
2773 /* the pipelined request */
2774
2775 if (b != c->buffer) {
2776
2777 /*
2778 * If the large header buffers were allocated while the previous
2779 * request processing then we do not use c->buffer for
2780 * the pipelined request (see ngx_http_create_request()).
2781 *
2782 * Now we would move the large header buffers to the free list.
2783 */
2784
2785 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2786
2787 if (hc->free == NULL) {
2788 hc->free = ngx_palloc(c->pool,
2789 cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
2790
2791 if (hc->free == NULL) {
2792 ngx_http_close_request(r, 0);
2793 return;
2794 }
2795 }
2796
2797 for (i = 0; i < hc->nbusy - 1; i++) {
2798 f = hc->busy[i];
2799 hc->free[hc->nfree++] = f;
2800 f->pos = f->start;
2801 f->last = f->start;
2802 }
2803
2804 hc->busy[0] = b;
2805 hc->nbusy = 1;
2806 }
2807 }
2808
2809 /* guard against recursive call from ngx_http_finalize_connection() */
2810 r->keepalive = 0;
2811
2812 ngx_http_free_request(r, 0);
2813
2814 c->data = hc;
2815
2816 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2817 ngx_http_close_connection(c);
2818 return;
2819 }
2820
2821 wev = c->write;
2822 wev->handler = ngx_http_empty_handler;
2823
2824 if (b->pos < b->last) {
2825
2826 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
2827
2828 c->log->action = "reading client pipelined request line";
2829
2830 r = ngx_http_create_request(c);
2831 if (r == NULL) {
2832 ngx_http_close_connection(c);
2833 return;
2834 }
2835
2836 r->pipeline = 1;
2837
2838 c->data = r;
2839
2840 c->sent = 0;
2841 c->destroyed = 0;
2842
2843 if (rev->timer_set) {
2844 ngx_del_timer(rev);
2845 }
2846
2847 rev->handler = ngx_http_process_request_line;
2848 ngx_post_event(rev, &ngx_posted_events);
2849 return;
2850 }
2851
2852 /*
2853 * To keep a memory footprint as small as possible for an idle keepalive
2854 * connection we try to free c->buffer's memory if it was allocated outside
2855 * the c->pool. The large header buffers are always allocated outside the
2856 * c->pool and are freed too.
2857 */
2858
2859 b = c->buffer;
2860
2861 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
2862
2863 /*
2864 * the special note for ngx_http_keepalive_handler() that
2865 * c->buffer's memory was freed
2866 */
2867
2868 b->pos = NULL;
2869
2870 } else {
2871 b->pos = b->start;
2872 b->last = b->start;
2873 }
2874
2875 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p %d",
2876 hc->free, hc->nfree);
2877
2878 if (hc->free) {
2879 for (i = 0; i < hc->nfree; i++) {
2880 ngx_pfree(c->pool, hc->free[i]->start);
2881 hc->free[i] = NULL;
2882 }
2883
2884 hc->nfree = 0;
2885 }
2886
2887 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %d",
2888 hc->busy, hc->nbusy);
2889
2890 if (hc->busy) {
2891 for (i = 0; i < hc->nbusy; i++) {
2892 ngx_pfree(c->pool, hc->busy[i]->start);
2893 hc->busy[i] = NULL;
2894 }
2895
2896 hc->nbusy = 0;
2897 }
2898
2899 #if (NGX_HTTP_SSL)
2900 if (c->ssl) {
2901 ngx_ssl_free_buffer(c);
2902 }
2903 #endif
2904
2905 rev->handler = ngx_http_keepalive_handler;
2906
2907 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
2908 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
2909 ngx_http_close_connection(c);
2910 return;
2911 }
2912 }
2913
2914 c->log->action = "keepalive";
2915
2916 if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
2917 if (ngx_tcp_push(c->fd) == -1) {
2918 ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
2919 ngx_http_close_connection(c);
2920 return;
2921 }
2922
2923 c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
2924 tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
2925
2926 } else {
2927 tcp_nodelay = 1;
2928 }
2929
2930 if (tcp_nodelay
2931 && clcf->tcp_nodelay
2932 && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
2933 {
2934 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
2935
2936 if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
2937 (const void *) &tcp_nodelay, sizeof(int))
2938 == -1)
2939 {
2940 #if (NGX_SOLARIS)
2941 /* Solaris returns EINVAL if a socket has been shut down */
2942 c->log_error = NGX_ERROR_IGNORE_EINVAL;
2943 #endif
2944
2945 ngx_connection_error(c, ngx_socket_errno,
2946 "setsockopt(TCP_NODELAY) failed");
2947
2948 c->log_error = NGX_ERROR_INFO;
2949 ngx_http_close_connection(c);
2950 return;
2951 }
2952
2953 c->tcp_nodelay = NGX_TCP_NODELAY_SET;
2954 }
2955
2956 #if 0
2957 /* if ngx_http_request_t was freed then we need some other place */
2958 r->http_state = NGX_HTTP_KEEPALIVE_STATE;
2959 #endif
2960
2961 c->idle = 1;
2962 ngx_reusable_connection(c, 1);
2963
2964 ngx_add_timer(rev, clcf->keepalive_timeout);
2965
2966 if (rev->ready) {
2967 ngx_post_event(rev, &ngx_posted_events);
2968 }
2969 }
2970
2971
2972 static void
2973 ngx_http_keepalive_handler(ngx_event_t *rev)
2974 {
2975 size_t size;
2976 ssize_t n;
2977 ngx_buf_t *b;
2978 ngx_connection_t *c;
2979
2980 c = rev->data;
2981
2982 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
2983
2984 if (rev->timedout || c->close) {
2985 ngx_http_close_connection(c);
2986 return;
2987 }
2988
2989 #if (NGX_HAVE_KQUEUE)
2990
2991 if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2992 if (rev->pending_eof) {
2993 c->log->handler = NULL;
2994 ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
2995 "kevent() reported that client %V closed "
2996 "keepalive connection", &c->addr_text);
2997 #if (NGX_HTTP_SSL)
2998 if (c->ssl) {
2999 c->ssl->no_send_shutdown = 1;
3000 }
3001 #endif
3002 ngx_http_close_connection(c);
3003 return;
3004 }
3005 }
3006
3007 #endif
3008
3009 b = c->buffer;
3010 size = b->end - b->start;
3011
3012 if (b->pos == NULL) {
3013
3014 /*
3015 * The c->buffer's memory was freed by ngx_http_set_keepalive().
3016 * However, the c->buffer->start and c->buffer->end were not changed
3017 * to keep the buffer size.
3018 */
3019
3020 b->pos = ngx_palloc(c->pool, size);
3021 if (b->pos == NULL) {
3022 ngx_http_close_connection(c);
3023 return;
3024 }
3025
3026 b->start = b->pos;
3027 b->last = b->pos;
3028 b->end = b->pos + size;
3029 }
3030
3031 /*
3032 * MSIE closes a keepalive connection with RST flag
3033 * so we ignore ECONNRESET here.
3034 */
3035
3036 c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
3037 ngx_set_socket_errno(0);
3038
3039 n = c->recv(c, b->last, size);
3040 c->log_error = NGX_ERROR_INFO;
3041
3042 if (n == NGX_AGAIN) {
3043 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3044 ngx_http_close_connection(c);
3045 return;
3046 }
3047
3048 /*
3049 * Like ngx_http_set_keepalive() we are trying to not hold
3050 * c->buffer's memory for a keepalive connection.
3051 */
3052
3053 if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3054
3055 /*
3056 * the special note that c->buffer's memory was freed
3057 */
3058
3059 b->pos = NULL;
3060 }
3061
3062 return;
3063 }
3064
3065 if (n == NGX_ERROR) {
3066 ngx_http_close_connection(c);
3067 return;
3068 }
3069
3070 c->log->handler = NULL;
3071
3072 if (n == 0) {
3073 ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
3074 "client %V closed keepalive connection", &c->addr_text);
3075 ngx_http_close_connection(c);
3076 return;
3077 }
3078
3079 b->last += n;
3080
3081 c->log->handler = ngx_http_log_error;
3082 c->log->action = "reading client request line";
3083
3084 c->idle = 0;
3085 ngx_reusable_connection(c, 0);
3086
3087 c->data = ngx_http_create_request(c);
3088 if (c->data == NULL) {
3089 ngx_http_close_connection(c);
3090 return;
3091 }
3092
3093 c->sent = 0;
3094 c->destroyed = 0;
3095
3096 ngx_del_timer(rev);
3097
3098 rev->handler = ngx_http_process_request_line;
3099 ngx_http_process_request_line(rev);
3100 }
3101
3102
3103 static void
3104 ngx_http_set_lingering_close(ngx_http_request_t *r)
3105 {
3106 ngx_event_t *rev, *wev;
3107 ngx_connection_t *c;
3108 ngx_http_core_loc_conf_t *clcf;
3109
3110 c = r->connection;
3111
3112 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3113
3114 rev = c->read;
3115 rev->handler = ngx_http_lingering_close_handler;
3116
3117 r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3118 ngx_add_timer(rev, clcf->lingering_timeout);
3119
3120 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3121 ngx_http_close_request(r, 0);
3122 return;
3123 }
3124
3125 wev = c->write;
3126 wev->handler = ngx_http_empty_handler;
3127
3128 if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3129 if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3130 ngx_http_close_request(r, 0);
3131 return;
3132 }
3133 }
3134
3135 if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
3136 ngx_connection_error(c, ngx_socket_errno,
3137 ngx_shutdown_socket_n " failed");
3138 ngx_http_close_request(r, 0);
3139 return;
3140 }
3141
3142 if (rev->ready) {
3143 ngx_http_lingering_close_handler(rev);
3144 }
3145 }
3146
3147
3148 static void
3149 ngx_http_lingering_close_handler(ngx_event_t *rev)
3150 {
3151 ssize_t n;
3152 ngx_msec_t timer;
3153 ngx_connection_t *c;
3154 ngx_http_request_t *r;
3155 ngx_http_core_loc_conf_t *clcf;
3156 u_char buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
3157
3158 c = rev->data;
3159 r = c->data;
3160
3161 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3162 "http lingering close handler");
3163
3164 if (rev->timedout) {
3165 ngx_http_close_request(r, 0);
3166 return;
3167 }
3168
3169 timer = (ngx_msec_t) (r->lingering_time - ngx_time());
3170 if (timer <= 0) {
3171 ngx_http_close_request(r, 0);
3172 return;
3173 }
3174
3175 do {
3176 n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
3177
3178 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %d", n);
3179
3180 if (n == NGX_ERROR || n == 0) {
3181 ngx_http_close_request(r, 0);
3182 return;
3183 }
3184
3185 } while (rev->ready);
3186
3187 if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3188 ngx_http_close_request(r, 0);
3189 return;
3190 }
3191
3192 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3193
3194 timer *= 1000;
3195
3196 if (timer > clcf->lingering_timeout) {
3197 timer = clcf->lingering_timeout;
3198 }
3199
3200 ngx_add_timer(rev, timer);
3201 }
3202
3203
3204 void
3205 ngx_http_empty_handler(ngx_event_t *wev)
3206 {
3207 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
3208
3209 return;
3210 }
3211
3212
3213 void
3214 ngx_http_request_empty_handler(ngx_http_request_t *r)
3215 {
3216 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3217 "http request empty handler");
3218
3219 return;
3220 }
3221
3222
3223 ngx_int_t
3224 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
3225 {
3226 ngx_buf_t *b;
3227 ngx_chain_t out;
3228
3229 b = ngx_calloc_buf(r->pool);
3230 if (b == NULL) {
3231 return NGX_ERROR;
3232 }
3233
3234 if (flags & NGX_HTTP_LAST) {
3235
3236 if (r == r->main && !r->post_action) {
3237 b->last_buf = 1;
3238
3239 } else {
3240 b->sync = 1;
3241 b->last_in_chain = 1;
3242 }
3243 }
3244
3245 if (flags & NGX_HTTP_FLUSH) {
3246 b->flush = 1;
3247 }
3248
3249 out.buf = b;
3250 out.next = NULL;
3251
3252 return ngx_http_output_filter(r, &out);
3253 }
3254
3255
3256 static ngx_int_t
3257 ngx_http_post_action(ngx_http_request_t *r)
3258 {
3259 ngx_http_core_loc_conf_t *clcf;
3260
3261 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3262
3263 if (clcf->post_action.data == NULL) {
3264 return NGX_DECLINED;
3265 }
3266
3267 if (r->post_action && r->uri_changes == 0) {
3268 return NGX_DECLINED;
3269 }
3270
3271 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3272 "post action: \"%V\"", &clcf->post_action);
3273
3274 r->main->count--;
3275
3276 r->http_version = NGX_HTTP_VERSION_9;
3277 r->header_only = 1;
3278 r->post_action = 1;
3279
3280 r->read_event_handler = ngx_http_block_reading;
3281
3282 if (clcf->post_action.data[0] == '/') {
3283 ngx_http_internal_redirect(r, &clcf->post_action, NULL);
3284
3285 } else {
3286 ngx_http_named_location(r, &clcf->post_action);
3287 }
3288
3289 return NGX_OK;
3290 }
3291
3292
3293 static void
3294 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
3295 {
3296 ngx_connection_t *c;
3297
3298 r = r->main;
3299 c = r->connection;
3300
3301 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3302 "http request count:%d blk:%d", r->count, r->blocked);
3303
3304 if (r->count == 0) {
3305 ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
3306 }
3307
3308 r->count--;
3309
3310 if (r->count || r->blocked) {
3311 return;
3312 }
3313
3314 #if (NGX_HTTP_SPDY)
3315 if (r->spdy_stream) {
3316 ngx_http_spdy_close_stream(r->spdy_stream, rc);
3317 return;
3318 }
3319 #endif
3320
3321 ngx_http_free_request(r, rc);
3322 ngx_http_close_connection(c);
3323 }
3324
3325
3326 void
3327 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3328 {
3329 ngx_log_t *log;
3330 ngx_pool_t *pool;
3331 struct linger linger;
3332 ngx_http_cleanup_t *cln;
3333 ngx_http_log_ctx_t *ctx;
3334 ngx_http_core_loc_conf_t *clcf;
3335
3336 log = r->connection->log;
3337
3338 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
3339
3340 if (r->pool == NULL) {
3341 ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
3342 return;
3343 }
3344
3345 for (cln = r->cleanup; cln; cln = cln->next) {
3346 if (cln->handler) {
3347 cln->handler(cln->data);
3348 }
3349 }
3350
3351 #if (NGX_STAT_STUB)
3352
3353 if (r->stat_reading) {
3354 (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
3355 }
3356
3357 if (r->stat_writing) {
3358 (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
3359 }
3360
3361 #endif
3362
3363 if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
3364 r->headers_out.status = rc;
3365 }
3366
3367 log->action = "logging request";
3368
3369 ngx_http_log_request(r);
3370
3371 log->action = "closing request";
3372
3373 if (r->connection->timedout) {
3374 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3375
3376 if (clcf->reset_timedout_connection) {
3377 linger.l_onoff = 1;
3378 linger.l_linger = 0;
3379
3380 if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
3381 (const void *) &linger, sizeof(struct linger)) == -1)
3382 {
3383 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
3384 "setsockopt(SO_LINGER) failed");
3385 }
3386 }
3387 }
3388
3389 /* the various request strings were allocated from r->pool */
3390 ctx = log->data;
3391 ctx->request = NULL;
3392
3393 r->request_line.len = 0;
3394
3395 r->connection->destroyed = 1;
3396
3397 /*
3398 * Setting r->pool to NULL will increase probability to catch double close
3399 * of request since the request object is allocated from its own pool.
3400 */
3401
3402 pool = r->pool;
3403 r->pool = NULL;
3404
3405 ngx_destroy_pool(pool);
3406 }
3407
3408
3409 static void
3410 ngx_http_log_request(ngx_http_request_t *r)
3411 {
3412 ngx_uint_t i, n;
3413 ngx_http_handler_pt *log_handler;
3414 ngx_http_core_main_conf_t *cmcf;
3415
3416 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3417
3418 log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
3419 n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
3420
3421 for (i = 0; i < n; i++) {
3422 log_handler[i](r);
3423 }
3424 }
3425
3426
3427 void
3428 ngx_http_close_connection(ngx_connection_t *c)
3429 {
3430 ngx_pool_t *pool;
3431
3432 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3433 "close http connection: %d", c->fd);
3434
3435 #if (NGX_HTTP_SSL)
3436
3437 if (c->ssl) {
3438 if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3439 c->ssl->handler = ngx_http_close_connection;
3440 return;
3441 }
3442 }
3443
3444 #endif
3445
3446 #if (NGX_STAT_STUB)
3447 (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
3448 #endif
3449
3450 c->destroyed = 1;
3451
3452 pool = c->pool;
3453
3454 ngx_close_connection(c);
3455
3456 ngx_destroy_pool(pool);
3457 }
3458
3459
3460 static u_char *
3461 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
3462 {
3463 u_char *p;
3464 ngx_http_request_t *r;
3465 ngx_http_log_ctx_t *ctx;
3466
3467 if (log->action) {
3468 p = ngx_snprintf(buf, len, " while %s", log->action);
3469 len -= p - buf;
3470 buf = p;
3471 }
3472
3473 ctx = log->data;
3474
3475 p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3476 len -= p - buf;
3477
3478 r = ctx->request;
3479
3480 if (r) {
3481 return r->log_handler(r, ctx->current_request, p, len);
3482
3483 } else {
3484 p = ngx_snprintf(p, len, ", server: %V",
3485 &ctx->connection->listening->addr_text);
3486 }
3487
3488 return p;
3489 }
3490
3491
3492 static u_char *
3493 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3494 u_char *buf, size_t len)
3495 {
3496 char *uri_separator;
3497 u_char *p;
3498 ngx_http_upstream_t *u;
3499 ngx_http_core_srv_conf_t *cscf;
3500
3501 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3502
3503 p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3504 len -= p - buf;
3505 buf = p;
3506
3507 if (r->request_line.data == NULL && r->request_start) {
3508 for (p = r->request_start; p < r->header_in->last; p++) {
3509 if (*p == CR || *p == LF) {
3510 break;
3511 }
3512 }
3513
3514 r->request_line.len = p - r->request_start;
3515 r->request_line.data = r->request_start;
3516 }
3517
3518 if (r->request_line.len) {
3519 p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3520 len -= p - buf;
3521 buf = p;
3522 }
3523
3524 if (r != sr) {
3525 p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3526 len -= p - buf;
3527 buf = p;
3528 }
3529
3530 u = sr->upstream;
3531
3532 if (u && u->peer.name) {
3533
3534 uri_separator = "";
3535
3536 #if (NGX_HAVE_UNIX_DOMAIN)
3537 if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3538 uri_separator = ":";
3539 }
3540 #endif
3541
3542 p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3543 &u->schema, u->peer.name,
3544 uri_separator, &u->uri);
3545 len -= p - buf;
3546 buf = p;
3547 }
3548
3549 if (r->headers_in.host) {
3550 p = ngx_snprintf(buf, len, ", host: \"%V\"",
3551 &r->headers_in.host->value);
3552 len -= p - buf;
3553 buf = p;
3554 }
3555
3556 if (r->headers_in.referer) {
3557 p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3558 &r->headers_in.referer->value);
3559 buf = p;
3560 }
3561
3562 return buf;
3563 }
3564
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.