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