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