1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_router.h> 8#include <nxt_http.h> 9 10 11/* 12 * nxt_h1p_conn_ prefix is used for connection handlers. 13 * nxt_h1p_request_ prefix is used for HTTP/1 protocol request methods. 14 */ 15 16static ssize_t nxt_h1p_conn_io_read_handler(nxt_conn_t *c); 17static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data); 18static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data); 19static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, 20 void *data); 21static nxt_int_t nxt_h1p_header_process(nxt_h1proto_t *h1p, 22 nxt_http_request_t *r); 23static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task, 24 nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf); 25static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, 26 uintptr_t data); 27static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, 28 uintptr_t data); 29static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r); 30static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, 31 void *data); 32static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r); 33static void nxt_h1p_request_header_send(nxt_task_t *task, 34 nxt_http_request_t *r); 35static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, 36 nxt_buf_t *out); 37static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, 38 nxt_buf_t *out); 39static void nxt_h1p_conn_request_sent(nxt_task_t *task, void *obj, void *data); 40static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task, 41 nxt_http_proto_t proto); 42static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, 43 nxt_buf_t *last); 44static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, 45 nxt_socket_conf_joint_t *joint); 46static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, 47 nxt_conn_t *c); 48static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data); 49static void nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data); 50static nxt_msec_t nxt_h1p_conn_timeout_value(nxt_conn_t *c, 51 uintptr_t data); 52static void nxt_h1p_close(nxt_task_t *task, nxt_conn_t *c); 53static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data); 54static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data); 55static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, 56 void *data); 57static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, 58 void *data); 59static nxt_msec_t nxt_h1p_conn_request_timeout_value(nxt_conn_t *c, 60 uintptr_t data); 61nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_http_request_t *r); 62 63 64static const nxt_conn_state_t nxt_h1p_idle_state; 65static const nxt_conn_state_t nxt_h1p_header_parse_state; 66static const nxt_conn_state_t nxt_h1p_read_body_state; 67static const nxt_conn_state_t nxt_h1p_send_state; 68static const nxt_conn_state_t nxt_h1p_keepalive_state; 69static const nxt_conn_state_t nxt_h1p_close_state; 70 71 72const nxt_http_proto_body_read_t nxt_http_proto_body_read[3] = { 73 nxt_h1p_request_body_read, 74 NULL, 75 NULL, 76}; 77 78 79const nxt_http_proto_local_addr_t nxt_http_proto_local_addr[3] = { 80 nxt_h1p_request_local_addr, 81 NULL, 82 NULL, 83}; 84 85 86const nxt_http_proto_header_send_t nxt_http_proto_header_send[3] = { 87 nxt_h1p_request_header_send, 88 NULL, 89 NULL, 90}; 91 92 93const nxt_http_proto_send_t nxt_http_proto_send[3] = { 94 nxt_h1p_request_send, 95 NULL, 96 NULL, 97}; 98 99 100const nxt_http_proto_body_bytes_sent_t nxt_http_proto_body_bytes_sent[3] = { 101 nxt_h1p_request_body_bytes_sent, 102 NULL, 103 NULL, 104}; 105 106 107const nxt_http_proto_discard_t nxt_http_proto_discard[3] = { 108 nxt_h1p_request_discard, 109 NULL, 110 NULL, 111}; 112 113 114const nxt_http_proto_close_t nxt_http_proto_close[3] = { 115 nxt_h1p_request_close, 116 NULL, 117 NULL, 118}; 119 120 121static nxt_lvlhsh_t nxt_h1p_fields_hash; 122 123static nxt_http_field_proc_t nxt_h1p_fields[] = { 124 { nxt_string("Connection"), &nxt_h1p_connection, 0 }, 125 { nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0 }, 126 127 { nxt_string("Host"), &nxt_http_request_host, 0 }, 128 { nxt_string("Cookie"), &nxt_http_request_field, 129 offsetof(nxt_http_request_t, cookie) }, 130 { nxt_string("Referer"), &nxt_http_request_field, 131 offsetof(nxt_http_request_t, referer) }, 132 { nxt_string("User-Agent"), &nxt_http_request_field, 133 offsetof(nxt_http_request_t, user_agent) }, 134 { nxt_string("Content-Type"), &nxt_http_request_field, 135 offsetof(nxt_http_request_t, content_type) }, 136 { nxt_string("Content-Length"), &nxt_http_request_content_length, 0 }, 137}; 138 139 140nxt_int_t 141nxt_h1p_init(nxt_task_t *task, nxt_runtime_t *rt) 142{ 143 return nxt_http_fields_hash(&nxt_h1p_fields_hash, rt->mem_pool, 144 nxt_h1p_fields, nxt_nitems(nxt_h1p_fields)); 145} 146 147 148void 149nxt_http_conn_init(nxt_task_t *task, void *obj, void *data) 150{ 151 nxt_conn_t *c; 152 nxt_socket_conf_t *skcf; 153 nxt_event_engine_t *engine; 154 nxt_listen_event_t *lev; 155 nxt_socket_conf_joint_t *joint; 156 157 c = obj; 158 lev = data; 159 160 nxt_debug(task, "http conn init"); 161 162 joint = lev->socket.data; 163 skcf = joint->socket_conf; 164 c->local = skcf->sockaddr; 165 166 engine = task->thread->engine; 167 c->read_work_queue = &engine->fast_work_queue; 168 c->write_work_queue = &engine->fast_work_queue; 169 170 c->read_state = &nxt_h1p_idle_state; 171 172 nxt_conn_read(engine, c); 173} 174 175 176static const nxt_conn_state_t nxt_h1p_idle_state 177 nxt_aligned(64) = 178{ 179 .ready_handler = nxt_h1p_conn_proto_init, 180 .close_handler = nxt_h1p_conn_error, 181 .error_handler = nxt_h1p_conn_error, 182 183 .io_read_handler = nxt_h1p_conn_io_read_handler, 184 185 .timer_handler = nxt_h1p_conn_timeout, 186 .timer_value = nxt_h1p_conn_timeout_value, 187 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 188 .timer_autoreset = 1, 189}; 190 191 192static ssize_t 193nxt_h1p_conn_io_read_handler(nxt_conn_t *c) 194{ 195 size_t size; 196 ssize_t n; 197 nxt_buf_t *b; 198 nxt_socket_conf_joint_t *joint; 199 200 joint = c->listen->socket.data; 201 size = joint->socket_conf->header_buffer_size; 202 203 b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 204 if (nxt_slow_path(b == NULL)) { 205 c->socket.error = NXT_ENOMEM; 206 return NXT_ERROR; 207 } 208 209 n = c->io->recvbuf(c, b); 210 211 if (n > 0) { 212 c->read = b; 213 214 } else { 215 nxt_mp_free(c->mem_pool, b); 216 } 217 218 return n; 219} 220 221 222static void 223nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data) 224{ 225 nxt_conn_t *c; 226 nxt_h1proto_t *h1p; 227 228 c = obj; 229 230 nxt_debug(task, "h1p conn proto init"); 231 232 h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t)); 233 if (nxt_slow_path(h1p == NULL)) { 234 nxt_h1p_close(task, c); 235 return; 236 } 237 238 c->socket.data = h1p; 239 h1p->conn = c; 240 241 nxt_h1p_conn_request_init(task, c, h1p); 242} 243 244 245static void 246nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) 247{ 248 nxt_int_t ret; 249 nxt_conn_t *c; 250 nxt_h1proto_t *h1p; 251 nxt_http_request_t *r; 252 nxt_socket_conf_joint_t *joint; 253 254 c = obj; 255 h1p = data; 256 257 nxt_debug(task, "h1p conn request init"); 258 259 r = nxt_http_request_create(task); 260 261 if (nxt_fast_path(r != NULL)) { 262 h1p->request = r; 263 r->proto.h1 = h1p; 264 265 r->remote = c->remote; 266 267 ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); 268 269 if (nxt_fast_path(ret == NXT_OK)) { 270 joint = c->listen->socket.data; 271 joint->count++; 272 273 r->conf = joint; 274 c->local = joint->socket_conf->sockaddr; 275 276 nxt_h1p_conn_request_header_parse(task, c, h1p); 277 return; 278 } 279 280 /* 281 * The request is very incomplete here, 282 * so "internal server error" useless here. 283 */ 284 nxt_mp_release(r->mem_pool); 285 } 286 287 nxt_h1p_close(task, c); 288} 289 290 291static const nxt_conn_state_t nxt_h1p_header_parse_state 292 nxt_aligned(64) = 293{ 294 .ready_handler = nxt_h1p_conn_request_header_parse, 295 .close_handler = nxt_h1p_conn_request_error, 296 .error_handler = nxt_h1p_conn_request_error, 297 298 .timer_handler = nxt_h1p_conn_request_timeout, 299 .timer_value = nxt_h1p_conn_request_timeout_value, 300 .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 301}; 302 303 304static void 305nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, void *data) 306{ 307 nxt_int_t ret; 308 nxt_conn_t *c; 309 nxt_h1proto_t *h1p; 310 nxt_http_status_t status; 311 nxt_http_request_t *r; 312 313 c = obj; 314 h1p = data; 315 316 nxt_debug(task, "h1p conn header parse"); 317 318 ret = nxt_http_parse_request(&h1p->parser, &c->read->mem); 319 320 ret = nxt_expect(NXT_DONE, ret); 321 322 if (ret != NXT_AGAIN) { 323 nxt_timer_disable(task->thread->engine, &c->read_timer); 324 } 325 326 r = h1p->request; 327 328 switch (ret) { 329 330 case NXT_DONE: 331 /* 332 * By default the keepalive mode is disabled in HTTP/1.0 and 333 * enabled in HTTP/1.1. The mode can be overridden later by 334 * the "Connection" field processed in nxt_h1p_connection(). 335 */ 336 h1p->keepalive = (h1p->parser.version.s.minor != '0'); 337 338 ret = nxt_h1p_header_process(h1p, r); 339 340 if (nxt_fast_path(ret == NXT_OK)) { 341 r->state->ready_handler(task, r, NULL); 342 return; 343 } 344 345 /* ret == NXT_ERROR */ 346 status = NXT_HTTP_BAD_REQUEST; 347 348 goto error; 349 350 case NXT_AGAIN: 351 status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf); 352 353 if (nxt_fast_path(status == NXT_OK)) { 354 c->read_state = &nxt_h1p_header_parse_state; 355 356 nxt_conn_read(task->thread->engine, c); 357 return; 358 } 359 360 break; 361 362 case NXT_HTTP_PARSE_INVALID: 363 status = NXT_HTTP_BAD_REQUEST; 364 break; 365 366 case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: 367 status = NXT_HTTP_VERSION_NOT_SUPPORTED; 368 break; 369 370 case NXT_HTTP_PARSE_TOO_LARGE_FIELD: 371 status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; 372 break; 373 374 default: 375 case NXT_ERROR: 376 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 377 break; 378 } 379 380 (void) nxt_h1p_header_process(h1p, r); 381 382error: 383 384 nxt_http_request_error(task, r, status); 385} 386 387 388static nxt_int_t 389nxt_h1p_header_process(nxt_h1proto_t *h1p, nxt_http_request_t *r) 390{ 391 r->target.start = h1p->parser.target_start; 392 r->target.length = h1p->parser.target_end - h1p->parser.target_start; 393 394 if (h1p->parser.version.ui64 != 0) { 395 r->version.start = h1p->parser.version.str; 396 r->version.length = sizeof(h1p->parser.version.str); 397 } 398 399 r->method = &h1p->parser.method; 400 r->path = &h1p->parser.path; 401 r->args = &h1p->parser.args; 402 403 r->fields = h1p->parser.fields; 404 405 return nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r); 406} 407 408 409static nxt_int_t 410nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c, 411 nxt_socket_conf_t *skcf) 412{ 413 size_t size, used; 414 nxt_buf_t *in, *b; 415 416 in = c->read; 417 418 if (nxt_buf_mem_free_size(&in->mem) == 0) { 419 size = skcf->large_header_buffer_size; 420 used = nxt_buf_mem_used_size(&in->mem); 421 422 if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) { 423 return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; 424 } 425 426 b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 427 if (nxt_slow_path(b == NULL)) { 428 return NXT_HTTP_INTERNAL_SERVER_ERROR; 429 } 430 431 b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used); 432 433 in->next = h1p->buffers; 434 h1p->buffers = in; 435 h1p->nbuffers++; 436 437 c->read = b; 438 } 439 440 return NXT_OK; 441} 442 443 444static nxt_int_t 445nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data) 446{ 447 nxt_http_request_t *r; 448 449 r = ctx; 450 451 if (field->value_length == 5 && nxt_memcmp(field->value, "close", 5) == 0) { 452 r->proto.h1->keepalive = 0; 453 } 454 455 return NXT_OK; 456} 457 458 459static nxt_int_t 460nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data) 461{ 462 nxt_http_te_t te; 463 nxt_http_request_t *r; 464 465 r = ctx; 466 467 if (field->value_length == 7 468 && nxt_memcmp(field->value, "chunked", 7) == 0) 469 { 470 te = NXT_HTTP_TE_CHUNKED; 471 472 } else { 473 te = NXT_HTTP_TE_UNSUPPORTED; 474 } 475 476 r->proto.h1->transfer_encoding = te; 477 478 return NXT_OK; 479} 480 481 482static void 483nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r) 484{ 485 size_t size, body_length; 486 nxt_buf_t *in, *b; 487 nxt_conn_t *c; 488 nxt_h1proto_t *h1p; 489 nxt_http_status_t status; 490 491 h1p = r->proto.h1; 492 493 nxt_debug(task, "h1p request body read %O te:%d", 494 r->content_length_n, h1p->transfer_encoding); 495 496 switch (h1p->transfer_encoding) { 497 498 case NXT_HTTP_TE_CHUNKED: 499 status = NXT_HTTP_LENGTH_REQUIRED; 500 goto error; 501 502 case NXT_HTTP_TE_UNSUPPORTED: 503 status = NXT_HTTP_NOT_IMPLEMENTED; 504 goto error; 505 506 default: 507 case NXT_HTTP_TE_NONE: 508 break; 509 } 510 511 if (r->content_length_n == -1 || r->content_length_n == 0) { 512 goto ready; 513 } 514 515 if (r->content_length_n > (nxt_off_t) r->conf->socket_conf->max_body_size) { 516 status = NXT_HTTP_PAYLOAD_TOO_LARGE; 517 goto error; 518 } 519 520 body_length = (size_t) r->content_length_n; 521 522 b = r->body; 523 524 if (b == NULL) { 525 b = nxt_buf_mem_alloc(r->mem_pool, body_length, 0); 526 if (nxt_slow_path(b == NULL)) { 527 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 528 goto error; 529 } 530 531 r->body = b; 532 } 533 534 in = h1p->conn->read; 535 536 size = nxt_buf_mem_used_size(&in->mem); 537 538 if (size != 0) { 539 if (size > body_length) { 540 size = body_length; 541 } 542 543 b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size); 544 in->mem.pos += size; 545 } 546 547 size = nxt_buf_mem_free_size(&b->mem); 548 549 nxt_debug(task, "h1p body rest: %uz", size); 550 551 if (size != 0) { 552 in->next = h1p->buffers; 553 h1p->buffers = in; 554 555 c = h1p->conn; 556 c->read = b; 557 c->read_state = &nxt_h1p_read_body_state; 558 559 nxt_conn_read(task->thread->engine, c); 560 return; 561 } 562 563ready: 564 565 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 566 r->state->ready_handler, task, r, NULL); 567 568 return; 569 570error: 571 572 h1p->keepalive = 0; 573 574 nxt_http_request_error(task, r, status); 575} 576 577 578static const nxt_conn_state_t nxt_h1p_read_body_state 579 nxt_aligned(64) = 580{ 581 .ready_handler = nxt_h1p_conn_request_body_read, 582 .close_handler = nxt_h1p_conn_request_error, 583 .error_handler = nxt_h1p_conn_request_error, 584 585 .timer_handler = nxt_h1p_conn_request_timeout, 586 .timer_value = nxt_h1p_conn_request_timeout_value, 587 .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout), 588 .timer_autoreset = 1, 589}; 590 591 592static void 593nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data) 594{ 595 size_t size; 596 nxt_conn_t *c; 597 nxt_h1proto_t *h1p; 598 nxt_http_request_t *r; 599 nxt_event_engine_t *engine; 600 601 c = obj; 602 h1p = data; 603 604 nxt_debug(task, "h1p conn request body read"); 605 606 size = nxt_buf_mem_free_size(&c->read->mem); 607 608 nxt_debug(task, "h1p body rest: %uz", size); 609 610 engine = task->thread->engine; 611 612 if (size != 0) { 613 nxt_conn_read(engine, c); 614 615 } else { 616 c->read = NULL; 617 r = h1p->request; 618 619 nxt_work_queue_add(&engine->fast_work_queue, r->state->ready_handler, 620 task, r, NULL); 621 } 622} 623 624 625static void 626nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r) 627{ 628 r->local = nxt_conn_local_addr(task, r->proto.h1->conn); 629} 630 631 632#define NXT_HTTP_LAST_SUCCESS \ 633 (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1) 634 635static const nxt_str_t nxt_http_success[] = { 636 nxt_string("HTTP/1.1 200 OK\r\n"), 637 nxt_string("HTTP/1.1 201 Created\r\n"), 638 nxt_string("HTTP/1.1 202 Accepted\r\n"), 639 nxt_string("HTTP/1.1 203 Non-Authoritative Information\r\n"), 640 nxt_string("HTTP/1.1 204 No Content\r\n"), 641 nxt_string("HTTP/1.1 205 Reset Content\r\n"), 642 nxt_string("HTTP/1.1 206 Partial Content\r\n"), 643}; 644 645 646#define NXT_HTTP_LAST_REDIRECTION \ 647 (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1) 648 649static const nxt_str_t nxt_http_redirection[] = { 650 nxt_string("HTTP/1.1 300 Multiple Choices\r\n"), 651 nxt_string("HTTP/1.1 301 Moved Permanently\r\n"), 652 nxt_string("HTTP/1.1 302 Found\r\n"), 653 nxt_string("HTTP/1.1 303 See Other\r\n"), 654 nxt_string("HTTP/1.1 304 Not Modified\r\n"), 655}; 656 657 658#define NXT_HTTP_LAST_CLIENT_ERROR \ 659 (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1) 660 661static const nxt_str_t nxt_http_client_error[] = { 662 nxt_string("HTTP/1.1 400 Bad Request\r\n"), 663 nxt_string("HTTP/1.1 401 Unauthorized\r\n"), 664 nxt_string("HTTP/1.1 402 Payment Required\r\n"), 665 nxt_string("HTTP/1.1 403 Forbidden\r\n"), 666 nxt_string("HTTP/1.1 404 Not Found\r\n"), 667 nxt_string("HTTP/1.1 405 Method Not Allowed\r\n"), 668 nxt_string("HTTP/1.1 406 Not Acceptable\r\n"), 669 nxt_string("HTTP/1.1 407 Proxy Authentication Required\r\n"), 670 nxt_string("HTTP/1.1 408 Request Timeout\r\n"), 671 nxt_string("HTTP/1.1 409 Conflict\r\n"), 672 nxt_string("HTTP/1.1 410 Gone\r\n"), 673 nxt_string("HTTP/1.1 411 Length Required\r\n"), 674 nxt_string("HTTP/1.1 412 Precondition Failed\r\n"), 675 nxt_string("HTTP/1.1 413 Payload Too Large\r\n"), 676 nxt_string("HTTP/1.1 414 URI Too Long\r\n"), 677 nxt_string("HTTP/1.1 415 Unsupported Media Type\r\n"), 678 nxt_string("HTTP/1.1 416 Range Not Satisfiable\r\n"), 679 nxt_string("HTTP/1.1 417 Expectation Failed\r\n"), 680 nxt_string("HTTP/1.1 418\r\n"), 681 nxt_string("HTTP/1.1 419\r\n"), 682 nxt_string("HTTP/1.1 420\r\n"), 683 nxt_string("HTTP/1.1 421\r\n"), 684 nxt_string("HTTP/1.1 422\r\n"), 685 nxt_string("HTTP/1.1 423\r\n"), 686 nxt_string("HTTP/1.1 424\r\n"), 687 nxt_string("HTTP/1.1 425\r\n"), 688 nxt_string("HTTP/1.1 426\r\n"), 689 nxt_string("HTTP/1.1 427\r\n"), 690 nxt_string("HTTP/1.1 428\r\n"), 691 nxt_string("HTTP/1.1 429\r\n"), 692 nxt_string("HTTP/1.1 430\r\n"), 693 nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"), 694}; 695 696 697#define NXT_HTTP_LAST_SERVER_ERROR \ 698 (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1) 699 700static const nxt_str_t nxt_http_server_error[] = { 701 nxt_string("HTTP/1.1 500 Internal Server Error\r\n"), 702 nxt_string("HTTP/1.1 501 Not Implemented\r\n"), 703 nxt_string("HTTP/1.1 502 Bad Gateway\r\n"), 704 nxt_string("HTTP/1.1 503 Service Unavailable\r\n"), 705 nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"), 706 nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"), 707}; 708 709
| 1 2/* 3 * Copyright (C) Igor Sysoev 4 * Copyright (C) NGINX, Inc. 5 */ 6 7#include <nxt_router.h> 8#include <nxt_http.h> 9 10 11/* 12 * nxt_h1p_conn_ prefix is used for connection handlers. 13 * nxt_h1p_request_ prefix is used for HTTP/1 protocol request methods. 14 */ 15 16static ssize_t nxt_h1p_conn_io_read_handler(nxt_conn_t *c); 17static void nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data); 18static void nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data); 19static void nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, 20 void *data); 21static nxt_int_t nxt_h1p_header_process(nxt_h1proto_t *h1p, 22 nxt_http_request_t *r); 23static nxt_int_t nxt_h1p_header_buffer_test(nxt_task_t *task, 24 nxt_h1proto_t *h1p, nxt_conn_t *c, nxt_socket_conf_t *skcf); 25static nxt_int_t nxt_h1p_connection(void *ctx, nxt_http_field_t *field, 26 uintptr_t data); 27static nxt_int_t nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, 28 uintptr_t data); 29static void nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r); 30static void nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, 31 void *data); 32static void nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r); 33static void nxt_h1p_request_header_send(nxt_task_t *task, 34 nxt_http_request_t *r); 35static void nxt_h1p_request_send(nxt_task_t *task, nxt_http_request_t *r, 36 nxt_buf_t *out); 37static nxt_buf_t *nxt_h1p_chunk_create(nxt_task_t *task, nxt_http_request_t *r, 38 nxt_buf_t *out); 39static void nxt_h1p_conn_request_sent(nxt_task_t *task, void *obj, void *data); 40static nxt_off_t nxt_h1p_request_body_bytes_sent(nxt_task_t *task, 41 nxt_http_proto_t proto); 42static void nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, 43 nxt_buf_t *last); 44static void nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, 45 nxt_socket_conf_joint_t *joint); 46static void nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, 47 nxt_conn_t *c); 48static void nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data); 49static void nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data); 50static nxt_msec_t nxt_h1p_conn_timeout_value(nxt_conn_t *c, 51 uintptr_t data); 52static void nxt_h1p_close(nxt_task_t *task, nxt_conn_t *c); 53static void nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data); 54static void nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data); 55static void nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, 56 void *data); 57static void nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, 58 void *data); 59static nxt_msec_t nxt_h1p_conn_request_timeout_value(nxt_conn_t *c, 60 uintptr_t data); 61nxt_inline void nxt_h1p_request_error(nxt_task_t *task, nxt_http_request_t *r); 62 63 64static const nxt_conn_state_t nxt_h1p_idle_state; 65static const nxt_conn_state_t nxt_h1p_header_parse_state; 66static const nxt_conn_state_t nxt_h1p_read_body_state; 67static const nxt_conn_state_t nxt_h1p_send_state; 68static const nxt_conn_state_t nxt_h1p_keepalive_state; 69static const nxt_conn_state_t nxt_h1p_close_state; 70 71 72const nxt_http_proto_body_read_t nxt_http_proto_body_read[3] = { 73 nxt_h1p_request_body_read, 74 NULL, 75 NULL, 76}; 77 78 79const nxt_http_proto_local_addr_t nxt_http_proto_local_addr[3] = { 80 nxt_h1p_request_local_addr, 81 NULL, 82 NULL, 83}; 84 85 86const nxt_http_proto_header_send_t nxt_http_proto_header_send[3] = { 87 nxt_h1p_request_header_send, 88 NULL, 89 NULL, 90}; 91 92 93const nxt_http_proto_send_t nxt_http_proto_send[3] = { 94 nxt_h1p_request_send, 95 NULL, 96 NULL, 97}; 98 99 100const nxt_http_proto_body_bytes_sent_t nxt_http_proto_body_bytes_sent[3] = { 101 nxt_h1p_request_body_bytes_sent, 102 NULL, 103 NULL, 104}; 105 106 107const nxt_http_proto_discard_t nxt_http_proto_discard[3] = { 108 nxt_h1p_request_discard, 109 NULL, 110 NULL, 111}; 112 113 114const nxt_http_proto_close_t nxt_http_proto_close[3] = { 115 nxt_h1p_request_close, 116 NULL, 117 NULL, 118}; 119 120 121static nxt_lvlhsh_t nxt_h1p_fields_hash; 122 123static nxt_http_field_proc_t nxt_h1p_fields[] = { 124 { nxt_string("Connection"), &nxt_h1p_connection, 0 }, 125 { nxt_string("Transfer-Encoding"), &nxt_h1p_transfer_encoding, 0 }, 126 127 { nxt_string("Host"), &nxt_http_request_host, 0 }, 128 { nxt_string("Cookie"), &nxt_http_request_field, 129 offsetof(nxt_http_request_t, cookie) }, 130 { nxt_string("Referer"), &nxt_http_request_field, 131 offsetof(nxt_http_request_t, referer) }, 132 { nxt_string("User-Agent"), &nxt_http_request_field, 133 offsetof(nxt_http_request_t, user_agent) }, 134 { nxt_string("Content-Type"), &nxt_http_request_field, 135 offsetof(nxt_http_request_t, content_type) }, 136 { nxt_string("Content-Length"), &nxt_http_request_content_length, 0 }, 137}; 138 139 140nxt_int_t 141nxt_h1p_init(nxt_task_t *task, nxt_runtime_t *rt) 142{ 143 return nxt_http_fields_hash(&nxt_h1p_fields_hash, rt->mem_pool, 144 nxt_h1p_fields, nxt_nitems(nxt_h1p_fields)); 145} 146 147 148void 149nxt_http_conn_init(nxt_task_t *task, void *obj, void *data) 150{ 151 nxt_conn_t *c; 152 nxt_socket_conf_t *skcf; 153 nxt_event_engine_t *engine; 154 nxt_listen_event_t *lev; 155 nxt_socket_conf_joint_t *joint; 156 157 c = obj; 158 lev = data; 159 160 nxt_debug(task, "http conn init"); 161 162 joint = lev->socket.data; 163 skcf = joint->socket_conf; 164 c->local = skcf->sockaddr; 165 166 engine = task->thread->engine; 167 c->read_work_queue = &engine->fast_work_queue; 168 c->write_work_queue = &engine->fast_work_queue; 169 170 c->read_state = &nxt_h1p_idle_state; 171 172 nxt_conn_read(engine, c); 173} 174 175 176static const nxt_conn_state_t nxt_h1p_idle_state 177 nxt_aligned(64) = 178{ 179 .ready_handler = nxt_h1p_conn_proto_init, 180 .close_handler = nxt_h1p_conn_error, 181 .error_handler = nxt_h1p_conn_error, 182 183 .io_read_handler = nxt_h1p_conn_io_read_handler, 184 185 .timer_handler = nxt_h1p_conn_timeout, 186 .timer_value = nxt_h1p_conn_timeout_value, 187 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 188 .timer_autoreset = 1, 189}; 190 191 192static ssize_t 193nxt_h1p_conn_io_read_handler(nxt_conn_t *c) 194{ 195 size_t size; 196 ssize_t n; 197 nxt_buf_t *b; 198 nxt_socket_conf_joint_t *joint; 199 200 joint = c->listen->socket.data; 201 size = joint->socket_conf->header_buffer_size; 202 203 b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 204 if (nxt_slow_path(b == NULL)) { 205 c->socket.error = NXT_ENOMEM; 206 return NXT_ERROR; 207 } 208 209 n = c->io->recvbuf(c, b); 210 211 if (n > 0) { 212 c->read = b; 213 214 } else { 215 nxt_mp_free(c->mem_pool, b); 216 } 217 218 return n; 219} 220 221 222static void 223nxt_h1p_conn_proto_init(nxt_task_t *task, void *obj, void *data) 224{ 225 nxt_conn_t *c; 226 nxt_h1proto_t *h1p; 227 228 c = obj; 229 230 nxt_debug(task, "h1p conn proto init"); 231 232 h1p = nxt_mp_zget(c->mem_pool, sizeof(nxt_h1proto_t)); 233 if (nxt_slow_path(h1p == NULL)) { 234 nxt_h1p_close(task, c); 235 return; 236 } 237 238 c->socket.data = h1p; 239 h1p->conn = c; 240 241 nxt_h1p_conn_request_init(task, c, h1p); 242} 243 244 245static void 246nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) 247{ 248 nxt_int_t ret; 249 nxt_conn_t *c; 250 nxt_h1proto_t *h1p; 251 nxt_http_request_t *r; 252 nxt_socket_conf_joint_t *joint; 253 254 c = obj; 255 h1p = data; 256 257 nxt_debug(task, "h1p conn request init"); 258 259 r = nxt_http_request_create(task); 260 261 if (nxt_fast_path(r != NULL)) { 262 h1p->request = r; 263 r->proto.h1 = h1p; 264 265 r->remote = c->remote; 266 267 ret = nxt_http_parse_request_init(&h1p->parser, r->mem_pool); 268 269 if (nxt_fast_path(ret == NXT_OK)) { 270 joint = c->listen->socket.data; 271 joint->count++; 272 273 r->conf = joint; 274 c->local = joint->socket_conf->sockaddr; 275 276 nxt_h1p_conn_request_header_parse(task, c, h1p); 277 return; 278 } 279 280 /* 281 * The request is very incomplete here, 282 * so "internal server error" useless here. 283 */ 284 nxt_mp_release(r->mem_pool); 285 } 286 287 nxt_h1p_close(task, c); 288} 289 290 291static const nxt_conn_state_t nxt_h1p_header_parse_state 292 nxt_aligned(64) = 293{ 294 .ready_handler = nxt_h1p_conn_request_header_parse, 295 .close_handler = nxt_h1p_conn_request_error, 296 .error_handler = nxt_h1p_conn_request_error, 297 298 .timer_handler = nxt_h1p_conn_request_timeout, 299 .timer_value = nxt_h1p_conn_request_timeout_value, 300 .timer_data = offsetof(nxt_socket_conf_t, header_read_timeout), 301}; 302 303 304static void 305nxt_h1p_conn_request_header_parse(nxt_task_t *task, void *obj, void *data) 306{ 307 nxt_int_t ret; 308 nxt_conn_t *c; 309 nxt_h1proto_t *h1p; 310 nxt_http_status_t status; 311 nxt_http_request_t *r; 312 313 c = obj; 314 h1p = data; 315 316 nxt_debug(task, "h1p conn header parse"); 317 318 ret = nxt_http_parse_request(&h1p->parser, &c->read->mem); 319 320 ret = nxt_expect(NXT_DONE, ret); 321 322 if (ret != NXT_AGAIN) { 323 nxt_timer_disable(task->thread->engine, &c->read_timer); 324 } 325 326 r = h1p->request; 327 328 switch (ret) { 329 330 case NXT_DONE: 331 /* 332 * By default the keepalive mode is disabled in HTTP/1.0 and 333 * enabled in HTTP/1.1. The mode can be overridden later by 334 * the "Connection" field processed in nxt_h1p_connection(). 335 */ 336 h1p->keepalive = (h1p->parser.version.s.minor != '0'); 337 338 ret = nxt_h1p_header_process(h1p, r); 339 340 if (nxt_fast_path(ret == NXT_OK)) { 341 r->state->ready_handler(task, r, NULL); 342 return; 343 } 344 345 /* ret == NXT_ERROR */ 346 status = NXT_HTTP_BAD_REQUEST; 347 348 goto error; 349 350 case NXT_AGAIN: 351 status = nxt_h1p_header_buffer_test(task, h1p, c, r->conf->socket_conf); 352 353 if (nxt_fast_path(status == NXT_OK)) { 354 c->read_state = &nxt_h1p_header_parse_state; 355 356 nxt_conn_read(task->thread->engine, c); 357 return; 358 } 359 360 break; 361 362 case NXT_HTTP_PARSE_INVALID: 363 status = NXT_HTTP_BAD_REQUEST; 364 break; 365 366 case NXT_HTTP_PARSE_UNSUPPORTED_VERSION: 367 status = NXT_HTTP_VERSION_NOT_SUPPORTED; 368 break; 369 370 case NXT_HTTP_PARSE_TOO_LARGE_FIELD: 371 status = NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; 372 break; 373 374 default: 375 case NXT_ERROR: 376 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 377 break; 378 } 379 380 (void) nxt_h1p_header_process(h1p, r); 381 382error: 383 384 nxt_http_request_error(task, r, status); 385} 386 387 388static nxt_int_t 389nxt_h1p_header_process(nxt_h1proto_t *h1p, nxt_http_request_t *r) 390{ 391 r->target.start = h1p->parser.target_start; 392 r->target.length = h1p->parser.target_end - h1p->parser.target_start; 393 394 if (h1p->parser.version.ui64 != 0) { 395 r->version.start = h1p->parser.version.str; 396 r->version.length = sizeof(h1p->parser.version.str); 397 } 398 399 r->method = &h1p->parser.method; 400 r->path = &h1p->parser.path; 401 r->args = &h1p->parser.args; 402 403 r->fields = h1p->parser.fields; 404 405 return nxt_http_fields_process(r->fields, &nxt_h1p_fields_hash, r); 406} 407 408 409static nxt_int_t 410nxt_h1p_header_buffer_test(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c, 411 nxt_socket_conf_t *skcf) 412{ 413 size_t size, used; 414 nxt_buf_t *in, *b; 415 416 in = c->read; 417 418 if (nxt_buf_mem_free_size(&in->mem) == 0) { 419 size = skcf->large_header_buffer_size; 420 used = nxt_buf_mem_used_size(&in->mem); 421 422 if (size <= used || h1p->nbuffers >= skcf->large_header_buffers) { 423 return NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE; 424 } 425 426 b = nxt_buf_mem_alloc(c->mem_pool, size, 0); 427 if (nxt_slow_path(b == NULL)) { 428 return NXT_HTTP_INTERNAL_SERVER_ERROR; 429 } 430 431 b->mem.free = nxt_cpymem(b->mem.pos, in->mem.pos, used); 432 433 in->next = h1p->buffers; 434 h1p->buffers = in; 435 h1p->nbuffers++; 436 437 c->read = b; 438 } 439 440 return NXT_OK; 441} 442 443 444static nxt_int_t 445nxt_h1p_connection(void *ctx, nxt_http_field_t *field, uintptr_t data) 446{ 447 nxt_http_request_t *r; 448 449 r = ctx; 450 451 if (field->value_length == 5 && nxt_memcmp(field->value, "close", 5) == 0) { 452 r->proto.h1->keepalive = 0; 453 } 454 455 return NXT_OK; 456} 457 458 459static nxt_int_t 460nxt_h1p_transfer_encoding(void *ctx, nxt_http_field_t *field, uintptr_t data) 461{ 462 nxt_http_te_t te; 463 nxt_http_request_t *r; 464 465 r = ctx; 466 467 if (field->value_length == 7 468 && nxt_memcmp(field->value, "chunked", 7) == 0) 469 { 470 te = NXT_HTTP_TE_CHUNKED; 471 472 } else { 473 te = NXT_HTTP_TE_UNSUPPORTED; 474 } 475 476 r->proto.h1->transfer_encoding = te; 477 478 return NXT_OK; 479} 480 481 482static void 483nxt_h1p_request_body_read(nxt_task_t *task, nxt_http_request_t *r) 484{ 485 size_t size, body_length; 486 nxt_buf_t *in, *b; 487 nxt_conn_t *c; 488 nxt_h1proto_t *h1p; 489 nxt_http_status_t status; 490 491 h1p = r->proto.h1; 492 493 nxt_debug(task, "h1p request body read %O te:%d", 494 r->content_length_n, h1p->transfer_encoding); 495 496 switch (h1p->transfer_encoding) { 497 498 case NXT_HTTP_TE_CHUNKED: 499 status = NXT_HTTP_LENGTH_REQUIRED; 500 goto error; 501 502 case NXT_HTTP_TE_UNSUPPORTED: 503 status = NXT_HTTP_NOT_IMPLEMENTED; 504 goto error; 505 506 default: 507 case NXT_HTTP_TE_NONE: 508 break; 509 } 510 511 if (r->content_length_n == -1 || r->content_length_n == 0) { 512 goto ready; 513 } 514 515 if (r->content_length_n > (nxt_off_t) r->conf->socket_conf->max_body_size) { 516 status = NXT_HTTP_PAYLOAD_TOO_LARGE; 517 goto error; 518 } 519 520 body_length = (size_t) r->content_length_n; 521 522 b = r->body; 523 524 if (b == NULL) { 525 b = nxt_buf_mem_alloc(r->mem_pool, body_length, 0); 526 if (nxt_slow_path(b == NULL)) { 527 status = NXT_HTTP_INTERNAL_SERVER_ERROR; 528 goto error; 529 } 530 531 r->body = b; 532 } 533 534 in = h1p->conn->read; 535 536 size = nxt_buf_mem_used_size(&in->mem); 537 538 if (size != 0) { 539 if (size > body_length) { 540 size = body_length; 541 } 542 543 b->mem.free = nxt_cpymem(b->mem.free, in->mem.pos, size); 544 in->mem.pos += size; 545 } 546 547 size = nxt_buf_mem_free_size(&b->mem); 548 549 nxt_debug(task, "h1p body rest: %uz", size); 550 551 if (size != 0) { 552 in->next = h1p->buffers; 553 h1p->buffers = in; 554 555 c = h1p->conn; 556 c->read = b; 557 c->read_state = &nxt_h1p_read_body_state; 558 559 nxt_conn_read(task->thread->engine, c); 560 return; 561 } 562 563ready: 564 565 nxt_work_queue_add(&task->thread->engine->fast_work_queue, 566 r->state->ready_handler, task, r, NULL); 567 568 return; 569 570error: 571 572 h1p->keepalive = 0; 573 574 nxt_http_request_error(task, r, status); 575} 576 577 578static const nxt_conn_state_t nxt_h1p_read_body_state 579 nxt_aligned(64) = 580{ 581 .ready_handler = nxt_h1p_conn_request_body_read, 582 .close_handler = nxt_h1p_conn_request_error, 583 .error_handler = nxt_h1p_conn_request_error, 584 585 .timer_handler = nxt_h1p_conn_request_timeout, 586 .timer_value = nxt_h1p_conn_request_timeout_value, 587 .timer_data = offsetof(nxt_socket_conf_t, body_read_timeout), 588 .timer_autoreset = 1, 589}; 590 591 592static void 593nxt_h1p_conn_request_body_read(nxt_task_t *task, void *obj, void *data) 594{ 595 size_t size; 596 nxt_conn_t *c; 597 nxt_h1proto_t *h1p; 598 nxt_http_request_t *r; 599 nxt_event_engine_t *engine; 600 601 c = obj; 602 h1p = data; 603 604 nxt_debug(task, "h1p conn request body read"); 605 606 size = nxt_buf_mem_free_size(&c->read->mem); 607 608 nxt_debug(task, "h1p body rest: %uz", size); 609 610 engine = task->thread->engine; 611 612 if (size != 0) { 613 nxt_conn_read(engine, c); 614 615 } else { 616 c->read = NULL; 617 r = h1p->request; 618 619 nxt_work_queue_add(&engine->fast_work_queue, r->state->ready_handler, 620 task, r, NULL); 621 } 622} 623 624 625static void 626nxt_h1p_request_local_addr(nxt_task_t *task, nxt_http_request_t *r) 627{ 628 r->local = nxt_conn_local_addr(task, r->proto.h1->conn); 629} 630 631 632#define NXT_HTTP_LAST_SUCCESS \ 633 (NXT_HTTP_OK + nxt_nitems(nxt_http_success) - 1) 634 635static const nxt_str_t nxt_http_success[] = { 636 nxt_string("HTTP/1.1 200 OK\r\n"), 637 nxt_string("HTTP/1.1 201 Created\r\n"), 638 nxt_string("HTTP/1.1 202 Accepted\r\n"), 639 nxt_string("HTTP/1.1 203 Non-Authoritative Information\r\n"), 640 nxt_string("HTTP/1.1 204 No Content\r\n"), 641 nxt_string("HTTP/1.1 205 Reset Content\r\n"), 642 nxt_string("HTTP/1.1 206 Partial Content\r\n"), 643}; 644 645 646#define NXT_HTTP_LAST_REDIRECTION \ 647 (NXT_HTTP_MULTIPLE_CHOICES + nxt_nitems(nxt_http_redirection) - 1) 648 649static const nxt_str_t nxt_http_redirection[] = { 650 nxt_string("HTTP/1.1 300 Multiple Choices\r\n"), 651 nxt_string("HTTP/1.1 301 Moved Permanently\r\n"), 652 nxt_string("HTTP/1.1 302 Found\r\n"), 653 nxt_string("HTTP/1.1 303 See Other\r\n"), 654 nxt_string("HTTP/1.1 304 Not Modified\r\n"), 655}; 656 657 658#define NXT_HTTP_LAST_CLIENT_ERROR \ 659 (NXT_HTTP_BAD_REQUEST + nxt_nitems(nxt_http_client_error) - 1) 660 661static const nxt_str_t nxt_http_client_error[] = { 662 nxt_string("HTTP/1.1 400 Bad Request\r\n"), 663 nxt_string("HTTP/1.1 401 Unauthorized\r\n"), 664 nxt_string("HTTP/1.1 402 Payment Required\r\n"), 665 nxt_string("HTTP/1.1 403 Forbidden\r\n"), 666 nxt_string("HTTP/1.1 404 Not Found\r\n"), 667 nxt_string("HTTP/1.1 405 Method Not Allowed\r\n"), 668 nxt_string("HTTP/1.1 406 Not Acceptable\r\n"), 669 nxt_string("HTTP/1.1 407 Proxy Authentication Required\r\n"), 670 nxt_string("HTTP/1.1 408 Request Timeout\r\n"), 671 nxt_string("HTTP/1.1 409 Conflict\r\n"), 672 nxt_string("HTTP/1.1 410 Gone\r\n"), 673 nxt_string("HTTP/1.1 411 Length Required\r\n"), 674 nxt_string("HTTP/1.1 412 Precondition Failed\r\n"), 675 nxt_string("HTTP/1.1 413 Payload Too Large\r\n"), 676 nxt_string("HTTP/1.1 414 URI Too Long\r\n"), 677 nxt_string("HTTP/1.1 415 Unsupported Media Type\r\n"), 678 nxt_string("HTTP/1.1 416 Range Not Satisfiable\r\n"), 679 nxt_string("HTTP/1.1 417 Expectation Failed\r\n"), 680 nxt_string("HTTP/1.1 418\r\n"), 681 nxt_string("HTTP/1.1 419\r\n"), 682 nxt_string("HTTP/1.1 420\r\n"), 683 nxt_string("HTTP/1.1 421\r\n"), 684 nxt_string("HTTP/1.1 422\r\n"), 685 nxt_string("HTTP/1.1 423\r\n"), 686 nxt_string("HTTP/1.1 424\r\n"), 687 nxt_string("HTTP/1.1 425\r\n"), 688 nxt_string("HTTP/1.1 426\r\n"), 689 nxt_string("HTTP/1.1 427\r\n"), 690 nxt_string("HTTP/1.1 428\r\n"), 691 nxt_string("HTTP/1.1 429\r\n"), 692 nxt_string("HTTP/1.1 430\r\n"), 693 nxt_string("HTTP/1.1 431 Request Header Fields Too Large\r\n"), 694}; 695 696 697#define NXT_HTTP_LAST_SERVER_ERROR \ 698 (NXT_HTTP_INTERNAL_SERVER_ERROR + nxt_nitems(nxt_http_server_error) - 1) 699 700static const nxt_str_t nxt_http_server_error[] = { 701 nxt_string("HTTP/1.1 500 Internal Server Error\r\n"), 702 nxt_string("HTTP/1.1 501 Not Implemented\r\n"), 703 nxt_string("HTTP/1.1 502 Bad Gateway\r\n"), 704 nxt_string("HTTP/1.1 503 Service Unavailable\r\n"), 705 nxt_string("HTTP/1.1 504 Gateway Timeout\r\n"), 706 nxt_string("HTTP/1.1 505 HTTP Version Not Supported\r\n"), 707}; 708 709
|
922 923 break; 924 } 925 926 size += nxt_buf_used_size(b); 927 prev = &b->next; 928 } 929 930 if (size == 0) { 931 return out; 932 } 933 934 header = nxt_http_buf_mem(task, r, chunk_size); 935 if (nxt_slow_path(header == NULL)) { 936 return NULL; 937 } 938 939 header->next = out; 940 header->mem.free = nxt_sprintf(header->mem.free, header->mem.end, 941 "\r\n%xO\r\n", size); 942 return header; 943} 944 945 946static void 947nxt_h1p_conn_request_sent(nxt_task_t *task, void *obj, void *data) 948{ 949 nxt_conn_t *c; 950 nxt_event_engine_t *engine; 951 952 c = obj; 953 954 nxt_debug(task, "h1p conn request sent"); 955 956 engine = task->thread->engine; 957 958 c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); 959 960 if (c->write != NULL) { 961 nxt_conn_write(engine, c); 962 } 963} 964 965 966static nxt_off_t 967nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto) 968{ 969 nxt_off_t sent; 970 nxt_h1proto_t *h1p; 971 972 h1p = proto.h1; 973 974 sent = h1p->conn->sent - h1p->header_size; 975 976 return (sent > 0) ? sent : 0; 977} 978 979 980static void 981nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, 982 nxt_buf_t *last) 983{ 984 nxt_buf_t *b; 985 nxt_conn_t *c; 986 nxt_h1proto_t *h1p; 987 nxt_work_queue_t *wq; 988 989 nxt_debug(task, "h1p request discard"); 990 991 h1p = r->proto.h1; 992 h1p->keepalive = 0; 993 994 c = h1p->conn; 995 b = c->write; 996 c->write = NULL; 997 998 wq = &task->thread->engine->fast_work_queue; 999 1000 nxt_sendbuf_drain(task, wq, b); 1001 nxt_sendbuf_drain(task, wq, last); 1002} 1003 1004 1005static void 1006nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, 1007 nxt_socket_conf_joint_t *joint) 1008{ 1009 nxt_conn_t *c; 1010 nxt_h1proto_t *h1p; 1011 1012 nxt_debug(task, "h1p request close"); 1013 1014 h1p = proto.h1; 1015 h1p->request = NULL; 1016 1017 nxt_router_conf_release(task, joint); 1018 1019 c = h1p->conn; 1020 1021 if (h1p->keepalive) { 1022 nxt_h1p_keepalive(task, h1p, c); 1023 1024 } else { 1025 nxt_h1p_close(task, c); 1026 } 1027} 1028 1029 1030static void 1031nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) 1032{ 1033 size_t size; 1034 nxt_buf_t *in, *b, *next; 1035 1036 nxt_debug(task, "h1p keepalive"); 1037 1038 if (!c->tcp_nodelay) { 1039 nxt_conn_tcp_nodelay_on(task, c); 1040 } 1041 1042 b = h1p->buffers; 1043 1044 nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn)); 1045 1046 c->sent = 0; 1047 1048 in = c->read; 1049 1050 if (in == NULL) { 1051 /* A request with large body. */ 1052 in = b; 1053 c->read = in; 1054 1055 b = in->next; 1056 in->next = NULL; 1057 } 1058 1059 while (b != NULL) { 1060 next = b->next; 1061 nxt_mp_free(c->mem_pool, b); 1062 b = next; 1063 } 1064 1065 size = nxt_buf_mem_used_size(&in->mem); 1066 1067 if (size == 0) { 1068 nxt_mp_free(c->mem_pool, in); 1069 1070 c->read = NULL; 1071 c->read_state = &nxt_h1p_keepalive_state; 1072 1073 nxt_conn_read(task->thread->engine, c); 1074 1075 } else { 1076 nxt_debug(task, "h1p pipelining"); 1077 1078 nxt_memmove(in->mem.start, in->mem.pos, size); 1079 1080 in->mem.pos = in->mem.start; 1081 in->mem.free = in->mem.start + size; 1082 1083 nxt_h1p_conn_request_init(task, c, c->socket.data); 1084 } 1085} 1086 1087 1088static const nxt_conn_state_t nxt_h1p_keepalive_state 1089 nxt_aligned(64) = 1090{ 1091 .ready_handler = nxt_h1p_conn_request_init, 1092 .close_handler = nxt_h1p_conn_error, 1093 .error_handler = nxt_h1p_conn_error, 1094 1095 .io_read_handler = nxt_h1p_conn_io_read_handler, 1096 1097 .timer_handler = nxt_h1p_conn_timeout, 1098 .timer_value = nxt_h1p_conn_timeout_value, 1099 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 1100 .timer_autoreset = 1, 1101}; 1102 1103 1104static void 1105nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) 1106{ 1107 nxt_conn_t *c; 1108 1109 c = obj; 1110 1111 nxt_debug(task, "h1p conn error"); 1112 1113 nxt_h1p_close(task, c); 1114} 1115 1116 1117static void 1118nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data) 1119{ 1120 nxt_conn_t *c; 1121 nxt_timer_t *timer; 1122 1123 timer = obj; 1124 1125 nxt_debug(task, "h1p conn timeout"); 1126 1127 c = nxt_read_timer_conn(timer); 1128 1129 nxt_h1p_close(task, c); 1130} 1131 1132 1133static nxt_msec_t 1134nxt_h1p_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 1135{ 1136 nxt_socket_conf_joint_t *joint; 1137 1138 joint = c->listen->socket.data; 1139 1140 return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 1141} 1142 1143 1144static void 1145nxt_h1p_close(nxt_task_t *task, nxt_conn_t *c) 1146{ 1147 nxt_debug(task, "h1p close"); 1148 1149 c->socket.data = NULL; 1150 1151 c->write_state = &nxt_h1p_close_state; 1152 1153 nxt_conn_close(task->thread->engine, c); 1154} 1155 1156 1157static const nxt_conn_state_t nxt_h1p_close_state 1158 nxt_aligned(64) = 1159{ 1160 .ready_handler = nxt_h1p_conn_free, 1161}; 1162 1163 1164static void 1165nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data) 1166{ 1167 nxt_conn_t *c; 1168 nxt_listen_event_t *lev; 1169 nxt_event_engine_t *engine; 1170 1171 c = obj; 1172 1173 nxt_debug(task, "h1p conn free"); 1174 1175 nxt_queue_remove(&c->link); 1176 1177 engine = task->thread->engine; 1178 1179 nxt_sockaddr_cache_free(engine, c); 1180 1181 lev = c->listen; 1182 1183 nxt_conn_free(task, c); 1184 1185 nxt_router_listen_event_release(&engine->task, lev, NULL); 1186} 1187 1188 1189static void 1190nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data) 1191{ 1192 nxt_h1proto_t *h1p; 1193 nxt_http_request_t *r; 1194 1195 h1p = data; 1196 1197 nxt_debug(task, "h1p conn request error"); 1198 1199 r = h1p->request; 1200 1201 if (r->fields == NULL) { 1202 (void) nxt_h1p_header_process(h1p, r); 1203 } 1204 1205 if (r->status == 0) { 1206 r->status = NXT_HTTP_BAD_REQUEST; 1207 } 1208 1209 nxt_h1p_request_error(task, r); 1210} 1211 1212 1213static void 1214nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data) 1215{ 1216 nxt_conn_t *c; 1217 nxt_timer_t *timer; 1218 nxt_h1proto_t *h1p; 1219 nxt_http_request_t *r; 1220 1221 timer = obj; 1222 1223 nxt_debug(task, "h1p conn request timeout"); 1224 1225 c = nxt_read_timer_conn(timer); 1226 /* 1227 * Disable SO_LINGER off during socket closing 1228 * to send "408 Request Timeout" error response. 1229 */ 1230 c->socket.timedout = 0; 1231 1232 h1p = c->socket.data; 1233 r = h1p->request; 1234 1235 if (r->fields == NULL) { 1236 (void) nxt_h1p_header_process(h1p, r); 1237 } 1238 1239 nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT); 1240} 1241 1242 1243static void 1244nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data) 1245{ 1246 nxt_conn_t *c; 1247 nxt_timer_t *timer; 1248 nxt_h1proto_t *h1p; 1249 1250 timer = obj; 1251 1252 nxt_debug(task, "h1p conn request send timeout"); 1253 1254 c = nxt_read_timer_conn(timer); 1255 h1p = c->socket.data; 1256 1257 nxt_h1p_request_error(task, h1p->request); 1258} 1259 1260 1261static nxt_msec_t 1262nxt_h1p_conn_request_timeout_value(nxt_conn_t *c, uintptr_t data) 1263{ 1264 nxt_h1proto_t *h1p; 1265 1266 h1p = c->socket.data; 1267 1268 return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data); 1269} 1270 1271 1272nxt_inline void 1273nxt_h1p_request_error(nxt_task_t *task, nxt_http_request_t *r) 1274{ 1275 r->state->error_handler(task, r, r->proto.h1); 1276}
| 922 923 break; 924 } 925 926 size += nxt_buf_used_size(b); 927 prev = &b->next; 928 } 929 930 if (size == 0) { 931 return out; 932 } 933 934 header = nxt_http_buf_mem(task, r, chunk_size); 935 if (nxt_slow_path(header == NULL)) { 936 return NULL; 937 } 938 939 header->next = out; 940 header->mem.free = nxt_sprintf(header->mem.free, header->mem.end, 941 "\r\n%xO\r\n", size); 942 return header; 943} 944 945 946static void 947nxt_h1p_conn_request_sent(nxt_task_t *task, void *obj, void *data) 948{ 949 nxt_conn_t *c; 950 nxt_event_engine_t *engine; 951 952 c = obj; 953 954 nxt_debug(task, "h1p conn request sent"); 955 956 engine = task->thread->engine; 957 958 c->write = nxt_sendbuf_completion(task, &engine->fast_work_queue, c->write); 959 960 if (c->write != NULL) { 961 nxt_conn_write(engine, c); 962 } 963} 964 965 966static nxt_off_t 967nxt_h1p_request_body_bytes_sent(nxt_task_t *task, nxt_http_proto_t proto) 968{ 969 nxt_off_t sent; 970 nxt_h1proto_t *h1p; 971 972 h1p = proto.h1; 973 974 sent = h1p->conn->sent - h1p->header_size; 975 976 return (sent > 0) ? sent : 0; 977} 978 979 980static void 981nxt_h1p_request_discard(nxt_task_t *task, nxt_http_request_t *r, 982 nxt_buf_t *last) 983{ 984 nxt_buf_t *b; 985 nxt_conn_t *c; 986 nxt_h1proto_t *h1p; 987 nxt_work_queue_t *wq; 988 989 nxt_debug(task, "h1p request discard"); 990 991 h1p = r->proto.h1; 992 h1p->keepalive = 0; 993 994 c = h1p->conn; 995 b = c->write; 996 c->write = NULL; 997 998 wq = &task->thread->engine->fast_work_queue; 999 1000 nxt_sendbuf_drain(task, wq, b); 1001 nxt_sendbuf_drain(task, wq, last); 1002} 1003 1004 1005static void 1006nxt_h1p_request_close(nxt_task_t *task, nxt_http_proto_t proto, 1007 nxt_socket_conf_joint_t *joint) 1008{ 1009 nxt_conn_t *c; 1010 nxt_h1proto_t *h1p; 1011 1012 nxt_debug(task, "h1p request close"); 1013 1014 h1p = proto.h1; 1015 h1p->request = NULL; 1016 1017 nxt_router_conf_release(task, joint); 1018 1019 c = h1p->conn; 1020 1021 if (h1p->keepalive) { 1022 nxt_h1p_keepalive(task, h1p, c); 1023 1024 } else { 1025 nxt_h1p_close(task, c); 1026 } 1027} 1028 1029 1030static void 1031nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) 1032{ 1033 size_t size; 1034 nxt_buf_t *in, *b, *next; 1035 1036 nxt_debug(task, "h1p keepalive"); 1037 1038 if (!c->tcp_nodelay) { 1039 nxt_conn_tcp_nodelay_on(task, c); 1040 } 1041 1042 b = h1p->buffers; 1043 1044 nxt_memzero(h1p, offsetof(nxt_h1proto_t, conn)); 1045 1046 c->sent = 0; 1047 1048 in = c->read; 1049 1050 if (in == NULL) { 1051 /* A request with large body. */ 1052 in = b; 1053 c->read = in; 1054 1055 b = in->next; 1056 in->next = NULL; 1057 } 1058 1059 while (b != NULL) { 1060 next = b->next; 1061 nxt_mp_free(c->mem_pool, b); 1062 b = next; 1063 } 1064 1065 size = nxt_buf_mem_used_size(&in->mem); 1066 1067 if (size == 0) { 1068 nxt_mp_free(c->mem_pool, in); 1069 1070 c->read = NULL; 1071 c->read_state = &nxt_h1p_keepalive_state; 1072 1073 nxt_conn_read(task->thread->engine, c); 1074 1075 } else { 1076 nxt_debug(task, "h1p pipelining"); 1077 1078 nxt_memmove(in->mem.start, in->mem.pos, size); 1079 1080 in->mem.pos = in->mem.start; 1081 in->mem.free = in->mem.start + size; 1082 1083 nxt_h1p_conn_request_init(task, c, c->socket.data); 1084 } 1085} 1086 1087 1088static const nxt_conn_state_t nxt_h1p_keepalive_state 1089 nxt_aligned(64) = 1090{ 1091 .ready_handler = nxt_h1p_conn_request_init, 1092 .close_handler = nxt_h1p_conn_error, 1093 .error_handler = nxt_h1p_conn_error, 1094 1095 .io_read_handler = nxt_h1p_conn_io_read_handler, 1096 1097 .timer_handler = nxt_h1p_conn_timeout, 1098 .timer_value = nxt_h1p_conn_timeout_value, 1099 .timer_data = offsetof(nxt_socket_conf_t, idle_timeout), 1100 .timer_autoreset = 1, 1101}; 1102 1103 1104static void 1105nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) 1106{ 1107 nxt_conn_t *c; 1108 1109 c = obj; 1110 1111 nxt_debug(task, "h1p conn error"); 1112 1113 nxt_h1p_close(task, c); 1114} 1115 1116 1117static void 1118nxt_h1p_conn_timeout(nxt_task_t *task, void *obj, void *data) 1119{ 1120 nxt_conn_t *c; 1121 nxt_timer_t *timer; 1122 1123 timer = obj; 1124 1125 nxt_debug(task, "h1p conn timeout"); 1126 1127 c = nxt_read_timer_conn(timer); 1128 1129 nxt_h1p_close(task, c); 1130} 1131 1132 1133static nxt_msec_t 1134nxt_h1p_conn_timeout_value(nxt_conn_t *c, uintptr_t data) 1135{ 1136 nxt_socket_conf_joint_t *joint; 1137 1138 joint = c->listen->socket.data; 1139 1140 return nxt_value_at(nxt_msec_t, joint->socket_conf, data); 1141} 1142 1143 1144static void 1145nxt_h1p_close(nxt_task_t *task, nxt_conn_t *c) 1146{ 1147 nxt_debug(task, "h1p close"); 1148 1149 c->socket.data = NULL; 1150 1151 c->write_state = &nxt_h1p_close_state; 1152 1153 nxt_conn_close(task->thread->engine, c); 1154} 1155 1156 1157static const nxt_conn_state_t nxt_h1p_close_state 1158 nxt_aligned(64) = 1159{ 1160 .ready_handler = nxt_h1p_conn_free, 1161}; 1162 1163 1164static void 1165nxt_h1p_conn_free(nxt_task_t *task, void *obj, void *data) 1166{ 1167 nxt_conn_t *c; 1168 nxt_listen_event_t *lev; 1169 nxt_event_engine_t *engine; 1170 1171 c = obj; 1172 1173 nxt_debug(task, "h1p conn free"); 1174 1175 nxt_queue_remove(&c->link); 1176 1177 engine = task->thread->engine; 1178 1179 nxt_sockaddr_cache_free(engine, c); 1180 1181 lev = c->listen; 1182 1183 nxt_conn_free(task, c); 1184 1185 nxt_router_listen_event_release(&engine->task, lev, NULL); 1186} 1187 1188 1189static void 1190nxt_h1p_conn_request_error(nxt_task_t *task, void *obj, void *data) 1191{ 1192 nxt_h1proto_t *h1p; 1193 nxt_http_request_t *r; 1194 1195 h1p = data; 1196 1197 nxt_debug(task, "h1p conn request error"); 1198 1199 r = h1p->request; 1200 1201 if (r->fields == NULL) { 1202 (void) nxt_h1p_header_process(h1p, r); 1203 } 1204 1205 if (r->status == 0) { 1206 r->status = NXT_HTTP_BAD_REQUEST; 1207 } 1208 1209 nxt_h1p_request_error(task, r); 1210} 1211 1212 1213static void 1214nxt_h1p_conn_request_timeout(nxt_task_t *task, void *obj, void *data) 1215{ 1216 nxt_conn_t *c; 1217 nxt_timer_t *timer; 1218 nxt_h1proto_t *h1p; 1219 nxt_http_request_t *r; 1220 1221 timer = obj; 1222 1223 nxt_debug(task, "h1p conn request timeout"); 1224 1225 c = nxt_read_timer_conn(timer); 1226 /* 1227 * Disable SO_LINGER off during socket closing 1228 * to send "408 Request Timeout" error response. 1229 */ 1230 c->socket.timedout = 0; 1231 1232 h1p = c->socket.data; 1233 r = h1p->request; 1234 1235 if (r->fields == NULL) { 1236 (void) nxt_h1p_header_process(h1p, r); 1237 } 1238 1239 nxt_http_request_error(task, r, NXT_HTTP_REQUEST_TIMEOUT); 1240} 1241 1242 1243static void 1244nxt_h1p_conn_request_send_timeout(nxt_task_t *task, void *obj, void *data) 1245{ 1246 nxt_conn_t *c; 1247 nxt_timer_t *timer; 1248 nxt_h1proto_t *h1p; 1249 1250 timer = obj; 1251 1252 nxt_debug(task, "h1p conn request send timeout"); 1253 1254 c = nxt_read_timer_conn(timer); 1255 h1p = c->socket.data; 1256 1257 nxt_h1p_request_error(task, h1p->request); 1258} 1259 1260 1261static nxt_msec_t 1262nxt_h1p_conn_request_timeout_value(nxt_conn_t *c, uintptr_t data) 1263{ 1264 nxt_h1proto_t *h1p; 1265 1266 h1p = c->socket.data; 1267 1268 return nxt_value_at(nxt_msec_t, h1p->request->conf->socket_conf, data); 1269} 1270 1271 1272nxt_inline void 1273nxt_h1p_request_error(nxt_task_t *task, nxt_http_request_t *r) 1274{ 1275 r->state->error_handler(task, r, r->proto.h1); 1276}
|