~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/http/ngx_http_request.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.