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