Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_http.h>
0011 
0012 
0013 static void ngx_http_wait_request_handler(ngx_event_t *ev);
0014 static void ngx_http_process_request_line(ngx_event_t *rev);
0015 static void ngx_http_process_request_headers(ngx_event_t *rev);
0016 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
0017 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
0018     ngx_uint_t request_line);
0019 
0020 static ngx_int_t ngx_http_process_header_line(ngx_http_request_t *r,
0021     ngx_table_elt_t *h, ngx_uint_t offset);
0022 static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r,
0023     ngx_table_elt_t *h, ngx_uint_t offset);
0024 static ngx_int_t ngx_http_process_multi_header_lines(ngx_http_request_t *r,
0025     ngx_table_elt_t *h, ngx_uint_t offset);
0026 static ngx_int_t ngx_http_process_host(ngx_http_request_t *r,
0027     ngx_table_elt_t *h, ngx_uint_t offset);
0028 static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r,
0029     ngx_table_elt_t *h, ngx_uint_t offset);
0030 static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r,
0031     ngx_table_elt_t *h, ngx_uint_t offset);
0032 
0033 static ngx_int_t ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool,
0034     ngx_uint_t alloc);
0035 static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r,
0036     ngx_str_t *host);
0037 static ngx_int_t ngx_http_find_virtual_server(ngx_connection_t *c,
0038     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
0039     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp);
0040 
0041 static void ngx_http_request_handler(ngx_event_t *ev);
0042 static void ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc);
0043 static void ngx_http_terminate_handler(ngx_http_request_t *r);
0044 static void ngx_http_finalize_connection(ngx_http_request_t *r);
0045 static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r);
0046 static void ngx_http_writer(ngx_http_request_t *r);
0047 static void ngx_http_request_finalizer(ngx_http_request_t *r);
0048 
0049 static void ngx_http_set_keepalive(ngx_http_request_t *r);
0050 static void ngx_http_keepalive_handler(ngx_event_t *ev);
0051 static void ngx_http_set_lingering_close(ngx_http_request_t *r);
0052 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
0053 static ngx_int_t ngx_http_post_action(ngx_http_request_t *r);
0054 static void ngx_http_close_request(ngx_http_request_t *r, ngx_int_t error);
0055 static void ngx_http_log_request(ngx_http_request_t *r);
0056 
0057 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
0058 static u_char *ngx_http_log_error_handler(ngx_http_request_t *r,
0059     ngx_http_request_t *sr, u_char *buf, size_t len);
0060 
0061 #if (NGX_HTTP_SSL)
0062 static void ngx_http_ssl_handshake(ngx_event_t *rev);
0063 static void ngx_http_ssl_handshake_handler(ngx_connection_t *c);
0064 #endif
0065 
0066 
0067 static char *ngx_http_client_errors[] = {
0068 
0069     /* NGX_HTTP_PARSE_INVALID_METHOD */
0070     "client sent invalid method",
0071 
0072     /* NGX_HTTP_PARSE_INVALID_REQUEST */
0073     "client sent invalid request",
0074 
0075     /* NGX_HTTP_PARSE_INVALID_VERSION */
0076     "client sent invalid version",
0077 
0078     /* NGX_HTTP_PARSE_INVALID_09_METHOD */
0079     "client sent invalid method in HTTP/0.9 request"
0080 };
0081 
0082 
0083 ngx_http_header_t  ngx_http_headers_in[] = {
0084     { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host),
0085                  ngx_http_process_host },
0086 
0087     { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection),
0088                  ngx_http_process_connection },
0089 
0090     { ngx_string("If-Modified-Since"),
0091                  offsetof(ngx_http_headers_in_t, if_modified_since),
0092                  ngx_http_process_unique_header_line },
0093 
0094     { ngx_string("If-Unmodified-Since"),
0095                  offsetof(ngx_http_headers_in_t, if_unmodified_since),
0096                  ngx_http_process_unique_header_line },
0097 
0098     { ngx_string("If-Match"),
0099                  offsetof(ngx_http_headers_in_t, if_match),
0100                  ngx_http_process_unique_header_line },
0101 
0102     { ngx_string("If-None-Match"),
0103                  offsetof(ngx_http_headers_in_t, if_none_match),
0104                  ngx_http_process_unique_header_line },
0105 
0106     { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent),
0107                  ngx_http_process_user_agent },
0108 
0109     { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer),
0110                  ngx_http_process_header_line },
0111 
0112     { ngx_string("Content-Length"),
0113                  offsetof(ngx_http_headers_in_t, content_length),
0114                  ngx_http_process_unique_header_line },
0115 
0116     { ngx_string("Content-Range"),
0117                  offsetof(ngx_http_headers_in_t, content_range),
0118                  ngx_http_process_unique_header_line },
0119 
0120     { ngx_string("Content-Type"),
0121                  offsetof(ngx_http_headers_in_t, content_type),
0122                  ngx_http_process_header_line },
0123 
0124     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
0125                  ngx_http_process_header_line },
0126 
0127     { ngx_string("If-Range"),
0128                  offsetof(ngx_http_headers_in_t, if_range),
0129                  ngx_http_process_unique_header_line },
0130 
0131     { ngx_string("Transfer-Encoding"),
0132                  offsetof(ngx_http_headers_in_t, transfer_encoding),
0133                  ngx_http_process_header_line },
0134 
0135     { ngx_string("TE"),
0136                  offsetof(ngx_http_headers_in_t, te),
0137                  ngx_http_process_header_line },
0138 
0139     { ngx_string("Expect"),
0140                  offsetof(ngx_http_headers_in_t, expect),
0141                  ngx_http_process_unique_header_line },
0142 
0143     { ngx_string("Upgrade"),
0144                  offsetof(ngx_http_headers_in_t, upgrade),
0145                  ngx_http_process_header_line },
0146 
0147 #if (NGX_HTTP_GZIP || NGX_HTTP_HEADERS)
0148     { ngx_string("Accept-Encoding"),
0149                  offsetof(ngx_http_headers_in_t, accept_encoding),
0150                  ngx_http_process_header_line },
0151 
0152     { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via),
0153                  ngx_http_process_header_line },
0154 #endif
0155 
0156     { ngx_string("Authorization"),
0157                  offsetof(ngx_http_headers_in_t, authorization),
0158                  ngx_http_process_unique_header_line },
0159 
0160     { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive),
0161                  ngx_http_process_header_line },
0162 
0163 #if (NGX_HTTP_X_FORWARDED_FOR)
0164     { ngx_string("X-Forwarded-For"),
0165                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
0166                  ngx_http_process_multi_header_lines },
0167 #endif
0168 
0169 #if (NGX_HTTP_REALIP)
0170     { ngx_string("X-Real-IP"),
0171                  offsetof(ngx_http_headers_in_t, x_real_ip),
0172                  ngx_http_process_header_line },
0173 #endif
0174 
0175 #if (NGX_HTTP_HEADERS)
0176     { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept),
0177                  ngx_http_process_header_line },
0178 
0179     { ngx_string("Accept-Language"),
0180                  offsetof(ngx_http_headers_in_t, accept_language),
0181                  ngx_http_process_header_line },
0182 #endif
0183 
0184 #if (NGX_HTTP_DAV)
0185     { ngx_string("Depth"), offsetof(ngx_http_headers_in_t, depth),
0186                  ngx_http_process_header_line },
0187 
0188     { ngx_string("Destination"), offsetof(ngx_http_headers_in_t, destination),
0189                  ngx_http_process_header_line },
0190 
0191     { ngx_string("Overwrite"), offsetof(ngx_http_headers_in_t, overwrite),
0192                  ngx_http_process_header_line },
0193 
0194     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
0195                  ngx_http_process_header_line },
0196 #endif
0197 
0198     { ngx_string("Cookie"), offsetof(ngx_http_headers_in_t, cookies),
0199                  ngx_http_process_multi_header_lines },
0200 
0201     { ngx_null_string, 0, NULL }
0202 };
0203 
0204 
0205 void
0206 ngx_http_init_connection(ngx_connection_t *c)
0207 {
0208     ngx_uint_t              i;
0209     ngx_event_t            *rev;
0210     struct sockaddr_in     *sin;
0211     ngx_http_port_t        *port;
0212     ngx_http_in_addr_t     *addr;
0213     ngx_http_log_ctx_t     *ctx;
0214     ngx_http_connection_t  *hc;
0215 #if (NGX_HAVE_INET6)
0216     struct sockaddr_in6    *sin6;
0217     ngx_http_in6_addr_t    *addr6;
0218 #endif
0219 
0220     hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
0221     if (hc == NULL) {
0222         ngx_http_close_connection(c);
0223         return;
0224     }
0225 
0226     c->data = hc;
0227 
0228     /* find the server configuration for the address:port */
0229 
0230     port = c->listening->servers;
0231 
0232     if (port->naddrs > 1) {
0233 
0234         /*
0235          * there are several addresses on this port and one of them
0236          * is an "*:port" wildcard so getsockname() in ngx_http_server_addr()
0237          * is required to determine a server address
0238          */
0239 
0240         if (ngx_connection_local_sockaddr(c, NULL, 0) != NGX_OK) {
0241             ngx_http_close_connection(c);
0242             return;
0243         }
0244 
0245         switch (c->local_sockaddr->sa_family) {
0246 
0247 #if (NGX_HAVE_INET6)
0248         case AF_INET6:
0249             sin6 = (struct sockaddr_in6 *) c->local_sockaddr;
0250 
0251             addr6 = port->addrs;
0252 
0253             /* the last address is "*" */
0254 
0255             for (i = 0; i < port->naddrs - 1; i++) {
0256                 if (ngx_memcmp(&addr6[i].addr6, &sin6->sin6_addr, 16) == 0) {
0257                     break;
0258                 }
0259             }
0260 
0261             hc->addr_conf = &addr6[i].conf;
0262 
0263             break;
0264 #endif
0265 
0266         default: /* AF_INET */
0267             sin = (struct sockaddr_in *) c->local_sockaddr;
0268 
0269             addr = port->addrs;
0270 
0271             /* the last address is "*" */
0272 
0273             for (i = 0; i < port->naddrs - 1; i++) {
0274                 if (addr[i].addr == sin->sin_addr.s_addr) {
0275                     break;
0276                 }
0277             }
0278 
0279             hc->addr_conf = &addr[i].conf;
0280 
0281             break;
0282         }
0283 
0284     } else {
0285 
0286         switch (c->local_sockaddr->sa_family) {
0287 
0288 #if (NGX_HAVE_INET6)
0289         case AF_INET6:
0290             addr6 = port->addrs;
0291             hc->addr_conf = &addr6[0].conf;
0292             break;
0293 #endif
0294 
0295         default: /* AF_INET */
0296             addr = port->addrs;
0297             hc->addr_conf = &addr[0].conf;
0298             break;
0299         }
0300     }
0301 
0302     /* the default server configuration for the address:port */
0303     hc->conf_ctx = hc->addr_conf->default_server->ctx;
0304 
0305     ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
0306     if (ctx == NULL) {
0307         ngx_http_close_connection(c);
0308         return;
0309     }
0310 
0311     ctx->connection = c;
0312     ctx->request = NULL;
0313     ctx->current_request = NULL;
0314 
0315     c->log->connection = c->number;
0316     c->log->handler = ngx_http_log_error;
0317     c->log->data = ctx;
0318     c->log->action = "waiting for request";
0319 
0320     c->log_error = NGX_ERROR_INFO;
0321 
0322     rev = c->read;
0323     rev->handler = ngx_http_wait_request_handler;
0324     c->write->handler = ngx_http_empty_handler;
0325 
0326 #if (NGX_HTTP_V2)
0327     if (hc->addr_conf->http2) {
0328         rev->handler = ngx_http_v2_init;
0329     }
0330 #endif
0331 
0332 #if (NGX_HTTP_SSL)
0333     {
0334     ngx_http_ssl_srv_conf_t  *sscf;
0335 
0336     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
0337 
0338     if (sscf->enable || hc->addr_conf->ssl) {
0339 
0340         c->log->action = "SSL handshaking";
0341 
0342         if (hc->addr_conf->ssl && sscf->ssl.ctx == NULL) {
0343             ngx_log_error(NGX_LOG_ERR, c->log, 0,
0344                           "no \"ssl_certificate\" is defined "
0345                           "in server listening on SSL port");
0346             ngx_http_close_connection(c);
0347             return;
0348         }
0349 
0350         hc->ssl = 1;
0351 
0352         rev->handler = ngx_http_ssl_handshake;
0353     }
0354     }
0355 #endif
0356 
0357     if (hc->addr_conf->proxy_protocol) {
0358         hc->proxy_protocol = 1;
0359         c->log->action = "reading PROXY protocol";
0360     }
0361 
0362     if (rev->ready) {
0363         /* the deferred accept(), iocp */
0364 
0365         if (ngx_use_accept_mutex) {
0366             ngx_post_event(rev, &ngx_posted_events);
0367             return;
0368         }
0369 
0370         rev->handler(rev);
0371         return;
0372     }
0373 
0374     ngx_add_timer(rev, c->listening->post_accept_timeout);
0375     ngx_reusable_connection(c, 1);
0376 
0377     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0378         ngx_http_close_connection(c);
0379         return;
0380     }
0381 }
0382 
0383 
0384 static void
0385 ngx_http_wait_request_handler(ngx_event_t *rev)
0386 {
0387     u_char                    *p;
0388     size_t                     size;
0389     ssize_t                    n;
0390     ngx_buf_t                 *b;
0391     ngx_connection_t          *c;
0392     ngx_http_connection_t     *hc;
0393     ngx_http_core_srv_conf_t  *cscf;
0394 
0395     c = rev->data;
0396 
0397     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler");
0398 
0399     if (rev->timedout) {
0400         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0401         ngx_http_close_connection(c);
0402         return;
0403     }
0404 
0405     if (c->close) {
0406         ngx_http_close_connection(c);
0407         return;
0408     }
0409 
0410     hc = c->data;
0411     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
0412 
0413     size = cscf->client_header_buffer_size;
0414 
0415     b = c->buffer;
0416 
0417     if (b == NULL) {
0418         b = ngx_create_temp_buf(c->pool, size);
0419         if (b == NULL) {
0420             ngx_http_close_connection(c);
0421             return;
0422         }
0423 
0424         c->buffer = b;
0425 
0426     } else if (b->start == NULL) {
0427 
0428         b->start = ngx_palloc(c->pool, size);
0429         if (b->start == NULL) {
0430             ngx_http_close_connection(c);
0431             return;
0432         }
0433 
0434         b->pos = b->start;
0435         b->last = b->start;
0436         b->end = b->last + size;
0437     }
0438 
0439     n = c->recv(c, b->last, size);
0440 
0441     if (n == NGX_AGAIN) {
0442 
0443         if (!rev->timer_set) {
0444             ngx_add_timer(rev, c->listening->post_accept_timeout);
0445             ngx_reusable_connection(c, 1);
0446         }
0447 
0448         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0449             ngx_http_close_connection(c);
0450             return;
0451         }
0452 
0453         /*
0454          * We are trying to not hold c->buffer's memory for an idle connection.
0455          */
0456 
0457         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
0458             b->start = NULL;
0459         }
0460 
0461         return;
0462     }
0463 
0464     if (n == NGX_ERROR) {
0465         ngx_http_close_connection(c);
0466         return;
0467     }
0468 
0469     if (n == 0) {
0470         ngx_log_error(NGX_LOG_INFO, c->log, 0,
0471                       "client closed connection");
0472         ngx_http_close_connection(c);
0473         return;
0474     }
0475 
0476     b->last += n;
0477 
0478     if (hc->proxy_protocol) {
0479         hc->proxy_protocol = 0;
0480 
0481         p = ngx_proxy_protocol_read(c, b->pos, b->last);
0482 
0483         if (p == NULL) {
0484             ngx_http_close_connection(c);
0485             return;
0486         }
0487 
0488         b->pos = p;
0489 
0490         if (b->pos == b->last) {
0491             c->log->action = "waiting for request";
0492             b->pos = b->start;
0493             b->last = b->start;
0494             ngx_post_event(rev, &ngx_posted_events);
0495             return;
0496         }
0497     }
0498 
0499     c->log->action = "reading client request line";
0500 
0501     ngx_reusable_connection(c, 0);
0502 
0503     c->data = ngx_http_create_request(c);
0504     if (c->data == NULL) {
0505         ngx_http_close_connection(c);
0506         return;
0507     }
0508 
0509     rev->handler = ngx_http_process_request_line;
0510     ngx_http_process_request_line(rev);
0511 }
0512 
0513 
0514 ngx_http_request_t *
0515 ngx_http_create_request(ngx_connection_t *c)
0516 {
0517     ngx_pool_t                 *pool;
0518     ngx_time_t                 *tp;
0519     ngx_http_request_t         *r;
0520     ngx_http_log_ctx_t         *ctx;
0521     ngx_http_connection_t      *hc;
0522     ngx_http_core_srv_conf_t   *cscf;
0523     ngx_http_core_loc_conf_t   *clcf;
0524     ngx_http_core_main_conf_t  *cmcf;
0525 
0526     c->requests++;
0527 
0528     hc = c->data;
0529 
0530     cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module);
0531 
0532     pool = ngx_create_pool(cscf->request_pool_size, c->log);
0533     if (pool == NULL) {
0534         return NULL;
0535     }
0536 
0537     r = ngx_pcalloc(pool, sizeof(ngx_http_request_t));
0538     if (r == NULL) {
0539         ngx_destroy_pool(pool);
0540         return NULL;
0541     }
0542 
0543     r->pool = pool;
0544 
0545     r->http_connection = hc;
0546     r->signature = NGX_HTTP_MODULE;
0547     r->connection = c;
0548 
0549     r->main_conf = hc->conf_ctx->main_conf;
0550     r->srv_conf = hc->conf_ctx->srv_conf;
0551     r->loc_conf = hc->conf_ctx->loc_conf;
0552 
0553     r->read_event_handler = ngx_http_block_reading;
0554 
0555     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
0556 
0557     ngx_set_connection_log(r->connection, clcf->error_log);
0558 
0559     r->header_in = hc->busy ? hc->busy->buf : c->buffer;
0560 
0561     if (ngx_list_init(&r->headers_out.headers, r->pool, 20,
0562                       sizeof(ngx_table_elt_t))
0563         != NGX_OK)
0564     {
0565         ngx_destroy_pool(r->pool);
0566         return NULL;
0567     }
0568 
0569     if (ngx_list_init(&r->headers_out.trailers, r->pool, 4,
0570                       sizeof(ngx_table_elt_t))
0571         != NGX_OK)
0572     {
0573         ngx_destroy_pool(r->pool);
0574         return NULL;
0575     }
0576 
0577     r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
0578     if (r->ctx == NULL) {
0579         ngx_destroy_pool(r->pool);
0580         return NULL;
0581     }
0582 
0583     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
0584 
0585     r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
0586                                         * sizeof(ngx_http_variable_value_t));
0587     if (r->variables == NULL) {
0588         ngx_destroy_pool(r->pool);
0589         return NULL;
0590     }
0591 
0592 #if (NGX_HTTP_SSL)
0593     if (c->ssl) {
0594         r->main_filter_need_in_memory = 1;
0595     }
0596 #endif
0597 
0598     r->main = r;
0599     r->count = 1;
0600 
0601     tp = ngx_timeofday();
0602     r->start_sec = tp->sec;
0603     r->start_msec = tp->msec;
0604 
0605     r->method = NGX_HTTP_UNKNOWN;
0606     r->http_version = NGX_HTTP_VERSION_10;
0607 
0608     r->headers_in.content_length_n = -1;
0609     r->headers_in.keep_alive_n = -1;
0610     r->headers_out.content_length_n = -1;
0611     r->headers_out.last_modified_time = -1;
0612 
0613     r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
0614     r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1;
0615 
0616     r->http_state = NGX_HTTP_READING_REQUEST_STATE;
0617 
0618     ctx = c->log->data;
0619     ctx->request = r;
0620     ctx->current_request = r;
0621     r->log_handler = ngx_http_log_error_handler;
0622 
0623 #if (NGX_STAT_STUB)
0624     (void) ngx_atomic_fetch_add(ngx_stat_reading, 1);
0625     r->stat_reading = 1;
0626     (void) ngx_atomic_fetch_add(ngx_stat_requests, 1);
0627 #endif
0628 
0629     return r;
0630 }
0631 
0632 
0633 #if (NGX_HTTP_SSL)
0634 
0635 static void
0636 ngx_http_ssl_handshake(ngx_event_t *rev)
0637 {
0638     u_char                    *p, buf[NGX_PROXY_PROTOCOL_MAX_HEADER + 1];
0639     size_t                     size;
0640     ssize_t                    n;
0641     ngx_err_t                  err;
0642     ngx_int_t                  rc;
0643     ngx_connection_t          *c;
0644     ngx_http_connection_t     *hc;
0645     ngx_http_ssl_srv_conf_t   *sscf;
0646     ngx_http_core_loc_conf_t  *clcf;
0647 
0648     c = rev->data;
0649     hc = c->data;
0650 
0651     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
0652                    "http check ssl handshake");
0653 
0654     if (rev->timedout) {
0655         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0656         ngx_http_close_connection(c);
0657         return;
0658     }
0659 
0660     if (c->close) {
0661         ngx_http_close_connection(c);
0662         return;
0663     }
0664 
0665     size = hc->proxy_protocol ? sizeof(buf) : 1;
0666 
0667     n = recv(c->fd, (char *) buf, size, MSG_PEEK);
0668 
0669     err = ngx_socket_errno;
0670 
0671     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, "http recv(): %z", n);
0672 
0673     if (n == -1) {
0674         if (err == NGX_EAGAIN) {
0675             rev->ready = 0;
0676 
0677             if (!rev->timer_set) {
0678                 ngx_add_timer(rev, c->listening->post_accept_timeout);
0679                 ngx_reusable_connection(c, 1);
0680             }
0681 
0682             if (ngx_handle_read_event(rev, 0) != NGX_OK) {
0683                 ngx_http_close_connection(c);
0684             }
0685 
0686             return;
0687         }
0688 
0689         ngx_connection_error(c, err, "recv() failed");
0690         ngx_http_close_connection(c);
0691 
0692         return;
0693     }
0694 
0695     if (hc->proxy_protocol) {
0696         hc->proxy_protocol = 0;
0697 
0698         p = ngx_proxy_protocol_read(c, buf, buf + n);
0699 
0700         if (p == NULL) {
0701             ngx_http_close_connection(c);
0702             return;
0703         }
0704 
0705         size = p - buf;
0706 
0707         if (c->recv(c, buf, size) != (ssize_t) size) {
0708             ngx_http_close_connection(c);
0709             return;
0710         }
0711 
0712         c->log->action = "SSL handshaking";
0713 
0714         if (n == (ssize_t) size) {
0715             ngx_post_event(rev, &ngx_posted_events);
0716             return;
0717         }
0718 
0719         n = 1;
0720         buf[0] = *p;
0721     }
0722 
0723     if (n == 1) {
0724         if (buf[0] & 0x80 /* SSLv2 */ || buf[0] == 0x16 /* SSLv3/TLSv1 */) {
0725             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0,
0726                            "https ssl handshake: 0x%02Xd", buf[0]);
0727 
0728             clcf = ngx_http_get_module_loc_conf(hc->conf_ctx,
0729                                                 ngx_http_core_module);
0730 
0731             if (clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
0732                 ngx_http_close_connection(c);
0733                 return;
0734             }
0735 
0736             sscf = ngx_http_get_module_srv_conf(hc->conf_ctx,
0737                                                 ngx_http_ssl_module);
0738 
0739             if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER)
0740                 != NGX_OK)
0741             {
0742                 ngx_http_close_connection(c);
0743                 return;
0744             }
0745 
0746             rc = ngx_ssl_handshake(c);
0747 
0748             if (rc == NGX_AGAIN) {
0749 
0750                 if (!rev->timer_set) {
0751                     ngx_add_timer(rev, c->listening->post_accept_timeout);
0752                 }
0753 
0754                 ngx_reusable_connection(c, 0);
0755 
0756                 c->ssl->handler = ngx_http_ssl_handshake_handler;
0757                 return;
0758             }
0759 
0760             ngx_http_ssl_handshake_handler(c);
0761 
0762             return;
0763         }
0764 
0765         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0, "plain http");
0766 
0767         c->log->action = "waiting for request";
0768 
0769         rev->handler = ngx_http_wait_request_handler;
0770         ngx_http_wait_request_handler(rev);
0771 
0772         return;
0773     }
0774 
0775     ngx_log_error(NGX_LOG_INFO, c->log, 0, "client closed connection");
0776     ngx_http_close_connection(c);
0777 }
0778 
0779 
0780 static void
0781 ngx_http_ssl_handshake_handler(ngx_connection_t *c)
0782 {
0783     if (c->ssl->handshaked) {
0784 
0785         /*
0786          * The majority of browsers do not send the "close notify" alert.
0787          * Among them are MSIE, old Mozilla, Netscape 4, Konqueror,
0788          * and Links.  And what is more, MSIE ignores the server's alert.
0789          *
0790          * Opera and recent Mozilla send the alert.
0791          */
0792 
0793         c->ssl->no_wait_shutdown = 1;
0794 
0795 #if (NGX_HTTP_V2                                                              \
0796      && (defined TLSEXT_TYPE_application_layer_protocol_negotiation           \
0797          || defined TLSEXT_TYPE_next_proto_neg))
0798         {
0799         unsigned int            len;
0800         const unsigned char    *data;
0801         ngx_http_connection_t  *hc;
0802 
0803         hc = c->data;
0804 
0805         if (hc->addr_conf->http2) {
0806 
0807 #ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
0808             SSL_get0_alpn_selected(c->ssl->connection, &data, &len);
0809 
0810 #ifdef TLSEXT_TYPE_next_proto_neg
0811             if (len == 0) {
0812                 SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
0813             }
0814 #endif
0815 
0816 #else /* TLSEXT_TYPE_next_proto_neg */
0817             SSL_get0_next_proto_negotiated(c->ssl->connection, &data, &len);
0818 #endif
0819 
0820             if (len == 2 && data[0] == 'h' && data[1] == '2') {
0821                 ngx_http_v2_init(c->read);
0822                 return;
0823             }
0824         }
0825         }
0826 #endif
0827 
0828         c->log->action = "waiting for request";
0829 
0830         c->read->handler = ngx_http_wait_request_handler;
0831         /* STUB: epoll edge */ c->write->handler = ngx_http_empty_handler;
0832 
0833         ngx_reusable_connection(c, 1);
0834 
0835         ngx_http_wait_request_handler(c->read);
0836 
0837         return;
0838     }
0839 
0840     if (c->read->timedout) {
0841         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0842     }
0843 
0844     ngx_http_close_connection(c);
0845 }
0846 
0847 #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
0848 
0849 int
0850 ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg)
0851 {
0852     ngx_str_t                  host;
0853     const char                *servername;
0854     ngx_connection_t          *c;
0855     ngx_http_connection_t     *hc;
0856     ngx_http_ssl_srv_conf_t   *sscf;
0857     ngx_http_core_loc_conf_t  *clcf;
0858     ngx_http_core_srv_conf_t  *cscf;
0859 
0860     servername = SSL_get_servername(ssl_conn, TLSEXT_NAMETYPE_host_name);
0861 
0862     if (servername == NULL) {
0863         return SSL_TLSEXT_ERR_NOACK;
0864     }
0865 
0866     c = ngx_ssl_get_connection(ssl_conn);
0867 
0868     if (c->ssl->renegotiation) {
0869         return SSL_TLSEXT_ERR_NOACK;
0870     }
0871 
0872     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
0873                    "SSL server name: \"%s\"", servername);
0874 
0875     host.len = ngx_strlen(servername);
0876 
0877     if (host.len == 0) {
0878         return SSL_TLSEXT_ERR_NOACK;
0879     }
0880 
0881     host.data = (u_char *) servername;
0882 
0883     if (ngx_http_validate_host(&host, c->pool, 1) != NGX_OK) {
0884         return SSL_TLSEXT_ERR_NOACK;
0885     }
0886 
0887     hc = c->data;
0888 
0889     if (ngx_http_find_virtual_server(c, hc->addr_conf->virtual_names, &host,
0890                                      NULL, &cscf)
0891         != NGX_OK)
0892     {
0893         return SSL_TLSEXT_ERR_NOACK;
0894     }
0895 
0896     hc->ssl_servername = ngx_palloc(c->pool, sizeof(ngx_str_t));
0897     if (hc->ssl_servername == NULL) {
0898         return SSL_TLSEXT_ERR_NOACK;
0899     }
0900 
0901     *hc->ssl_servername = host;
0902 
0903     hc->conf_ctx = cscf->ctx;
0904 
0905     clcf = ngx_http_get_module_loc_conf(hc->conf_ctx, ngx_http_core_module);
0906 
0907     ngx_set_connection_log(c, clcf->error_log);
0908 
0909     sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module);
0910 
0911     c->ssl->buffer_size = sscf->buffer_size;
0912 
0913     if (sscf->ssl.ctx) {
0914         SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx);
0915 
0916         /*
0917          * SSL_set_SSL_CTX() only changes certs as of 1.0.0d
0918          * adjust other things we care about
0919          */
0920 
0921         SSL_set_verify(ssl_conn, SSL_CTX_get_verify_mode(sscf->ssl.ctx),
0922                        SSL_CTX_get_verify_callback(sscf->ssl.ctx));
0923 
0924         SSL_set_verify_depth(ssl_conn, SSL_CTX_get_verify_depth(sscf->ssl.ctx));
0925 
0926 #ifdef SSL_CTRL_CLEAR_OPTIONS
0927         /* only in 0.9.8m+ */
0928         SSL_clear_options(ssl_conn, SSL_get_options(ssl_conn) &
0929                                     ~SSL_CTX_get_options(sscf->ssl.ctx));
0930 #endif
0931 
0932         SSL_set_options(ssl_conn, SSL_CTX_get_options(sscf->ssl.ctx));
0933     }
0934 
0935     return SSL_TLSEXT_ERR_OK;
0936 }
0937 
0938 #endif
0939 
0940 #endif
0941 
0942 
0943 static void
0944 ngx_http_process_request_line(ngx_event_t *rev)
0945 {
0946     ssize_t              n;
0947     ngx_int_t            rc, rv;
0948     ngx_str_t            host;
0949     ngx_connection_t    *c;
0950     ngx_http_request_t  *r;
0951 
0952     c = rev->data;
0953     r = c->data;
0954 
0955     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
0956                    "http process request line");
0957 
0958     if (rev->timedout) {
0959         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
0960         c->timedout = 1;
0961         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
0962         return;
0963     }
0964 
0965     rc = NGX_AGAIN;
0966 
0967     for ( ;; ) {
0968 
0969         if (rc == NGX_AGAIN) {
0970             n = ngx_http_read_request_header(r);
0971 
0972             if (n == NGX_AGAIN || n == NGX_ERROR) {
0973                 return;
0974             }
0975         }
0976 
0977         rc = ngx_http_parse_request_line(r, r->header_in);
0978 
0979         if (rc == NGX_OK) {
0980 
0981             /* the request line has been parsed successfully */
0982 
0983             r->request_line.len = r->request_end - r->request_start;
0984             r->request_line.data = r->request_start;
0985             r->request_length = r->header_in->pos - r->request_start;
0986 
0987             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
0988                            "http request line: \"%V\"", &r->request_line);
0989 
0990             r->method_name.len = r->method_end - r->request_start + 1;
0991             r->method_name.data = r->request_line.data;
0992 
0993             if (r->http_protocol.data) {
0994                 r->http_protocol.len = r->request_end - r->http_protocol.data;
0995             }
0996 
0997             if (ngx_http_process_request_uri(r) != NGX_OK) {
0998                 return;
0999             }
1000 
1001             if (r->host_start && r->host_end) {
1002 
1003                 host.len = r->host_end - r->host_start;
1004                 host.data = r->host_start;
1005 
1006                 rc = ngx_http_validate_host(&host, r->pool, 0);
1007 
1008                 if (rc == NGX_DECLINED) {
1009                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1010                                   "client sent invalid host in request line");
1011                     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1012                     return;
1013                 }
1014 
1015                 if (rc == NGX_ERROR) {
1016                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1017                     return;
1018                 }
1019 
1020                 if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1021                     return;
1022                 }
1023 
1024                 r->headers_in.server = host;
1025             }
1026 
1027             if (r->http_version < NGX_HTTP_VERSION_10) {
1028 
1029                 if (r->headers_in.server.len == 0
1030                     && ngx_http_set_virtual_server(r, &r->headers_in.server)
1031                        == NGX_ERROR)
1032                 {
1033                     return;
1034                 }
1035 
1036                 ngx_http_process_request(r);
1037                 return;
1038             }
1039 
1040 
1041             if (ngx_list_init(&r->headers_in.headers, r->pool, 20,
1042                               sizeof(ngx_table_elt_t))
1043                 != NGX_OK)
1044             {
1045                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1046                 return;
1047             }
1048 
1049             c->log->action = "reading client request headers";
1050 
1051             rev->handler = ngx_http_process_request_headers;
1052             ngx_http_process_request_headers(rev);
1053 
1054             return;
1055         }
1056 
1057         if (rc != NGX_AGAIN) {
1058 
1059             /* there was error while a request line parsing */
1060 
1061             ngx_log_error(NGX_LOG_INFO, c->log, 0,
1062                           ngx_http_client_errors[rc - NGX_HTTP_CLIENT_ERROR]);
1063 
1064             if (rc == NGX_HTTP_PARSE_INVALID_VERSION) {
1065                 ngx_http_finalize_request(r, NGX_HTTP_VERSION_NOT_SUPPORTED);
1066 
1067             } else {
1068                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1069             }
1070 
1071             return;
1072         }
1073 
1074         /* NGX_AGAIN: a request line parsing is still incomplete */
1075 
1076         if (r->header_in->pos == r->header_in->end) {
1077 
1078             rv = ngx_http_alloc_large_header_buffer(r, 1);
1079 
1080             if (rv == NGX_ERROR) {
1081                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1082                 return;
1083             }
1084 
1085             if (rv == NGX_DECLINED) {
1086                 r->request_line.len = r->header_in->end - r->request_start;
1087                 r->request_line.data = r->request_start;
1088 
1089                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1090                               "client sent too long URI");
1091                 ngx_http_finalize_request(r, NGX_HTTP_REQUEST_URI_TOO_LARGE);
1092                 return;
1093             }
1094         }
1095     }
1096 }
1097 
1098 
1099 ngx_int_t
1100 ngx_http_process_request_uri(ngx_http_request_t *r)
1101 {
1102     ngx_http_core_srv_conf_t  *cscf;
1103 
1104     if (r->args_start) {
1105         r->uri.len = r->args_start - 1 - r->uri_start;
1106     } else {
1107         r->uri.len = r->uri_end - r->uri_start;
1108     }
1109 
1110     if (r->complex_uri || r->quoted_uri) {
1111 
1112         r->uri.data = ngx_pnalloc(r->pool, r->uri.len + 1);
1113         if (r->uri.data == NULL) {
1114             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1115             return NGX_ERROR;
1116         }
1117 
1118         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1119 
1120         if (ngx_http_parse_complex_uri(r, cscf->merge_slashes) != NGX_OK) {
1121             r->uri.len = 0;
1122 
1123             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1124                           "client sent invalid request");
1125             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1126             return NGX_ERROR;
1127         }
1128 
1129     } else {
1130         r->uri.data = r->uri_start;
1131     }
1132 
1133     r->unparsed_uri.len = r->uri_end - r->uri_start;
1134     r->unparsed_uri.data = r->uri_start;
1135 
1136     r->valid_unparsed_uri = r->space_in_uri ? 0 : 1;
1137 
1138     if (r->uri_ext) {
1139         if (r->args_start) {
1140             r->exten.len = r->args_start - 1 - r->uri_ext;
1141         } else {
1142             r->exten.len = r->uri_end - r->uri_ext;
1143         }
1144 
1145         r->exten.data = r->uri_ext;
1146     }
1147 
1148     if (r->args_start && r->uri_end > r->args_start) {
1149         r->args.len = r->uri_end - r->args_start;
1150         r->args.data = r->args_start;
1151     }
1152 
1153 #if (NGX_WIN32)
1154     {
1155     u_char  *p, *last;
1156 
1157     p = r->uri.data;
1158     last = r->uri.data + r->uri.len;
1159 
1160     while (p < last) {
1161 
1162         if (*p++ == ':') {
1163 
1164             /*
1165              * this check covers "::$data", "::$index_allocation" and
1166              * ":$i30:$index_allocation"
1167              */
1168 
1169             if (p < last && *p == '$') {
1170                 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1171                               "client sent unsafe win32 URI");
1172                 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1173                 return NGX_ERROR;
1174             }
1175         }
1176     }
1177 
1178     p = r->uri.data + r->uri.len - 1;
1179 
1180     while (p > r->uri.data) {
1181 
1182         if (*p == ' ') {
1183             p--;
1184             continue;
1185         }
1186 
1187         if (*p == '.') {
1188             p--;
1189             continue;
1190         }
1191 
1192         break;
1193     }
1194 
1195     if (p != r->uri.data + r->uri.len - 1) {
1196         r->uri.len = p + 1 - r->uri.data;
1197         ngx_http_set_exten(r);
1198     }
1199 
1200     }
1201 #endif
1202 
1203     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1204                    "http uri: \"%V\"", &r->uri);
1205 
1206     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1207                    "http args: \"%V\"", &r->args);
1208 
1209     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1210                    "http exten: \"%V\"", &r->exten);
1211 
1212     return NGX_OK;
1213 }
1214 
1215 
1216 static void
1217 ngx_http_process_request_headers(ngx_event_t *rev)
1218 {
1219     u_char                     *p;
1220     size_t                      len;
1221     ssize_t                     n;
1222     ngx_int_t                   rc, rv;
1223     ngx_table_elt_t            *h;
1224     ngx_connection_t           *c;
1225     ngx_http_header_t          *hh;
1226     ngx_http_request_t         *r;
1227     ngx_http_core_srv_conf_t   *cscf;
1228     ngx_http_core_main_conf_t  *cmcf;
1229 
1230     c = rev->data;
1231     r = c->data;
1232 
1233     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, rev->log, 0,
1234                    "http process request header line");
1235 
1236     if (rev->timedout) {
1237         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out");
1238         c->timedout = 1;
1239         ngx_http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT);
1240         return;
1241     }
1242 
1243     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
1244 
1245     rc = NGX_AGAIN;
1246 
1247     for ( ;; ) {
1248 
1249         if (rc == NGX_AGAIN) {
1250 
1251             if (r->header_in->pos == r->header_in->end) {
1252 
1253                 rv = ngx_http_alloc_large_header_buffer(r, 0);
1254 
1255                 if (rv == NGX_ERROR) {
1256                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1257                     return;
1258                 }
1259 
1260                 if (rv == NGX_DECLINED) {
1261                     p = r->header_name_start;
1262 
1263                     r->lingering_close = 1;
1264 
1265                     if (p == NULL) {
1266                         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1267                                       "client sent too large request");
1268                         ngx_http_finalize_request(r,
1269                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1270                         return;
1271                     }
1272 
1273                     len = r->header_in->end - p;
1274 
1275                     if (len > NGX_MAX_ERROR_STR - 300) {
1276                         len = NGX_MAX_ERROR_STR - 300;
1277                     }
1278 
1279                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1280                                 "client sent too long header line: \"%*s...\"",
1281                                 len, r->header_name_start);
1282 
1283                     ngx_http_finalize_request(r,
1284                                             NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
1285                     return;
1286                 }
1287             }
1288 
1289             n = ngx_http_read_request_header(r);
1290 
1291             if (n == NGX_AGAIN || n == NGX_ERROR) {
1292                 return;
1293             }
1294         }
1295 
1296         /* the host header could change the server configuration context */
1297         cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1298 
1299         rc = ngx_http_parse_header_line(r, r->header_in,
1300                                         cscf->underscores_in_headers);
1301 
1302         if (rc == NGX_OK) {
1303 
1304             r->request_length += r->header_in->pos - r->header_name_start;
1305 
1306             if (r->invalid_header && cscf->ignore_invalid_headers) {
1307 
1308                 /* there was error while a header line parsing */
1309 
1310                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1311                               "client sent invalid header line: \"%*s\"",
1312                               r->header_end - r->header_name_start,
1313                               r->header_name_start);
1314                 continue;
1315             }
1316 
1317             /* a header line has been parsed successfully */
1318 
1319             h = ngx_list_push(&r->headers_in.headers);
1320             if (h == NULL) {
1321                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1322                 return;
1323             }
1324 
1325             h->hash = r->header_hash;
1326 
1327             h->key.len = r->header_name_end - r->header_name_start;
1328             h->key.data = r->header_name_start;
1329             h->key.data[h->key.len] = '\0';
1330 
1331             h->value.len = r->header_end - r->header_start;
1332             h->value.data = r->header_start;
1333             h->value.data[h->value.len] = '\0';
1334 
1335             h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
1336             if (h->lowcase_key == NULL) {
1337                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1338                 return;
1339             }
1340 
1341             if (h->key.len == r->lowcase_index) {
1342                 ngx_memcpy(h->lowcase_key, r->lowcase_header, h->key.len);
1343 
1344             } else {
1345                 ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
1346             }
1347 
1348             hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash,
1349                                h->lowcase_key, h->key.len);
1350 
1351             if (hh && hh->handler(r, h, hh->offset) != NGX_OK) {
1352                 return;
1353             }
1354 
1355             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1356                            "http header: \"%V: %V\"",
1357                            &h->key, &h->value);
1358 
1359             continue;
1360         }
1361 
1362         if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
1363 
1364             /* a whole header has been parsed successfully */
1365 
1366             ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1367                            "http header done");
1368 
1369             r->request_length += r->header_in->pos - r->header_name_start;
1370 
1371             r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
1372 
1373             rc = ngx_http_process_request_header(r);
1374 
1375             if (rc != NGX_OK) {
1376                 return;
1377             }
1378 
1379             ngx_http_process_request(r);
1380 
1381             return;
1382         }
1383 
1384         if (rc == NGX_AGAIN) {
1385 
1386             /* a header line parsing is still not complete */
1387 
1388             continue;
1389         }
1390 
1391         /* rc == NGX_HTTP_PARSE_INVALID_HEADER */
1392 
1393         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1394                       "client sent invalid header line");
1395 
1396         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1397         return;
1398     }
1399 }
1400 
1401 
1402 static ssize_t
1403 ngx_http_read_request_header(ngx_http_request_t *r)
1404 {
1405     ssize_t                    n;
1406     ngx_event_t               *rev;
1407     ngx_connection_t          *c;
1408     ngx_http_core_srv_conf_t  *cscf;
1409 
1410     c = r->connection;
1411     rev = c->read;
1412 
1413     n = r->header_in->last - r->header_in->pos;
1414 
1415     if (n > 0) {
1416         return n;
1417     }
1418 
1419     if (rev->ready) {
1420         n = c->recv(c, r->header_in->last,
1421                     r->header_in->end - r->header_in->last);
1422     } else {
1423         n = NGX_AGAIN;
1424     }
1425 
1426     if (n == NGX_AGAIN) {
1427         if (!rev->timer_set) {
1428             cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1429             ngx_add_timer(rev, cscf->client_header_timeout);
1430         }
1431 
1432         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
1433             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1434             return NGX_ERROR;
1435         }
1436 
1437         return NGX_AGAIN;
1438     }
1439 
1440     if (n == 0) {
1441         ngx_log_error(NGX_LOG_INFO, c->log, 0,
1442                       "client prematurely closed connection");
1443     }
1444 
1445     if (n == 0 || n == NGX_ERROR) {
1446         c->error = 1;
1447         c->log->action = "reading client request headers";
1448 
1449         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1450         return NGX_ERROR;
1451     }
1452 
1453     r->header_in->last += n;
1454 
1455     return n;
1456 }
1457 
1458 
1459 static ngx_int_t
1460 ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
1461     ngx_uint_t request_line)
1462 {
1463     u_char                    *old, *new;
1464     ngx_buf_t                 *b;
1465     ngx_chain_t               *cl;
1466     ngx_http_connection_t     *hc;
1467     ngx_http_core_srv_conf_t  *cscf;
1468 
1469     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1470                    "http alloc large header buffer");
1471 
1472     if (request_line && r->state == 0) {
1473 
1474         /* the client fills up the buffer with "\r\n" */
1475 
1476         r->header_in->pos = r->header_in->start;
1477         r->header_in->last = r->header_in->start;
1478 
1479         return NGX_OK;
1480     }
1481 
1482     old = request_line ? r->request_start : r->header_name_start;
1483 
1484     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
1485 
1486     if (r->state != 0
1487         && (size_t) (r->header_in->pos - old)
1488                                      >= cscf->large_client_header_buffers.size)
1489     {
1490         return NGX_DECLINED;
1491     }
1492 
1493     hc = r->http_connection;
1494 
1495     if (hc->free) {
1496         cl = hc->free;
1497         hc->free = cl->next;
1498 
1499         b = cl->buf;
1500 
1501         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1502                        "http large header free: %p %uz",
1503                        b->pos, b->end - b->last);
1504 
1505     } else if (hc->nbusy < cscf->large_client_header_buffers.num) {
1506 
1507         b = ngx_create_temp_buf(r->connection->pool,
1508                                 cscf->large_client_header_buffers.size);
1509         if (b == NULL) {
1510             return NGX_ERROR;
1511         }
1512 
1513         cl = ngx_alloc_chain_link(r->connection->pool);
1514         if (cl == NULL) {
1515             return NGX_ERROR;
1516         }
1517 
1518         cl->buf = b;
1519 
1520         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1521                        "http large header alloc: %p %uz",
1522                        b->pos, b->end - b->last);
1523 
1524     } else {
1525         return NGX_DECLINED;
1526     }
1527 
1528     cl->next = hc->busy;
1529     hc->busy = cl;
1530     hc->nbusy++;
1531 
1532     if (r->state == 0) {
1533         /*
1534          * r->state == 0 means that a header line was parsed successfully
1535          * and we do not need to copy incomplete header line and
1536          * to relocate the parser header pointers
1537          */
1538 
1539         r->header_in = b;
1540 
1541         return NGX_OK;
1542     }
1543 
1544     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1545                    "http large header copy: %uz", r->header_in->pos - old);
1546 
1547     new = b->start;
1548 
1549     ngx_memcpy(new, old, r->header_in->pos - old);
1550 
1551     b->pos = new + (r->header_in->pos - old);
1552     b->last = new + (r->header_in->pos - old);
1553 
1554     if (request_line) {
1555         r->request_start = new;
1556 
1557         if (r->request_end) {
1558             r->request_end = new + (r->request_end - old);
1559         }
1560 
1561         r->method_end = new + (r->method_end - old);
1562 
1563         r->uri_start = new + (r->uri_start - old);
1564         r->uri_end = new + (r->uri_end - old);
1565 
1566         if (r->schema_start) {
1567             r->schema_start = new + (r->schema_start - old);
1568             r->schema_end = new + (r->schema_end - old);
1569         }
1570 
1571         if (r->host_start) {
1572             r->host_start = new + (r->host_start - old);
1573             if (r->host_end) {
1574                 r->host_end = new + (r->host_end - old);
1575             }
1576         }
1577 
1578         if (r->port_start) {
1579             r->port_start = new + (r->port_start - old);
1580             r->port_end = new + (r->port_end - old);
1581         }
1582 
1583         if (r->uri_ext) {
1584             r->uri_ext = new + (r->uri_ext - old);
1585         }
1586 
1587         if (r->args_start) {
1588             r->args_start = new + (r->args_start - old);
1589         }
1590 
1591         if (r->http_protocol.data) {
1592             r->http_protocol.data = new + (r->http_protocol.data - old);
1593         }
1594 
1595     } else {
1596         r->header_name_start = new;
1597         r->header_name_end = new + (r->header_name_end - old);
1598         r->header_start = new + (r->header_start - old);
1599         r->header_end = new + (r->header_end - old);
1600     }
1601 
1602     r->header_in = b;
1603 
1604     return NGX_OK;
1605 }
1606 
1607 
1608 static ngx_int_t
1609 ngx_http_process_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1610     ngx_uint_t offset)
1611 {
1612     ngx_table_elt_t  **ph;
1613 
1614     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1615 
1616     if (*ph == NULL) {
1617         *ph = h;
1618     }
1619 
1620     return NGX_OK;
1621 }
1622 
1623 
1624 static ngx_int_t
1625 ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h,
1626     ngx_uint_t offset)
1627 {
1628     ngx_table_elt_t  **ph;
1629 
1630     ph = (ngx_table_elt_t **) ((char *) &r->headers_in + offset);
1631 
1632     if (*ph == NULL) {
1633         *ph = h;
1634         return NGX_OK;
1635     }
1636 
1637     ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1638                   "client sent duplicate header line: \"%V: %V\", "
1639                   "previous value: \"%V: %V\"",
1640                   &h->key, &h->value, &(*ph)->key, &(*ph)->value);
1641 
1642     ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1643 
1644     return NGX_ERROR;
1645 }
1646 
1647 
1648 static ngx_int_t
1649 ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h,
1650     ngx_uint_t offset)
1651 {
1652     ngx_int_t  rc;
1653     ngx_str_t  host;
1654 
1655     if (r->headers_in.host == NULL) {
1656         r->headers_in.host = h;
1657     }
1658 
1659     host = h->value;
1660 
1661     rc = ngx_http_validate_host(&host, r->pool, 0);
1662 
1663     if (rc == NGX_DECLINED) {
1664         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1665                       "client sent invalid host header");
1666         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1667         return NGX_ERROR;
1668     }
1669 
1670     if (rc == NGX_ERROR) {
1671         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1672         return NGX_ERROR;
1673     }
1674 
1675     if (r->headers_in.server.len) {
1676         return NGX_OK;
1677     }
1678 
1679     if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) {
1680         return NGX_ERROR;
1681     }
1682 
1683     r->headers_in.server = host;
1684 
1685     return NGX_OK;
1686 }
1687 
1688 
1689 static ngx_int_t
1690 ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h,
1691     ngx_uint_t offset)
1692 {
1693     if (ngx_strcasestrn(h->value.data, "close", 5 - 1)) {
1694         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
1695 
1696     } else if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) {
1697         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
1698     }
1699 
1700     return NGX_OK;
1701 }
1702 
1703 
1704 static ngx_int_t
1705 ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h,
1706     ngx_uint_t offset)
1707 {
1708     u_char  *user_agent, *msie;
1709 
1710     if (r->headers_in.user_agent) {
1711         return NGX_OK;
1712     }
1713 
1714     r->headers_in.user_agent = h;
1715 
1716     /* check some widespread browsers while the header is in CPU cache */
1717 
1718     user_agent = h->value.data;
1719 
1720     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
1721 
1722     if (msie && msie + 7 < user_agent + h->value.len) {
1723 
1724         r->headers_in.msie = 1;
1725 
1726         if (msie[6] == '.') {
1727 
1728             switch (msie[5]) {
1729             case '4':
1730             case '5':
1731                 r->headers_in.msie6 = 1;
1732                 break;
1733             case '6':
1734                 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
1735                     r->headers_in.msie6 = 1;
1736                 }
1737                 break;
1738             }
1739         }
1740 
1741 #if 0
1742         /* MSIE ignores the SSL "close notify" alert */
1743         if (c->ssl) {
1744             c->ssl->no_send_shutdown = 1;
1745         }
1746 #endif
1747     }
1748 
1749     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
1750         r->headers_in.opera = 1;
1751         r->headers_in.msie = 0;
1752         r->headers_in.msie6 = 0;
1753     }
1754 
1755     if (!r->headers_in.msie && !r->headers_in.opera) {
1756 
1757         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
1758             r->headers_in.gecko = 1;
1759 
1760         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
1761             r->headers_in.chrome = 1;
1762 
1763         } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
1764                    && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
1765         {
1766             r->headers_in.safari = 1;
1767 
1768         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
1769             r->headers_in.konqueror = 1;
1770         }
1771     }
1772 
1773     return NGX_OK;
1774 }
1775 
1776 
1777 static ngx_int_t
1778 ngx_http_process_multi_header_lines(ngx_http_request_t *r, ngx_table_elt_t *h,
1779     ngx_uint_t offset)
1780 {
1781     ngx_array_t       *headers;
1782     ngx_table_elt_t  **ph;
1783 
1784     headers = (ngx_array_t *) ((char *) &r->headers_in + offset);
1785 
1786     if (headers->elts == NULL) {
1787         if (ngx_array_init(headers, r->pool, 1, sizeof(ngx_table_elt_t *))
1788             != NGX_OK)
1789         {
1790             ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1791             return NGX_ERROR;
1792         }
1793     }
1794 
1795     ph = ngx_array_push(headers);
1796     if (ph == NULL) {
1797         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1798         return NGX_ERROR;
1799     }
1800 
1801     *ph = h;
1802     return NGX_OK;
1803 }
1804 
1805 
1806 ngx_int_t
1807 ngx_http_process_request_header(ngx_http_request_t *r)
1808 {
1809     if (r->headers_in.server.len == 0
1810         && ngx_http_set_virtual_server(r, &r->headers_in.server)
1811            == NGX_ERROR)
1812     {
1813         return NGX_ERROR;
1814     }
1815 
1816     if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) {
1817         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1818                    "client sent HTTP/1.1 request without \"Host\" header");
1819         ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1820         return NGX_ERROR;
1821     }
1822 
1823     if (r->headers_in.content_length) {
1824         r->headers_in.content_length_n =
1825                             ngx_atoof(r->headers_in.content_length->value.data,
1826                                       r->headers_in.content_length->value.len);
1827 
1828         if (r->headers_in.content_length_n == NGX_ERROR) {
1829             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1830                           "client sent invalid \"Content-Length\" header");
1831             ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST);
1832             return NGX_ERROR;
1833         }
1834     }
1835 
1836     if (r->method == NGX_HTTP_TRACE) {
1837         ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1838                       "client sent TRACE method");
1839         ngx_http_finalize_request(r, NGX_HTTP_NOT_ALLOWED);
1840         return NGX_ERROR;
1841     }
1842 
1843     if (r->headers_in.transfer_encoding) {
1844         if (r->headers_in.transfer_encoding->value.len == 7
1845             && ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1846                                (u_char *) "chunked", 7) == 0)
1847         {
1848             r->headers_in.content_length = NULL;
1849             r->headers_in.content_length_n = -1;
1850             r->headers_in.chunked = 1;
1851 
1852         } else if (r->headers_in.transfer_encoding->value.len != 8
1853             || ngx_strncasecmp(r->headers_in.transfer_encoding->value.data,
1854                                (u_char *) "identity", 8) != 0)
1855         {
1856             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
1857                           "client sent unknown \"Transfer-Encoding\": \"%V\"",
1858                           &r->headers_in.transfer_encoding->value);
1859             ngx_http_finalize_request(r, NGX_HTTP_NOT_IMPLEMENTED);
1860             return NGX_ERROR;
1861         }
1862     }
1863 
1864     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
1865         if (r->headers_in.keep_alive) {
1866             r->headers_in.keep_alive_n =
1867                             ngx_atotm(r->headers_in.keep_alive->value.data,
1868                                       r->headers_in.keep_alive->value.len);
1869         }
1870     }
1871 
1872     return NGX_OK;
1873 }
1874 
1875 
1876 void
1877 ngx_http_process_request(ngx_http_request_t *r)
1878 {
1879     ngx_connection_t  *c;
1880 
1881     c = r->connection;
1882 
1883 #if (NGX_HTTP_SSL)
1884 
1885     if (r->http_connection->ssl) {
1886         long                      rc;
1887         X509                     *cert;
1888         ngx_http_ssl_srv_conf_t  *sscf;
1889 
1890         if (c->ssl == NULL) {
1891             ngx_log_error(NGX_LOG_INFO, c->log, 0,
1892                           "client sent plain HTTP request to HTTPS port");
1893             ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
1894             return;
1895         }
1896 
1897         sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module);
1898 
1899         if (sscf->verify) {
1900             rc = SSL_get_verify_result(c->ssl->connection);
1901 
1902             if (rc != X509_V_OK
1903                 && (sscf->verify != 3 || !ngx_ssl_verify_error_optional(rc)))
1904             {
1905                 ngx_log_error(NGX_LOG_INFO, c->log, 0,
1906                               "client SSL certificate verify error: (%l:%s)",
1907                               rc, X509_verify_cert_error_string(rc));
1908 
1909                 ngx_ssl_remove_cached_session(c->ssl->session_ctx,
1910                                        (SSL_get0_session(c->ssl->connection)));
1911 
1912                 ngx_http_finalize_request(r, NGX_HTTPS_CERT_ERROR);
1913                 return;
1914             }
1915 
1916             if (sscf->verify == 1) {
1917                 cert = SSL_get_peer_certificate(c->ssl->connection);
1918 
1919                 if (cert == NULL) {
1920                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
1921                                   "client sent no required SSL certificate");
1922 
1923                     ngx_ssl_remove_cached_session(c->ssl->session_ctx,
1924                                        (SSL_get0_session(c->ssl->connection)));
1925 
1926                     ngx_http_finalize_request(r, NGX_HTTPS_NO_CERT);
1927                     return;
1928                 }
1929 
1930                 X509_free(cert);
1931             }
1932         }
1933     }
1934 
1935 #endif
1936 
1937     if (c->read->timer_set) {
1938         ngx_del_timer(c->read);
1939     }
1940 
1941 #if (NGX_STAT_STUB)
1942     (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
1943     r->stat_reading = 0;
1944     (void) ngx_atomic_fetch_add(ngx_stat_writing, 1);
1945     r->stat_writing = 1;
1946 #endif
1947 
1948     c->read->handler = ngx_http_request_handler;
1949     c->write->handler = ngx_http_request_handler;
1950     r->read_event_handler = ngx_http_block_reading;
1951 
1952     ngx_http_handler(r);
1953 
1954     ngx_http_run_posted_requests(c);
1955 }
1956 
1957 
1958 static ngx_int_t
1959 ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
1960 {
1961     u_char  *h, ch;
1962     size_t   i, dot_pos, host_len;
1963 
1964     enum {
1965         sw_usual = 0,
1966         sw_literal,
1967         sw_rest
1968     } state;
1969 
1970     dot_pos = host->len;
1971     host_len = host->len;
1972 
1973     h = host->data;
1974 
1975     state = sw_usual;
1976 
1977     for (i = 0; i < host->len; i++) {
1978         ch = h[i];
1979 
1980         switch (ch) {
1981 
1982         case '.':
1983             if (dot_pos == i - 1) {
1984                 return NGX_DECLINED;
1985             }
1986             dot_pos = i;
1987             break;
1988 
1989         case ':':
1990             if (state == sw_usual) {
1991                 host_len = i;
1992                 state = sw_rest;
1993             }
1994             break;
1995 
1996         case '[':
1997             if (i == 0) {
1998                 state = sw_literal;
1999             }
2000             break;
2001 
2002         case ']':
2003             if (state == sw_literal) {
2004                 host_len = i + 1;
2005                 state = sw_rest;
2006             }
2007             break;
2008 
2009         case '\0':
2010             return NGX_DECLINED;
2011 
2012         default:
2013 
2014             if (ngx_path_separator(ch)) {
2015                 return NGX_DECLINED;
2016             }
2017 
2018             if (ch >= 'A' && ch <= 'Z') {
2019                 alloc = 1;
2020             }
2021 
2022             break;
2023         }
2024     }
2025 
2026     if (dot_pos == host_len - 1) {
2027         host_len--;
2028     }
2029 
2030     if (host_len == 0) {
2031         return NGX_DECLINED;
2032     }
2033 
2034     if (alloc) {
2035         host->data = ngx_pnalloc(pool, host_len);
2036         if (host->data == NULL) {
2037             return NGX_ERROR;
2038         }
2039 
2040         ngx_strlow(host->data, h, host_len);
2041     }
2042 
2043     host->len = host_len;
2044 
2045     return NGX_OK;
2046 }
2047 
2048 
2049 static ngx_int_t
2050 ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host)
2051 {
2052     ngx_int_t                  rc;
2053     ngx_http_connection_t     *hc;
2054     ngx_http_core_loc_conf_t  *clcf;
2055     ngx_http_core_srv_conf_t  *cscf;
2056 
2057 #if (NGX_SUPPRESS_WARN)
2058     cscf = NULL;
2059 #endif
2060 
2061     hc = r->http_connection;
2062 
2063 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2064 
2065     if (hc->ssl_servername) {
2066         if (hc->ssl_servername->len == host->len
2067             && ngx_strncmp(hc->ssl_servername->data,
2068                            host->data, host->len) == 0)
2069         {
2070 #if (NGX_PCRE)
2071             if (hc->ssl_servername_regex
2072                 && ngx_http_regex_exec(r, hc->ssl_servername_regex,
2073                                           hc->ssl_servername) != NGX_OK)
2074             {
2075                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2076                 return NGX_ERROR;
2077             }
2078 #endif
2079             return NGX_OK;
2080         }
2081     }
2082 
2083 #endif
2084 
2085     rc = ngx_http_find_virtual_server(r->connection,
2086                                       hc->addr_conf->virtual_names,
2087                                       host, r, &cscf);
2088 
2089     if (rc == NGX_ERROR) {
2090         ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2091         return NGX_ERROR;
2092     }
2093 
2094 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2095 
2096     if (hc->ssl_servername) {
2097         ngx_http_ssl_srv_conf_t  *sscf;
2098 
2099         if (rc == NGX_DECLINED) {
2100             cscf = hc->addr_conf->default_server;
2101             rc = NGX_OK;
2102         }
2103 
2104         sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module);
2105 
2106         if (sscf->verify) {
2107             ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
2108                           "client attempted to request the server name "
2109                           "different from the one that was negotiated");
2110             ngx_http_finalize_request(r, NGX_HTTP_MISDIRECTED_REQUEST);
2111             return NGX_ERROR;
2112         }
2113     }
2114 
2115 #endif
2116 
2117     if (rc == NGX_DECLINED) {
2118         return NGX_OK;
2119     }
2120 
2121     r->srv_conf = cscf->ctx->srv_conf;
2122     r->loc_conf = cscf->ctx->loc_conf;
2123 
2124     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2125 
2126     ngx_set_connection_log(r->connection, clcf->error_log);
2127 
2128     return NGX_OK;
2129 }
2130 
2131 
2132 static ngx_int_t
2133 ngx_http_find_virtual_server(ngx_connection_t *c,
2134     ngx_http_virtual_names_t *virtual_names, ngx_str_t *host,
2135     ngx_http_request_t *r, ngx_http_core_srv_conf_t **cscfp)
2136 {
2137     ngx_http_core_srv_conf_t  *cscf;
2138 
2139     if (virtual_names == NULL) {
2140         return NGX_DECLINED;
2141     }
2142 
2143     cscf = ngx_hash_find_combined(&virtual_names->names,
2144                                   ngx_hash_key(host->data, host->len),
2145                                   host->data, host->len);
2146 
2147     if (cscf) {
2148         *cscfp = cscf;
2149         return NGX_OK;
2150     }
2151 
2152 #if (NGX_PCRE)
2153 
2154     if (host->len && virtual_names->nregex) {
2155         ngx_int_t                n;
2156         ngx_uint_t               i;
2157         ngx_http_server_name_t  *sn;
2158 
2159         sn = virtual_names->regex;
2160 
2161 #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME)
2162 
2163         if (r == NULL) {
2164             ngx_http_connection_t  *hc;
2165 
2166             for (i = 0; i < virtual_names->nregex; i++) {
2167 
2168                 n = ngx_regex_exec(sn[i].regex->regex, host, NULL, 0);
2169 
2170                 if (n == NGX_REGEX_NO_MATCHED) {
2171                     continue;
2172                 }
2173 
2174                 if (n >= 0) {
2175                     hc = c->data;
2176                     hc->ssl_servername_regex = sn[i].regex;
2177 
2178                     *cscfp = sn[i].server;
2179                     return NGX_OK;
2180                 }
2181 
2182                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2183                               ngx_regex_exec_n " failed: %i "
2184                               "on \"%V\" using \"%V\"",
2185                               n, host, &sn[i].regex->name);
2186 
2187                 return NGX_ERROR;
2188             }
2189 
2190             return NGX_DECLINED;
2191         }
2192 
2193 #endif /* NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME */
2194 
2195         for (i = 0; i < virtual_names->nregex; i++) {
2196 
2197             n = ngx_http_regex_exec(r, sn[i].regex, host);
2198 
2199             if (n == NGX_DECLINED) {
2200                 continue;
2201             }
2202 
2203             if (n == NGX_OK) {
2204                 *cscfp = sn[i].server;
2205                 return NGX_OK;
2206             }
2207 
2208             return NGX_ERROR;
2209         }
2210     }
2211 
2212 #endif /* NGX_PCRE */
2213 
2214     return NGX_DECLINED;
2215 }
2216 
2217 
2218 static void
2219 ngx_http_request_handler(ngx_event_t *ev)
2220 {
2221     ngx_connection_t    *c;
2222     ngx_http_request_t  *r;
2223 
2224     c = ev->data;
2225     r = c->data;
2226 
2227     ngx_http_set_log_request(c->log, r);
2228 
2229     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2230                    "http run request: \"%V?%V\"", &r->uri, &r->args);
2231 
2232     if (c->close) {
2233         r->main->count++;
2234         ngx_http_terminate_request(r, 0);
2235         ngx_http_run_posted_requests(c);
2236         return;
2237     }
2238 
2239     if (ev->delayed && ev->timedout) {
2240         ev->delayed = 0;
2241         ev->timedout = 0;
2242     }
2243 
2244     if (ev->write) {
2245         r->write_event_handler(r);
2246 
2247     } else {
2248         r->read_event_handler(r);
2249     }
2250 
2251     ngx_http_run_posted_requests(c);
2252 }
2253 
2254 
2255 void
2256 ngx_http_run_posted_requests(ngx_connection_t *c)
2257 {
2258     ngx_http_request_t         *r;
2259     ngx_http_posted_request_t  *pr;
2260 
2261     for ( ;; ) {
2262 
2263         if (c->destroyed) {
2264             return;
2265         }
2266 
2267         r = c->data;
2268         pr = r->main->posted_requests;
2269 
2270         if (pr == NULL) {
2271             return;
2272         }
2273 
2274         r->main->posted_requests = pr->next;
2275 
2276         r = pr->request;
2277 
2278         ngx_http_set_log_request(c->log, r);
2279 
2280         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2281                        "http posted request: \"%V?%V\"", &r->uri, &r->args);
2282 
2283         r->write_event_handler(r);
2284     }
2285 }
2286 
2287 
2288 ngx_int_t
2289 ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
2290 {
2291     ngx_http_posted_request_t  **p;
2292 
2293     if (pr == NULL) {
2294         pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
2295         if (pr == NULL) {
2296             return NGX_ERROR;
2297         }
2298     }
2299 
2300     pr->request = r;
2301     pr->next = NULL;
2302 
2303     for (p = &r->main->posted_requests; *p; p = &(*p)->next) { /* void */ }
2304 
2305     *p = pr;
2306 
2307     return NGX_OK;
2308 }
2309 
2310 
2311 void
2312 ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
2313 {
2314     ngx_connection_t          *c;
2315     ngx_http_request_t        *pr;
2316     ngx_http_core_loc_conf_t  *clcf;
2317 
2318     c = r->connection;
2319 
2320     ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
2321                    "http finalize request: %i, \"%V?%V\" a:%d, c:%d",
2322                    rc, &r->uri, &r->args, r == c->data, r->main->count);
2323 
2324     if (rc == NGX_DONE) {
2325         ngx_http_finalize_connection(r);
2326         return;
2327     }
2328 
2329     if (rc == NGX_OK && r->filter_finalize) {
2330         c->error = 1;
2331     }
2332 
2333     if (rc == NGX_DECLINED) {
2334         r->content_handler = NULL;
2335         r->write_event_handler = ngx_http_core_run_phases;
2336         ngx_http_core_run_phases(r);
2337         return;
2338     }
2339 
2340     if (r != r->main && r->post_subrequest) {
2341         rc = r->post_subrequest->handler(r, r->post_subrequest->data, rc);
2342     }
2343 
2344     if (rc == NGX_ERROR
2345         || rc == NGX_HTTP_REQUEST_TIME_OUT
2346         || rc == NGX_HTTP_CLIENT_CLOSED_REQUEST
2347         || c->error)
2348     {
2349         if (ngx_http_post_action(r) == NGX_OK) {
2350             return;
2351         }
2352 
2353         ngx_http_terminate_request(r, rc);
2354         return;
2355     }
2356 
2357     if (rc >= NGX_HTTP_SPECIAL_RESPONSE
2358         || rc == NGX_HTTP_CREATED
2359         || rc == NGX_HTTP_NO_CONTENT)
2360     {
2361         if (rc == NGX_HTTP_CLOSE) {
2362             ngx_http_terminate_request(r, rc);
2363             return;
2364         }
2365 
2366         if (r == r->main) {
2367             if (c->read->timer_set) {
2368                 ngx_del_timer(c->read);
2369             }
2370 
2371             if (c->write->timer_set) {
2372                 ngx_del_timer(c->write);
2373             }
2374         }
2375 
2376         c->read->handler = ngx_http_request_handler;
2377         c->write->handler = ngx_http_request_handler;
2378 
2379         ngx_http_finalize_request(r, ngx_http_special_response_handler(r, rc));
2380         return;
2381     }
2382 
2383     if (r != r->main) {
2384         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2385 
2386         if (r->background) {
2387             if (!r->logged) {
2388                 if (clcf->log_subrequest) {
2389                     ngx_http_log_request(r);
2390                 }
2391 
2392                 r->logged = 1;
2393 
2394             } else {
2395                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2396                               "subrequest: \"%V?%V\" logged again",
2397                               &r->uri, &r->args);
2398             }
2399 
2400             r->done = 1;
2401             ngx_http_finalize_connection(r);
2402             return;
2403         }
2404 
2405         if (r->buffered || r->postponed) {
2406 
2407             if (ngx_http_set_write_handler(r) != NGX_OK) {
2408                 ngx_http_terminate_request(r, 0);
2409             }
2410 
2411             return;
2412         }
2413 
2414         pr = r->parent;
2415 
2416         if (r == c->data) {
2417 
2418             r->main->count--;
2419 
2420             if (!r->logged) {
2421                 if (clcf->log_subrequest) {
2422                     ngx_http_log_request(r);
2423                 }
2424 
2425                 r->logged = 1;
2426 
2427             } else {
2428                 ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2429                               "subrequest: \"%V?%V\" logged again",
2430                               &r->uri, &r->args);
2431             }
2432 
2433             r->done = 1;
2434 
2435             if (pr->postponed && pr->postponed->request == r) {
2436                 pr->postponed = pr->postponed->next;
2437             }
2438 
2439             c->data = pr;
2440 
2441         } else {
2442 
2443             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2444                            "http finalize non-active request: \"%V?%V\"",
2445                            &r->uri, &r->args);
2446 
2447             r->write_event_handler = ngx_http_request_finalizer;
2448 
2449             if (r->waited) {
2450                 r->done = 1;
2451             }
2452         }
2453 
2454         if (ngx_http_post_request(pr, NULL) != NGX_OK) {
2455             r->main->count++;
2456             ngx_http_terminate_request(r, 0);
2457             return;
2458         }
2459 
2460         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2461                        "http wake parent request: \"%V?%V\"",
2462                        &pr->uri, &pr->args);
2463 
2464         return;
2465     }
2466 
2467     if (r->buffered || c->buffered || r->postponed) {
2468 
2469         if (ngx_http_set_write_handler(r) != NGX_OK) {
2470             ngx_http_terminate_request(r, 0);
2471         }
2472 
2473         return;
2474     }
2475 
2476     if (r != c->data) {
2477         ngx_log_error(NGX_LOG_ALERT, c->log, 0,
2478                       "http finalize non-active request: \"%V?%V\"",
2479                       &r->uri, &r->args);
2480         return;
2481     }
2482 
2483     r->done = 1;
2484 
2485     r->read_event_handler = ngx_http_block_reading;
2486     r->write_event_handler = ngx_http_request_empty_handler;
2487 
2488     if (!r->post_action) {
2489         r->request_complete = 1;
2490     }
2491 
2492     if (ngx_http_post_action(r) == NGX_OK) {
2493         return;
2494     }
2495 
2496     if (c->read->timer_set) {
2497         ngx_del_timer(c->read);
2498     }
2499 
2500     if (c->write->timer_set) {
2501         c->write->delayed = 0;
2502         ngx_del_timer(c->write);
2503     }
2504 
2505     if (c->read->eof) {
2506         ngx_http_close_request(r, 0);
2507         return;
2508     }
2509 
2510     ngx_http_finalize_connection(r);
2511 }
2512 
2513 
2514 static void
2515 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
2516 {
2517     ngx_http_cleanup_t    *cln;
2518     ngx_http_request_t    *mr;
2519     ngx_http_ephemeral_t  *e;
2520 
2521     mr = r->main;
2522 
2523     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2524                    "http terminate request count:%d", mr->count);
2525 
2526     if (rc > 0 && (mr->headers_out.status == 0 || mr->connection->sent == 0)) {
2527         mr->headers_out.status = rc;
2528     }
2529 
2530     cln = mr->cleanup;
2531     mr->cleanup = NULL;
2532 
2533     while (cln) {
2534         if (cln->handler) {
2535             cln->handler(cln->data);
2536         }
2537 
2538         cln = cln->next;
2539     }
2540 
2541     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2542                    "http terminate cleanup count:%d blk:%d",
2543                    mr->count, mr->blocked);
2544 
2545     if (mr->write_event_handler) {
2546 
2547         if (mr->blocked) {
2548             r->connection->error = 1;
2549             r->write_event_handler = ngx_http_request_finalizer;
2550             return;
2551         }
2552 
2553         e = ngx_http_ephemeral(mr);
2554         mr->posted_requests = NULL;
2555         mr->write_event_handler = ngx_http_terminate_handler;
2556         (void) ngx_http_post_request(mr, &e->terminal_posted_request);
2557         return;
2558     }
2559 
2560     ngx_http_close_request(mr, rc);
2561 }
2562 
2563 
2564 static void
2565 ngx_http_terminate_handler(ngx_http_request_t *r)
2566 {
2567     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2568                    "http terminate handler count:%d", r->count);
2569 
2570     r->count = 1;
2571 
2572     ngx_http_close_request(r, 0);
2573 }
2574 
2575 
2576 static void
2577 ngx_http_finalize_connection(ngx_http_request_t *r)
2578 {
2579     ngx_http_core_loc_conf_t  *clcf;
2580 
2581 #if (NGX_HTTP_V2)
2582     if (r->stream) {
2583         ngx_http_close_request(r, 0);
2584         return;
2585     }
2586 #endif
2587 
2588     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2589 
2590     if (r->main->count != 1) {
2591 
2592         if (r->discard_body) {
2593             r->read_event_handler = ngx_http_discarded_request_body_handler;
2594             ngx_add_timer(r->connection->read, clcf->lingering_timeout);
2595 
2596             if (r->lingering_time == 0) {
2597                 r->lingering_time = ngx_time()
2598                                       + (time_t) (clcf->lingering_time / 1000);
2599             }
2600         }
2601 
2602         ngx_http_close_request(r, 0);
2603         return;
2604     }
2605 
2606     r = r->main;
2607 
2608     if (r->reading_body) {
2609         r->keepalive = 0;
2610         r->lingering_close = 1;
2611     }
2612 
2613     if (!ngx_terminate
2614          && !ngx_exiting
2615          && r->keepalive
2616          && clcf->keepalive_timeout > 0)
2617     {
2618         ngx_http_set_keepalive(r);
2619         return;
2620     }
2621 
2622     if (clcf->lingering_close == NGX_HTTP_LINGERING_ALWAYS
2623         || (clcf->lingering_close == NGX_HTTP_LINGERING_ON
2624             && (r->lingering_close
2625                 || r->header_in->pos < r->header_in->last
2626                 || r->connection->read->ready)))
2627     {
2628         ngx_http_set_lingering_close(r);
2629         return;
2630     }
2631 
2632     ngx_http_close_request(r, 0);
2633 }
2634 
2635 
2636 static ngx_int_t
2637 ngx_http_set_write_handler(ngx_http_request_t *r)
2638 {
2639     ngx_event_t               *wev;
2640     ngx_http_core_loc_conf_t  *clcf;
2641 
2642     r->http_state = NGX_HTTP_WRITING_REQUEST_STATE;
2643 
2644     r->read_event_handler = r->discard_body ?
2645                                 ngx_http_discarded_request_body_handler:
2646                                 ngx_http_test_reading;
2647     r->write_event_handler = ngx_http_writer;
2648 
2649     wev = r->connection->write;
2650 
2651     if (wev->ready && wev->delayed) {
2652         return NGX_OK;
2653     }
2654 
2655     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2656     if (!wev->delayed) {
2657         ngx_add_timer(wev, clcf->send_timeout);
2658     }
2659 
2660     if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2661         ngx_http_close_request(r, 0);
2662         return NGX_ERROR;
2663     }
2664 
2665     return NGX_OK;
2666 }
2667 
2668 
2669 static void
2670 ngx_http_writer(ngx_http_request_t *r)
2671 {
2672     ngx_int_t                  rc;
2673     ngx_event_t               *wev;
2674     ngx_connection_t          *c;
2675     ngx_http_core_loc_conf_t  *clcf;
2676 
2677     c = r->connection;
2678     wev = c->write;
2679 
2680     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2681                    "http writer handler: \"%V?%V\"", &r->uri, &r->args);
2682 
2683     clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
2684 
2685     if (wev->timedout) {
2686         ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT,
2687                       "client timed out");
2688         c->timedout = 1;
2689 
2690         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT);
2691         return;
2692     }
2693 
2694     if (wev->delayed || r->aio) {
2695         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2696                        "http writer delayed");
2697 
2698         if (!wev->delayed) {
2699             ngx_add_timer(wev, clcf->send_timeout);
2700         }
2701 
2702         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2703             ngx_http_close_request(r, 0);
2704         }
2705 
2706         return;
2707     }
2708 
2709     rc = ngx_http_output_filter(r, NULL);
2710 
2711     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
2712                    "http writer output filter: %i, \"%V?%V\"",
2713                    rc, &r->uri, &r->args);
2714 
2715     if (rc == NGX_ERROR) {
2716         ngx_http_finalize_request(r, rc);
2717         return;
2718     }
2719 
2720     if (r->buffered || r->postponed || (r == r->main && c->buffered)) {
2721 
2722         if (!wev->delayed) {
2723             ngx_add_timer(wev, clcf->send_timeout);
2724         }
2725 
2726         if (ngx_handle_write_event(wev, clcf->send_lowat) != NGX_OK) {
2727             ngx_http_close_request(r, 0);
2728         }
2729 
2730         return;
2731     }
2732 
2733     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, wev->log, 0,
2734                    "http writer done: \"%V?%V\"", &r->uri, &r->args);
2735 
2736     r->write_event_handler = ngx_http_request_empty_handler;
2737 
2738     ngx_http_finalize_request(r, rc);
2739 }
2740 
2741 
2742 static void
2743 ngx_http_request_finalizer(ngx_http_request_t *r)
2744 {
2745     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2746                    "http finalizer done: \"%V?%V\"", &r->uri, &r->args);
2747 
2748     ngx_http_finalize_request(r, 0);
2749 }
2750 
2751 
2752 void
2753 ngx_http_block_reading(ngx_http_request_t *r)
2754 {
2755     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2756                    "http reading blocked");
2757 
2758     /* aio does not call this handler */
2759 
2760     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT)
2761         && r->connection->read->active)
2762     {
2763         if (ngx_del_event(r->connection->read, NGX_READ_EVENT, 0) != NGX_OK) {
2764             ngx_http_close_request(r, 0);
2765         }
2766     }
2767 }
2768 
2769 
2770 void
2771 ngx_http_test_reading(ngx_http_request_t *r)
2772 {
2773     int                n;
2774     char               buf[1];
2775     ngx_err_t          err;
2776     ngx_event_t       *rev;
2777     ngx_connection_t  *c;
2778 
2779     c = r->connection;
2780     rev = c->read;
2781 
2782     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http test reading");
2783 
2784 #if (NGX_HTTP_V2)
2785 
2786     if (r->stream) {
2787         if (c->error) {
2788             err = 0;
2789             goto closed;
2790         }
2791 
2792         return;
2793     }
2794 
2795 #endif
2796 
2797 #if (NGX_HAVE_KQUEUE)
2798 
2799     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
2800 
2801         if (!rev->pending_eof) {
2802             return;
2803         }
2804 
2805         rev->eof = 1;
2806         c->error = 1;
2807         err = rev->kq_errno;
2808 
2809         goto closed;
2810     }
2811 
2812 #endif
2813 
2814 #if (NGX_HAVE_EPOLLRDHUP)
2815 
2816     if ((ngx_event_flags & NGX_USE_EPOLL_EVENT) && ngx_use_epoll_rdhup) {
2817         socklen_t  len;
2818 
2819         if (!rev->pending_eof) {
2820             return;
2821         }
2822 
2823         rev->eof = 1;
2824         c->error = 1;
2825 
2826         err = 0;
2827         len = sizeof(ngx_err_t);
2828 
2829         /*
2830          * BSDs and Linux return 0 and set a pending error in err
2831          * Solaris returns -1 and sets errno
2832          */
2833 
2834         if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len)
2835             == -1)
2836         {
2837             err = ngx_socket_errno;
2838         }
2839 
2840         goto closed;
2841     }
2842 
2843 #endif
2844 
2845     n = recv(c->fd, buf, 1, MSG_PEEK);
2846 
2847     if (n == 0) {
2848         rev->eof = 1;
2849         c->error = 1;
2850         err = 0;
2851 
2852         goto closed;
2853 
2854     } else if (n == -1) {
2855         err = ngx_socket_errno;
2856 
2857         if (err != NGX_EAGAIN) {
2858             rev->eof = 1;
2859             c->error = 1;
2860 
2861             goto closed;
2862         }
2863     }
2864 
2865     /* aio does not call this handler */
2866 
2867     if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && rev->active) {
2868 
2869         if (ngx_del_event(rev, NGX_READ_EVENT, 0) != NGX_OK) {
2870             ngx_http_close_request(r, 0);
2871         }
2872     }
2873 
2874     return;
2875 
2876 closed:
2877 
2878     if (err) {
2879         rev->error = 1;
2880     }
2881 
2882     ngx_log_error(NGX_LOG_INFO, c->log, err,
2883                   "client prematurely closed connection");
2884 
2885     ngx_http_finalize_request(r, NGX_HTTP_CLIENT_CLOSED_REQUEST);
2886 }
2887 
2888 
2889 static void
2890 ngx_http_set_keepalive(ngx_http_request_t *r)
2891 {
2892     int                        tcp_nodelay;
2893     ngx_buf_t                 *b, *f;
2894     ngx_chain_t               *cl, *ln;
2895     ngx_event_t               *rev, *wev;
2896     ngx_connection_t          *c;
2897     ngx_http_connection_t     *hc;
2898     ngx_http_core_loc_conf_t  *clcf;
2899 
2900     c = r->connection;
2901     rev = c->read;
2902 
2903     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
2904 
2905     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "set http keepalive handler");
2906 
2907     if (r->discard_body) {
2908         r->write_event_handler = ngx_http_request_empty_handler;
2909         r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
2910         ngx_add_timer(rev, clcf->lingering_timeout);
2911         return;
2912     }
2913 
2914     c->log->action = "closing request";
2915 
2916     hc = r->http_connection;
2917     b = r->header_in;
2918 
2919     if (b->pos < b->last) {
2920 
2921         /* the pipelined request */
2922 
2923         if (b != c->buffer) {
2924 
2925             /*
2926              * If the large header buffers were allocated while the previous
2927              * request processing then we do not use c->buffer for
2928              * the pipelined request (see ngx_http_create_request()).
2929              *
2930              * Now we would move the large header buffers to the free list.
2931              */
2932 
2933             for (cl = hc->busy; cl; /* void */) {
2934                 ln = cl;
2935                 cl = cl->next;
2936 
2937                 if (ln->buf == b) {
2938                     ngx_free_chain(c->pool, ln);
2939                     continue;
2940                 }
2941 
2942                 f = ln->buf;
2943                 f->pos = f->start;
2944                 f->last = f->start;
2945 
2946                 ln->next = hc->free;
2947                 hc->free = ln;
2948             }
2949 
2950             cl = ngx_alloc_chain_link(c->pool);
2951             if (cl == NULL) {
2952                 ngx_http_close_request(r, 0);
2953                 return;
2954             }
2955 
2956             cl->buf = b;
2957             cl->next = NULL;
2958 
2959             hc->busy = cl;
2960             hc->nbusy = 1;
2961         }
2962     }
2963 
2964     /* guard against recursive call from ngx_http_finalize_connection() */
2965     r->keepalive = 0;
2966 
2967     ngx_http_free_request(r, 0);
2968 
2969     c->data = hc;
2970 
2971     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
2972         ngx_http_close_connection(c);
2973         return;
2974     }
2975 
2976     wev = c->write;
2977     wev->handler = ngx_http_empty_handler;
2978 
2979     if (b->pos < b->last) {
2980 
2981         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "pipelined request");
2982 
2983         c->log->action = "reading client pipelined request line";
2984 
2985         r = ngx_http_create_request(c);
2986         if (r == NULL) {
2987             ngx_http_close_connection(c);
2988             return;
2989         }
2990 
2991         r->pipeline = 1;
2992 
2993         c->data = r;
2994 
2995         c->sent = 0;
2996         c->destroyed = 0;
2997 
2998         if (rev->timer_set) {
2999             ngx_del_timer(rev);
3000         }
3001 
3002         rev->handler = ngx_http_process_request_line;
3003         ngx_post_event(rev, &ngx_posted_events);
3004         return;
3005     }
3006 
3007     /*
3008      * To keep a memory footprint as small as possible for an idle keepalive
3009      * connection we try to free c->buffer's memory if it was allocated outside
3010      * the c->pool.  The large header buffers are always allocated outside the
3011      * c->pool and are freed too.
3012      */
3013 
3014     b = c->buffer;
3015 
3016     if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3017 
3018         /*
3019          * the special note for ngx_http_keepalive_handler() that
3020          * c->buffer's memory was freed
3021          */
3022 
3023         b->pos = NULL;
3024 
3025     } else {
3026         b->pos = b->start;
3027         b->last = b->start;
3028     }
3029 
3030     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc free: %p",
3031                    hc->free);
3032 
3033     if (hc->free) {
3034         for (cl = hc->free; cl; /* void */) {
3035             ln = cl;
3036             cl = cl->next;
3037             ngx_pfree(c->pool, ln->buf->start);
3038             ngx_free_chain(c->pool, ln);
3039         }
3040 
3041         hc->free = NULL;
3042     }
3043 
3044     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "hc busy: %p %i",
3045                    hc->busy, hc->nbusy);
3046 
3047     if (hc->busy) {
3048         for (cl = hc->busy; cl; /* void */) {
3049             ln = cl;
3050             cl = cl->next;
3051             ngx_pfree(c->pool, ln->buf->start);
3052             ngx_free_chain(c->pool, ln);
3053         }
3054 
3055         hc->busy = NULL;
3056         hc->nbusy = 0;
3057     }
3058 
3059 #if (NGX_HTTP_SSL)
3060     if (c->ssl) {
3061         ngx_ssl_free_buffer(c);
3062     }
3063 #endif
3064 
3065     rev->handler = ngx_http_keepalive_handler;
3066 
3067     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3068         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3069             ngx_http_close_connection(c);
3070             return;
3071         }
3072     }
3073 
3074     c->log->action = "keepalive";
3075 
3076     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
3077         if (ngx_tcp_push(c->fd) == -1) {
3078             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
3079             ngx_http_close_connection(c);
3080             return;
3081         }
3082 
3083         c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
3084         tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
3085 
3086     } else {
3087         tcp_nodelay = 1;
3088     }
3089 
3090     if (tcp_nodelay && clcf->tcp_nodelay && ngx_tcp_nodelay(c) != NGX_OK) {
3091         ngx_http_close_connection(c);
3092         return;
3093     }
3094 
3095 #if 0
3096     /* if ngx_http_request_t was freed then we need some other place */
3097     r->http_state = NGX_HTTP_KEEPALIVE_STATE;
3098 #endif
3099 
3100     c->idle = 1;
3101     ngx_reusable_connection(c, 1);
3102 
3103     ngx_add_timer(rev, clcf->keepalive_timeout);
3104 
3105     if (rev->ready) {
3106         ngx_post_event(rev, &ngx_posted_events);
3107     }
3108 }
3109 
3110 
3111 static void
3112 ngx_http_keepalive_handler(ngx_event_t *rev)
3113 {
3114     size_t             size;
3115     ssize_t            n;
3116     ngx_buf_t         *b;
3117     ngx_connection_t  *c;
3118 
3119     c = rev->data;
3120 
3121     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http keepalive handler");
3122 
3123     if (rev->timedout || c->close) {
3124         ngx_http_close_connection(c);
3125         return;
3126     }
3127 
3128 #if (NGX_HAVE_KQUEUE)
3129 
3130     if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
3131         if (rev->pending_eof) {
3132             c->log->handler = NULL;
3133             ngx_log_error(NGX_LOG_INFO, c->log, rev->kq_errno,
3134                           "kevent() reported that client %V closed "
3135                           "keepalive connection", &c->addr_text);
3136 #if (NGX_HTTP_SSL)
3137             if (c->ssl) {
3138                 c->ssl->no_send_shutdown = 1;
3139             }
3140 #endif
3141             ngx_http_close_connection(c);
3142             return;
3143         }
3144     }
3145 
3146 #endif
3147 
3148     b = c->buffer;
3149     size = b->end - b->start;
3150 
3151     if (b->pos == NULL) {
3152 
3153         /*
3154          * The c->buffer's memory was freed by ngx_http_set_keepalive().
3155          * However, the c->buffer->start and c->buffer->end were not changed
3156          * to keep the buffer size.
3157          */
3158 
3159         b->pos = ngx_palloc(c->pool, size);
3160         if (b->pos == NULL) {
3161             ngx_http_close_connection(c);
3162             return;
3163         }
3164 
3165         b->start = b->pos;
3166         b->last = b->pos;
3167         b->end = b->pos + size;
3168     }
3169 
3170     /*
3171      * MSIE closes a keepalive connection with RST flag
3172      * so we ignore ECONNRESET here.
3173      */
3174 
3175     c->log_error = NGX_ERROR_IGNORE_ECONNRESET;
3176     ngx_set_socket_errno(0);
3177 
3178     n = c->recv(c, b->last, size);
3179     c->log_error = NGX_ERROR_INFO;
3180 
3181     if (n == NGX_AGAIN) {
3182         if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3183             ngx_http_close_connection(c);
3184             return;
3185         }
3186 
3187         /*
3188          * Like ngx_http_set_keepalive() we are trying to not hold
3189          * c->buffer's memory for a keepalive connection.
3190          */
3191 
3192         if (ngx_pfree(c->pool, b->start) == NGX_OK) {
3193 
3194             /*
3195              * the special note that c->buffer's memory was freed
3196              */
3197 
3198             b->pos = NULL;
3199         }
3200 
3201         return;
3202     }
3203 
3204     if (n == NGX_ERROR) {
3205         ngx_http_close_connection(c);
3206         return;
3207     }
3208 
3209     c->log->handler = NULL;
3210 
3211     if (n == 0) {
3212         ngx_log_error(NGX_LOG_INFO, c->log, ngx_socket_errno,
3213                       "client %V closed keepalive connection", &c->addr_text);
3214         ngx_http_close_connection(c);
3215         return;
3216     }
3217 
3218     b->last += n;
3219 
3220     c->log->handler = ngx_http_log_error;
3221     c->log->action = "reading client request line";
3222 
3223     c->idle = 0;
3224     ngx_reusable_connection(c, 0);
3225 
3226     c->data = ngx_http_create_request(c);
3227     if (c->data == NULL) {
3228         ngx_http_close_connection(c);
3229         return;
3230     }
3231 
3232     c->sent = 0;
3233     c->destroyed = 0;
3234 
3235     ngx_del_timer(rev);
3236 
3237     rev->handler = ngx_http_process_request_line;
3238     ngx_http_process_request_line(rev);
3239 }
3240 
3241 
3242 static void
3243 ngx_http_set_lingering_close(ngx_http_request_t *r)
3244 {
3245     ngx_event_t               *rev, *wev;
3246     ngx_connection_t          *c;
3247     ngx_http_core_loc_conf_t  *clcf;
3248 
3249     c = r->connection;
3250 
3251     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3252 
3253     rev = c->read;
3254     rev->handler = ngx_http_lingering_close_handler;
3255 
3256     r->lingering_time = ngx_time() + (time_t) (clcf->lingering_time / 1000);
3257     ngx_add_timer(rev, clcf->lingering_timeout);
3258 
3259     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3260         ngx_http_close_request(r, 0);
3261         return;
3262     }
3263 
3264     wev = c->write;
3265     wev->handler = ngx_http_empty_handler;
3266 
3267     if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) {
3268         if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) != NGX_OK) {
3269             ngx_http_close_request(r, 0);
3270             return;
3271         }
3272     }
3273 
3274     if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) {
3275         ngx_connection_error(c, ngx_socket_errno,
3276                              ngx_shutdown_socket_n " failed");
3277         ngx_http_close_request(r, 0);
3278         return;
3279     }
3280 
3281     if (rev->ready) {
3282         ngx_http_lingering_close_handler(rev);
3283     }
3284 }
3285 
3286 
3287 static void
3288 ngx_http_lingering_close_handler(ngx_event_t *rev)
3289 {
3290     ssize_t                    n;
3291     ngx_msec_t                 timer;
3292     ngx_connection_t          *c;
3293     ngx_http_request_t        *r;
3294     ngx_http_core_loc_conf_t  *clcf;
3295     u_char                     buffer[NGX_HTTP_LINGERING_BUFFER_SIZE];
3296 
3297     c = rev->data;
3298     r = c->data;
3299 
3300     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
3301                    "http lingering close handler");
3302 
3303     if (rev->timedout) {
3304         ngx_http_close_request(r, 0);
3305         return;
3306     }
3307 
3308     timer = (ngx_msec_t) r->lingering_time - (ngx_msec_t) ngx_time();
3309     if ((ngx_msec_int_t) timer <= 0) {
3310         ngx_http_close_request(r, 0);
3311         return;
3312     }
3313 
3314     do {
3315         n = c->recv(c, buffer, NGX_HTTP_LINGERING_BUFFER_SIZE);
3316 
3317         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "lingering read: %z", n);
3318 
3319         if (n == NGX_ERROR || n == 0) {
3320             ngx_http_close_request(r, 0);
3321             return;
3322         }
3323 
3324     } while (rev->ready);
3325 
3326     if (ngx_handle_read_event(rev, 0) != NGX_OK) {
3327         ngx_http_close_request(r, 0);
3328         return;
3329     }
3330 
3331     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3332 
3333     timer *= 1000;
3334 
3335     if (timer > clcf->lingering_timeout) {
3336         timer = clcf->lingering_timeout;
3337     }
3338 
3339     ngx_add_timer(rev, timer);
3340 }
3341 
3342 
3343 void
3344 ngx_http_empty_handler(ngx_event_t *wev)
3345 {
3346     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
3347 
3348     return;
3349 }
3350 
3351 
3352 void
3353 ngx_http_request_empty_handler(ngx_http_request_t *r)
3354 {
3355     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3356                    "http request empty handler");
3357 
3358     return;
3359 }
3360 
3361 
3362 ngx_int_t
3363 ngx_http_send_special(ngx_http_request_t *r, ngx_uint_t flags)
3364 {
3365     ngx_buf_t    *b;
3366     ngx_chain_t   out;
3367 
3368     b = ngx_calloc_buf(r->pool);
3369     if (b == NULL) {
3370         return NGX_ERROR;
3371     }
3372 
3373     if (flags & NGX_HTTP_LAST) {
3374 
3375         if (r == r->main && !r->post_action) {
3376             b->last_buf = 1;
3377 
3378         } else {
3379             b->sync = 1;
3380             b->last_in_chain = 1;
3381         }
3382     }
3383 
3384     if (flags & NGX_HTTP_FLUSH) {
3385         b->flush = 1;
3386     }
3387 
3388     out.buf = b;
3389     out.next = NULL;
3390 
3391     return ngx_http_output_filter(r, &out);
3392 }
3393 
3394 
3395 static ngx_int_t
3396 ngx_http_post_action(ngx_http_request_t *r)
3397 {
3398     ngx_http_core_loc_conf_t  *clcf;
3399 
3400     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3401 
3402     if (clcf->post_action.data == NULL) {
3403         return NGX_DECLINED;
3404     }
3405 
3406     if (r->post_action && r->uri_changes == 0) {
3407         return NGX_DECLINED;
3408     }
3409 
3410     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
3411                    "post action: \"%V\"", &clcf->post_action);
3412 
3413     r->main->count--;
3414 
3415     r->http_version = NGX_HTTP_VERSION_9;
3416     r->header_only = 1;
3417     r->post_action = 1;
3418 
3419     r->read_event_handler = ngx_http_block_reading;
3420 
3421     if (clcf->post_action.data[0] == '/') {
3422         ngx_http_internal_redirect(r, &clcf->post_action, NULL);
3423 
3424     } else {
3425         ngx_http_named_location(r, &clcf->post_action);
3426     }
3427 
3428     return NGX_OK;
3429 }
3430 
3431 
3432 static void
3433 ngx_http_close_request(ngx_http_request_t *r, ngx_int_t rc)
3434 {
3435     ngx_connection_t  *c;
3436 
3437     r = r->main;
3438     c = r->connection;
3439 
3440     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
3441                    "http request count:%d blk:%d", r->count, r->blocked);
3442 
3443     if (r->count == 0) {
3444         ngx_log_error(NGX_LOG_ALERT, c->log, 0, "http request count is zero");
3445     }
3446 
3447     r->count--;
3448 
3449     if (r->count || r->blocked) {
3450         return;
3451     }
3452 
3453 #if (NGX_HTTP_V2)
3454     if (r->stream) {
3455         ngx_http_v2_close_stream(r->stream, rc);
3456         return;
3457     }
3458 #endif
3459 
3460     ngx_http_free_request(r, rc);
3461     ngx_http_close_connection(c);
3462 }
3463 
3464 
3465 void
3466 ngx_http_free_request(ngx_http_request_t *r, ngx_int_t rc)
3467 {
3468     ngx_log_t                 *log;
3469     ngx_pool_t                *pool;
3470     struct linger              linger;
3471     ngx_http_cleanup_t        *cln;
3472     ngx_http_log_ctx_t        *ctx;
3473     ngx_http_core_loc_conf_t  *clcf;
3474 
3475     log = r->connection->log;
3476 
3477     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http close request");
3478 
3479     if (r->pool == NULL) {
3480         ngx_log_error(NGX_LOG_ALERT, log, 0, "http request already closed");
3481         return;
3482     }
3483 
3484     cln = r->cleanup;
3485     r->cleanup = NULL;
3486 
3487     while (cln) {
3488         if (cln->handler) {
3489             cln->handler(cln->data);
3490         }
3491 
3492         cln = cln->next;
3493     }
3494 
3495 #if (NGX_STAT_STUB)
3496 
3497     if (r->stat_reading) {
3498         (void) ngx_atomic_fetch_add(ngx_stat_reading, -1);
3499     }
3500 
3501     if (r->stat_writing) {
3502         (void) ngx_atomic_fetch_add(ngx_stat_writing, -1);
3503     }
3504 
3505 #endif
3506 
3507     if (rc > 0 && (r->headers_out.status == 0 || r->connection->sent == 0)) {
3508         r->headers_out.status = rc;
3509     }
3510 
3511     log->action = "logging request";
3512 
3513     ngx_http_log_request(r);
3514 
3515     log->action = "closing request";
3516 
3517     if (r->connection->timedout) {
3518         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
3519 
3520         if (clcf->reset_timedout_connection) {
3521             linger.l_onoff = 1;
3522             linger.l_linger = 0;
3523 
3524             if (setsockopt(r->connection->fd, SOL_SOCKET, SO_LINGER,
3525                            (const void *) &linger, sizeof(struct linger)) == -1)
3526             {
3527                 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno,
3528                               "setsockopt(SO_LINGER) failed");
3529             }
3530         }
3531     }
3532 
3533     /* the various request strings were allocated from r->pool */
3534     ctx = log->data;
3535     ctx->request = NULL;
3536 
3537     r->request_line.len = 0;
3538 
3539     r->connection->destroyed = 1;
3540 
3541     /*
3542      * Setting r->pool to NULL will increase probability to catch double close
3543      * of request since the request object is allocated from its own pool.
3544      */
3545 
3546     pool = r->pool;
3547     r->pool = NULL;
3548 
3549     ngx_destroy_pool(pool);
3550 }
3551 
3552 
3553 static void
3554 ngx_http_log_request(ngx_http_request_t *r)
3555 {
3556     ngx_uint_t                  i, n;
3557     ngx_http_handler_pt        *log_handler;
3558     ngx_http_core_main_conf_t  *cmcf;
3559 
3560     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
3561 
3562     log_handler = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.elts;
3563     n = cmcf->phases[NGX_HTTP_LOG_PHASE].handlers.nelts;
3564 
3565     for (i = 0; i < n; i++) {
3566         log_handler[i](r);
3567     }
3568 }
3569 
3570 
3571 void
3572 ngx_http_close_connection(ngx_connection_t *c)
3573 {
3574     ngx_pool_t  *pool;
3575 
3576     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
3577                    "close http connection: %d", c->fd);
3578 
3579 #if (NGX_HTTP_SSL)
3580 
3581     if (c->ssl) {
3582         if (ngx_ssl_shutdown(c) == NGX_AGAIN) {
3583             c->ssl->handler = ngx_http_close_connection;
3584             return;
3585         }
3586     }
3587 
3588 #endif
3589 
3590 #if (NGX_STAT_STUB)
3591     (void) ngx_atomic_fetch_add(ngx_stat_active, -1);
3592 #endif
3593 
3594     c->destroyed = 1;
3595 
3596     pool = c->pool;
3597 
3598     ngx_close_connection(c);
3599 
3600     ngx_destroy_pool(pool);
3601 }
3602 
3603 
3604 static u_char *
3605 ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
3606 {
3607     u_char              *p;
3608     ngx_http_request_t  *r;
3609     ngx_http_log_ctx_t  *ctx;
3610 
3611     if (log->action) {
3612         p = ngx_snprintf(buf, len, " while %s", log->action);
3613         len -= p - buf;
3614         buf = p;
3615     }
3616 
3617     ctx = log->data;
3618 
3619     p = ngx_snprintf(buf, len, ", client: %V", &ctx->connection->addr_text);
3620     len -= p - buf;
3621 
3622     r = ctx->request;
3623 
3624     if (r) {
3625         return r->log_handler(r, ctx->current_request, p, len);
3626 
3627     } else {
3628         p = ngx_snprintf(p, len, ", server: %V",
3629                          &ctx->connection->listening->addr_text);
3630     }
3631 
3632     return p;
3633 }
3634 
3635 
3636 static u_char *
3637 ngx_http_log_error_handler(ngx_http_request_t *r, ngx_http_request_t *sr,
3638     u_char *buf, size_t len)
3639 {
3640     char                      *uri_separator;
3641     u_char                    *p;
3642     ngx_http_upstream_t       *u;
3643     ngx_http_core_srv_conf_t  *cscf;
3644 
3645     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
3646 
3647     p = ngx_snprintf(buf, len, ", server: %V", &cscf->server_name);
3648     len -= p - buf;
3649     buf = p;
3650 
3651     if (r->request_line.data == NULL && r->request_start) {
3652         for (p = r->request_start; p < r->header_in->last; p++) {
3653             if (*p == CR || *p == LF) {
3654                 break;
3655             }
3656         }
3657 
3658         r->request_line.len = p - r->request_start;
3659         r->request_line.data = r->request_start;
3660     }
3661 
3662     if (r->request_line.len) {
3663         p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
3664         len -= p - buf;
3665         buf = p;
3666     }
3667 
3668     if (r != sr) {
3669         p = ngx_snprintf(buf, len, ", subrequest: \"%V\"", &sr->uri);
3670         len -= p - buf;
3671         buf = p;
3672     }
3673 
3674     u = sr->upstream;
3675 
3676     if (u && u->peer.name) {
3677 
3678         uri_separator = "";
3679 
3680 #if (NGX_HAVE_UNIX_DOMAIN)
3681         if (u->peer.sockaddr && u->peer.sockaddr->sa_family == AF_UNIX) {
3682             uri_separator = ":";
3683         }
3684 #endif
3685 
3686         p = ngx_snprintf(buf, len, ", upstream: \"%V%V%s%V\"",
3687                          &u->schema, u->peer.name,
3688                          uri_separator, &u->uri);
3689         len -= p - buf;
3690         buf = p;
3691     }
3692 
3693     if (r->headers_in.host) {
3694         p = ngx_snprintf(buf, len, ", host: \"%V\"",
3695                          &r->headers_in.host->value);
3696         len -= p - buf;
3697         buf = p;
3698     }
3699 
3700     if (r->headers_in.referer) {
3701         p = ngx_snprintf(buf, len, ", referrer: \"%V\"",
3702                          &r->headers_in.referer->value);
3703         buf = p;
3704     }
3705 
3706     return buf;
3707 }