Annotation of embedaddon/nginx/src/http/ngx_http_request.c, revision 1.1.1.1
1.1 misho 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: #if (NGX_HTTP_SSL && defined 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: #if (NGX_HTTP_SSL && defined 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: #if (NGX_HTTP_SSL && defined 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 /* NGX_HTTP_SSL && defined 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>