|
13 | 13 |
|
14 | 14 | static ngx_int_t ngx_http_header_filter_init(ngx_conf_t *cf);
|
15 | 15 | static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
|
| 16 | +static ngx_int_t ngx_http_early_hints_filter(ngx_http_request_t *r); |
16 | 17 |
|
17 | 18 |
|
18 | 19 | static ngx_http_module_t ngx_http_header_filter_module_ctx = {
|
@@ -50,6 +51,9 @@ static u_char ngx_http_server_string[] = "Server: nginx" CRLF;
|
50 | 51 | static u_char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
|
51 | 52 | static u_char ngx_http_server_build_string[] = "Server: " NGINX_VER_BUILD CRLF;
|
52 | 53 |
|
| 54 | +static ngx_str_t ngx_http_early_hints_status_line = |
| 55 | + ngx_string("HTTP/1.1 103 Early Hints" CRLF); |
| 56 | + |
53 | 57 |
|
54 | 58 | static ngx_str_t ngx_http_status_lines[] = {
|
55 | 59 |
|
@@ -625,10 +629,113 @@ ngx_http_header_filter(ngx_http_request_t *r)
|
625 | 629 | }
|
626 | 630 |
|
627 | 631 |
|
| 632 | +static ngx_int_t |
| 633 | +ngx_http_early_hints_filter(ngx_http_request_t *r) |
| 634 | +{ |
| 635 | + size_t len; |
| 636 | + ngx_buf_t *b; |
| 637 | + ngx_uint_t i; |
| 638 | + ngx_chain_t out; |
| 639 | + ngx_list_part_t *part; |
| 640 | + ngx_table_elt_t *header; |
| 641 | + |
| 642 | + if (r != r->main) { |
| 643 | + return NGX_OK; |
| 644 | + } |
| 645 | + |
| 646 | + if (r->http_version < NGX_HTTP_VERSION_11) { |
| 647 | + return NGX_OK; |
| 648 | + } |
| 649 | + |
| 650 | + len = 0; |
| 651 | + |
| 652 | + part = &r->headers_out.headers.part; |
| 653 | + header = part->elts; |
| 654 | + |
| 655 | + for (i = 0; /* void */; i++) { |
| 656 | + |
| 657 | + if (i >= part->nelts) { |
| 658 | + if (part->next == NULL) { |
| 659 | + break; |
| 660 | + } |
| 661 | + |
| 662 | + part = part->next; |
| 663 | + header = part->elts; |
| 664 | + i = 0; |
| 665 | + } |
| 666 | + |
| 667 | + if (header[i].hash == 0) { |
| 668 | + continue; |
| 669 | + } |
| 670 | + |
| 671 | + len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len |
| 672 | + + sizeof(CRLF) - 1; |
| 673 | + } |
| 674 | + |
| 675 | + if (len == 0) { |
| 676 | + return NGX_OK; |
| 677 | + } |
| 678 | + |
| 679 | + len += ngx_http_early_hints_status_line.len |
| 680 | + /* the end of the early hints */ |
| 681 | + + sizeof(CRLF) - 1; |
| 682 | + |
| 683 | + b = ngx_create_temp_buf(r->pool, len); |
| 684 | + if (b == NULL) { |
| 685 | + return NGX_ERROR; |
| 686 | + } |
| 687 | + |
| 688 | + b->last = ngx_copy(b->last, ngx_http_early_hints_status_line.data, |
| 689 | + ngx_http_early_hints_status_line.len); |
| 690 | + |
| 691 | + part = &r->headers_out.headers.part; |
| 692 | + header = part->elts; |
| 693 | + |
| 694 | + for (i = 0; /* void */; i++) { |
| 695 | + |
| 696 | + if (i >= part->nelts) { |
| 697 | + if (part->next == NULL) { |
| 698 | + break; |
| 699 | + } |
| 700 | + |
| 701 | + part = part->next; |
| 702 | + header = part->elts; |
| 703 | + i = 0; |
| 704 | + } |
| 705 | + |
| 706 | + if (header[i].hash == 0) { |
| 707 | + continue; |
| 708 | + } |
| 709 | + |
| 710 | + b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); |
| 711 | + *b->last++ = ':'; *b->last++ = ' '; |
| 712 | + |
| 713 | + b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); |
| 714 | + *b->last++ = CR; *b->last++ = LF; |
| 715 | + } |
| 716 | + |
| 717 | + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
| 718 | + "%*s", (size_t) (b->last - b->pos), b->pos); |
| 719 | + |
| 720 | + /* the end of HTTP early hints */ |
| 721 | + *b->last++ = CR; *b->last++ = LF; |
| 722 | + |
| 723 | + r->header_size = b->last - b->pos; |
| 724 | + |
| 725 | + b->flush = 1; |
| 726 | + |
| 727 | + out.buf = b; |
| 728 | + out.next = NULL; |
| 729 | + |
| 730 | + return ngx_http_write_filter(r, &out); |
| 731 | +} |
| 732 | + |
| 733 | + |
628 | 734 | static ngx_int_t
|
629 | 735 | ngx_http_header_filter_init(ngx_conf_t *cf)
|
630 | 736 | {
|
631 | 737 | ngx_http_top_header_filter = ngx_http_header_filter;
|
| 738 | + ngx_http_top_early_hints_filter = ngx_http_early_hints_filter; |
632 | 739 |
|
633 | 740 | return NGX_OK;
|
634 | 741 | }
|
0 commit comments