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