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