Mercurial > hg > nginx
comparison src/http/v3/ngx_http_v3_filter_module.c @ 9108:f742b1b46901 quic
HTTP/3: removed server push support.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 12 May 2023 10:02:10 +0400 |
parents | 8d0753760546 |
children | f91dc350be9f |
comparison
equal
deleted
inserted
replaced
9107:adcc6d8acfd4 | 9108:f742b1b46901 |
---|---|
34 ngx_chain_t *busy; | 34 ngx_chain_t *busy; |
35 } ngx_http_v3_filter_ctx_t; | 35 } ngx_http_v3_filter_ctx_t; |
36 | 36 |
37 | 37 |
38 static ngx_int_t ngx_http_v3_header_filter(ngx_http_request_t *r); | 38 static ngx_int_t ngx_http_v3_header_filter(ngx_http_request_t *r); |
39 static ngx_int_t ngx_http_v3_push_resources(ngx_http_request_t *r, | |
40 ngx_chain_t ***out); | |
41 static ngx_int_t ngx_http_v3_push_resource(ngx_http_request_t *r, | |
42 ngx_str_t *path, ngx_chain_t ***out); | |
43 static ngx_int_t ngx_http_v3_create_push_request( | |
44 ngx_http_request_t *pr, ngx_str_t *path, uint64_t push_id); | |
45 static ngx_int_t ngx_http_v3_set_push_header(ngx_http_request_t *r, | |
46 const char *name, ngx_str_t *value); | |
47 static void ngx_http_v3_push_request_handler(ngx_event_t *ev); | |
48 static ngx_chain_t *ngx_http_v3_create_push_promise(ngx_http_request_t *r, | |
49 ngx_str_t *path, uint64_t push_id); | |
50 static ngx_int_t ngx_http_v3_body_filter(ngx_http_request_t *r, | 39 static ngx_int_t ngx_http_v3_body_filter(ngx_http_request_t *r, |
51 ngx_chain_t *in); | 40 ngx_chain_t *in); |
52 static ngx_chain_t *ngx_http_v3_create_trailers(ngx_http_request_t *r, | 41 static ngx_chain_t *ngx_http_v3_create_trailers(ngx_http_request_t *r, |
53 ngx_http_v3_filter_ctx_t *ctx); | 42 ngx_http_v3_filter_ctx_t *ctx); |
54 static ngx_int_t ngx_http_v3_filter_init(ngx_conf_t *cf); | 43 static ngx_int_t ngx_http_v3_filter_init(ngx_conf_t *cf); |
153 c = r->connection; | 142 c = r->connection; |
154 | 143 |
155 out = NULL; | 144 out = NULL; |
156 ll = &out; | 145 ll = &out; |
157 | 146 |
158 if ((c->quic->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0 | |
159 && r->method != NGX_HTTP_HEAD) | |
160 { | |
161 if (ngx_http_v3_push_resources(r, &ll) != NGX_OK) { | |
162 return NGX_ERROR; | |
163 } | |
164 } | |
165 | |
166 len = ngx_http_v3_encode_field_section_prefix(NULL, 0, 0, 0); | 147 len = ngx_http_v3_encode_field_section_prefix(NULL, 0, 0, 0); |
167 | 148 |
168 if (r->headers_out.status == NGX_HTTP_OK) { | 149 if (r->headers_out.status == NGX_HTTP_OK) { |
169 len += ngx_http_v3_encode_field_ri(NULL, 0, | 150 len += ngx_http_v3_encode_field_ri(NULL, 0, |
170 NGX_HTTP_V3_HEADER_STATUS_200); | 151 NGX_HTTP_V3_HEADER_STATUS_200); |
601 for (cl = out; cl; cl = cl->next) { | 582 for (cl = out; cl; cl = cl->next) { |
602 h3c->total_bytes += cl->buf->last - cl->buf->pos; | 583 h3c->total_bytes += cl->buf->last - cl->buf->pos; |
603 } | 584 } |
604 | 585 |
605 return ngx_http_write_filter(r, out); | 586 return ngx_http_write_filter(r, out); |
606 } | |
607 | |
608 | |
609 static ngx_int_t | |
610 ngx_http_v3_push_resources(ngx_http_request_t *r, ngx_chain_t ***out) | |
611 { | |
612 u_char *start, *end, *last; | |
613 ngx_str_t path; | |
614 ngx_int_t rc; | |
615 ngx_uint_t i, push; | |
616 ngx_table_elt_t *h; | |
617 ngx_http_v3_loc_conf_t *h3lcf; | |
618 ngx_http_complex_value_t *pushes; | |
619 | |
620 h3lcf = ngx_http_get_module_loc_conf(r, ngx_http_v3_module); | |
621 | |
622 if (h3lcf->pushes) { | |
623 pushes = h3lcf->pushes->elts; | |
624 | |
625 for (i = 0; i < h3lcf->pushes->nelts; i++) { | |
626 | |
627 if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) { | |
628 return NGX_ERROR; | |
629 } | |
630 | |
631 if (path.len == 0) { | |
632 continue; | |
633 } | |
634 | |
635 if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) { | |
636 continue; | |
637 } | |
638 | |
639 rc = ngx_http_v3_push_resource(r, &path, out); | |
640 | |
641 if (rc == NGX_ERROR) { | |
642 return NGX_ERROR; | |
643 } | |
644 | |
645 if (rc == NGX_ABORT) { | |
646 return NGX_OK; | |
647 } | |
648 | |
649 /* NGX_OK, NGX_DECLINED */ | |
650 } | |
651 } | |
652 | |
653 if (!h3lcf->push_preload) { | |
654 return NGX_OK; | |
655 } | |
656 | |
657 for (h = r->headers_out.link; h; h = h->next) { | |
658 | |
659 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
660 "http3 parse link: \"%V\"", &h->value); | |
661 | |
662 start = h->value.data; | |
663 end = h->value.data + h->value.len; | |
664 | |
665 next_link: | |
666 | |
667 while (start < end && *start == ' ') { start++; } | |
668 | |
669 if (start == end || *start++ != '<') { | |
670 continue; | |
671 } | |
672 | |
673 while (start < end && *start == ' ') { start++; } | |
674 | |
675 for (last = start; last < end && *last != '>'; last++) { | |
676 /* void */ | |
677 } | |
678 | |
679 if (last == start || last == end) { | |
680 continue; | |
681 } | |
682 | |
683 path.len = last - start; | |
684 path.data = start; | |
685 | |
686 start = last + 1; | |
687 | |
688 while (start < end && *start == ' ') { start++; } | |
689 | |
690 if (start == end) { | |
691 continue; | |
692 } | |
693 | |
694 if (*start == ',') { | |
695 start++; | |
696 goto next_link; | |
697 } | |
698 | |
699 if (*start++ != ';') { | |
700 continue; | |
701 } | |
702 | |
703 last = ngx_strlchr(start, end, ','); | |
704 | |
705 if (last == NULL) { | |
706 last = end; | |
707 } | |
708 | |
709 push = 0; | |
710 | |
711 for ( ;; ) { | |
712 | |
713 while (start < last && *start == ' ') { start++; } | |
714 | |
715 if (last - start >= 6 | |
716 && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0) | |
717 { | |
718 start += 6; | |
719 | |
720 if (start == last || *start == ' ' || *start == ';') { | |
721 push = 0; | |
722 break; | |
723 } | |
724 | |
725 goto next_param; | |
726 } | |
727 | |
728 if (last - start >= 11 | |
729 && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0) | |
730 { | |
731 start += 11; | |
732 | |
733 if (start == last || *start == ' ' || *start == ';') { | |
734 push = 1; | |
735 } | |
736 | |
737 goto next_param; | |
738 } | |
739 | |
740 if (last - start >= 4 | |
741 && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0) | |
742 { | |
743 start += 4; | |
744 | |
745 while (start < last && *start == ' ') { start++; } | |
746 | |
747 if (start == last || *start++ != '"') { | |
748 goto next_param; | |
749 } | |
750 | |
751 for ( ;; ) { | |
752 | |
753 while (start < last && *start == ' ') { start++; } | |
754 | |
755 if (last - start >= 7 | |
756 && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0) | |
757 { | |
758 start += 7; | |
759 | |
760 if (start < last && (*start == ' ' || *start == '"')) { | |
761 push = 1; | |
762 break; | |
763 } | |
764 } | |
765 | |
766 while (start < last && *start != ' ' && *start != '"') { | |
767 start++; | |
768 } | |
769 | |
770 if (start == last) { | |
771 break; | |
772 } | |
773 | |
774 if (*start == '"') { | |
775 break; | |
776 } | |
777 | |
778 start++; | |
779 } | |
780 } | |
781 | |
782 next_param: | |
783 | |
784 start = ngx_strlchr(start, last, ';'); | |
785 | |
786 if (start == NULL) { | |
787 break; | |
788 } | |
789 | |
790 start++; | |
791 } | |
792 | |
793 if (push) { | |
794 while (path.len && path.data[path.len - 1] == ' ') { | |
795 path.len--; | |
796 } | |
797 } | |
798 | |
799 if (push && path.len | |
800 && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/')) | |
801 { | |
802 rc = ngx_http_v3_push_resource(r, &path, out); | |
803 | |
804 if (rc == NGX_ERROR) { | |
805 return NGX_ERROR; | |
806 } | |
807 | |
808 if (rc == NGX_ABORT) { | |
809 return NGX_OK; | |
810 } | |
811 | |
812 /* NGX_OK, NGX_DECLINED */ | |
813 } | |
814 | |
815 if (last < end) { | |
816 start = last + 1; | |
817 goto next_link; | |
818 } | |
819 } | |
820 | |
821 return NGX_OK; | |
822 } | |
823 | |
824 | |
825 static ngx_int_t | |
826 ngx_http_v3_push_resource(ngx_http_request_t *r, ngx_str_t *path, | |
827 ngx_chain_t ***ll) | |
828 { | |
829 uint64_t push_id; | |
830 ngx_int_t rc; | |
831 ngx_chain_t *cl; | |
832 ngx_connection_t *c; | |
833 ngx_http_v3_session_t *h3c; | |
834 ngx_http_v3_srv_conf_t *h3scf; | |
835 | |
836 c = r->connection; | |
837 h3c = ngx_http_v3_get_session(c); | |
838 h3scf = ngx_http_get_module_srv_conf(r, ngx_http_v3_module); | |
839 | |
840 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
841 "http3 push \"%V\" pushing:%ui/%ui id:%uL/%L", | |
842 path, h3c->npushing, h3scf->max_concurrent_pushes, | |
843 h3c->next_push_id, h3c->max_push_id); | |
844 | |
845 if (!ngx_path_separator(path->data[0])) { | |
846 ngx_log_error(NGX_LOG_WARN, c->log, 0, | |
847 "non-absolute path \"%V\" not pushed", path); | |
848 return NGX_DECLINED; | |
849 } | |
850 | |
851 if (h3c->max_push_id == (uint64_t) -1 | |
852 || h3c->next_push_id > h3c->max_push_id) | |
853 { | |
854 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
855 "http3 abort pushes due to max_push_id"); | |
856 return NGX_ABORT; | |
857 } | |
858 | |
859 if (h3c->goaway_push_id != (uint64_t) -1) { | |
860 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
861 "http3 abort pushes due to goaway"); | |
862 return NGX_ABORT; | |
863 } | |
864 | |
865 if (h3c->npushing >= h3scf->max_concurrent_pushes) { | |
866 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
867 "http3 abort pushes due to max_concurrent_pushes"); | |
868 return NGX_ABORT; | |
869 } | |
870 | |
871 if (r->headers_in.server.len == 0) { | |
872 return NGX_ABORT; | |
873 } | |
874 | |
875 push_id = h3c->next_push_id++; | |
876 | |
877 rc = ngx_http_v3_create_push_request(r, path, push_id); | |
878 if (rc != NGX_OK) { | |
879 return rc; | |
880 } | |
881 | |
882 cl = ngx_http_v3_create_push_promise(r, path, push_id); | |
883 if (cl == NULL) { | |
884 return NGX_ERROR; | |
885 } | |
886 | |
887 for (**ll = cl; **ll; *ll = &(**ll)->next); | |
888 | |
889 return NGX_OK; | |
890 } | |
891 | |
892 | |
893 static ngx_int_t | |
894 ngx_http_v3_create_push_request(ngx_http_request_t *pr, ngx_str_t *path, | |
895 uint64_t push_id) | |
896 { | |
897 ngx_connection_t *c, *pc; | |
898 ngx_http_request_t *r; | |
899 ngx_http_log_ctx_t *ctx; | |
900 ngx_http_connection_t *hc, *phc; | |
901 ngx_http_core_srv_conf_t *cscf; | |
902 | |
903 pc = pr->connection; | |
904 | |
905 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
906 "http3 create push request id:%uL", push_id); | |
907 | |
908 c = ngx_http_v3_create_push_stream(pc, push_id); | |
909 if (c == NULL) { | |
910 return NGX_ABORT; | |
911 } | |
912 | |
913 #if (NGX_STAT_STUB) | |
914 (void) ngx_atomic_fetch_add(ngx_stat_active, 1); | |
915 #endif | |
916 | |
917 hc = ngx_palloc(c->pool, sizeof(ngx_http_connection_t)); | |
918 if (hc == NULL) { | |
919 ngx_http_close_connection(c); | |
920 return NGX_ERROR; | |
921 } | |
922 | |
923 phc = ngx_http_quic_get_connection(pc); | |
924 ngx_memcpy(hc, phc, sizeof(ngx_http_connection_t)); | |
925 c->data = hc; | |
926 | |
927 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); | |
928 if (ctx == NULL) { | |
929 ngx_http_close_connection(c); | |
930 return NGX_ERROR; | |
931 } | |
932 | |
933 ctx->connection = c; | |
934 ctx->request = NULL; | |
935 ctx->current_request = NULL; | |
936 | |
937 c->log->handler = pc->log->handler; | |
938 c->log->data = ctx; | |
939 c->log->action = "processing pushed request headers"; | |
940 | |
941 c->log_error = NGX_ERROR_INFO; | |
942 | |
943 r = ngx_http_create_request(c); | |
944 if (r == NULL) { | |
945 ngx_http_close_connection(c); | |
946 return NGX_ERROR; | |
947 } | |
948 | |
949 c->data = r; | |
950 | |
951 ngx_str_set(&r->http_protocol, "HTTP/3.0"); | |
952 | |
953 r->http_version = NGX_HTTP_VERSION_30; | |
954 r->method_name = ngx_http_core_get_method; | |
955 r->method = NGX_HTTP_GET; | |
956 | |
957 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | |
958 | |
959 r->header_in = ngx_create_temp_buf(r->pool, | |
960 cscf->client_header_buffer_size); | |
961 if (r->header_in == NULL) { | |
962 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
963 return NGX_ERROR; | |
964 } | |
965 | |
966 if (ngx_list_init(&r->headers_in.headers, r->pool, 4, | |
967 sizeof(ngx_table_elt_t)) | |
968 != NGX_OK) | |
969 { | |
970 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
971 return NGX_ERROR; | |
972 } | |
973 | |
974 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; | |
975 | |
976 r->schema.data = ngx_pstrdup(r->pool, &pr->schema); | |
977 if (r->schema.data == NULL) { | |
978 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
979 return NGX_ERROR; | |
980 } | |
981 | |
982 r->schema.len = pr->schema.len; | |
983 | |
984 r->uri_start = ngx_pstrdup(r->pool, path); | |
985 if (r->uri_start == NULL) { | |
986 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
987 return NGX_ERROR; | |
988 } | |
989 | |
990 r->uri_end = r->uri_start + path->len; | |
991 | |
992 if (ngx_http_parse_uri(r) != NGX_OK) { | |
993 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | |
994 return NGX_ERROR; | |
995 } | |
996 | |
997 if (ngx_http_process_request_uri(r) != NGX_OK) { | |
998 return NGX_ERROR; | |
999 } | |
1000 | |
1001 if (ngx_http_v3_set_push_header(r, "host", &pr->headers_in.server) | |
1002 != NGX_OK) | |
1003 { | |
1004 return NGX_ERROR; | |
1005 } | |
1006 | |
1007 if (pr->headers_in.accept_encoding) { | |
1008 if (ngx_http_v3_set_push_header(r, "accept-encoding", | |
1009 &pr->headers_in.accept_encoding->value) | |
1010 != NGX_OK) | |
1011 { | |
1012 return NGX_ERROR; | |
1013 } | |
1014 } | |
1015 | |
1016 if (pr->headers_in.accept_language) { | |
1017 if (ngx_http_v3_set_push_header(r, "accept-language", | |
1018 &pr->headers_in.accept_language->value) | |
1019 != NGX_OK) | |
1020 { | |
1021 return NGX_ERROR; | |
1022 } | |
1023 } | |
1024 | |
1025 if (pr->headers_in.user_agent) { | |
1026 if (ngx_http_v3_set_push_header(r, "user-agent", | |
1027 &pr->headers_in.user_agent->value) | |
1028 != NGX_OK) | |
1029 { | |
1030 return NGX_ERROR; | |
1031 } | |
1032 } | |
1033 | |
1034 c->read->handler = ngx_http_v3_push_request_handler; | |
1035 c->read->handler = ngx_http_v3_push_request_handler; | |
1036 | |
1037 ngx_post_event(c->read, &ngx_posted_events); | |
1038 | |
1039 return NGX_OK; | |
1040 } | |
1041 | |
1042 | |
1043 static ngx_int_t | |
1044 ngx_http_v3_set_push_header(ngx_http_request_t *r, const char *name, | |
1045 ngx_str_t *value) | |
1046 { | |
1047 u_char *p; | |
1048 ngx_table_elt_t *h; | |
1049 ngx_http_header_t *hh; | |
1050 ngx_http_core_main_conf_t *cmcf; | |
1051 | |
1052 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1053 "http3 push header \"%s\": \"%V\"", name, value); | |
1054 | |
1055 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
1056 | |
1057 p = ngx_pnalloc(r->pool, value->len + 1); | |
1058 if (p == NULL) { | |
1059 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1060 return NGX_ERROR; | |
1061 } | |
1062 | |
1063 ngx_memcpy(p, value->data, value->len); | |
1064 p[value->len] = '\0'; | |
1065 | |
1066 h = ngx_list_push(&r->headers_in.headers); | |
1067 if (h == NULL) { | |
1068 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1069 return NGX_ERROR; | |
1070 } | |
1071 | |
1072 h->key.data = (u_char *) name; | |
1073 h->key.len = ngx_strlen(name); | |
1074 h->hash = ngx_hash_key(h->key.data, h->key.len); | |
1075 h->lowcase_key = (u_char *) name; | |
1076 h->value.data = p; | |
1077 h->value.len = value->len; | |
1078 | |
1079 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, | |
1080 h->lowcase_key, h->key.len); | |
1081 | |
1082 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | |
1083 return NGX_ERROR; | |
1084 } | |
1085 | |
1086 return NGX_OK; | |
1087 } | |
1088 | |
1089 | |
1090 static void | |
1091 ngx_http_v3_push_request_handler(ngx_event_t *ev) | |
1092 { | |
1093 ngx_connection_t *c; | |
1094 ngx_http_request_t *r; | |
1095 | |
1096 c = ev->data; | |
1097 r = c->data; | |
1098 | |
1099 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 push request handler"); | |
1100 | |
1101 ngx_http_process_request(r); | |
1102 } | |
1103 | |
1104 | |
1105 static ngx_chain_t * | |
1106 ngx_http_v3_create_push_promise(ngx_http_request_t *r, ngx_str_t *path, | |
1107 uint64_t push_id) | |
1108 { | |
1109 size_t n, len; | |
1110 ngx_buf_t *b; | |
1111 ngx_chain_t *hl, *cl; | |
1112 ngx_http_v3_session_t *h3c; | |
1113 | |
1114 h3c = ngx_http_v3_get_session(r->connection); | |
1115 | |
1116 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1117 "http3 create push promise id:%uL", push_id); | |
1118 | |
1119 len = ngx_http_v3_encode_varlen_int(NULL, push_id); | |
1120 | |
1121 len += ngx_http_v3_encode_field_section_prefix(NULL, 0, 0, 0); | |
1122 | |
1123 len += ngx_http_v3_encode_field_ri(NULL, 0, | |
1124 NGX_HTTP_V3_HEADER_METHOD_GET); | |
1125 | |
1126 len += ngx_http_v3_encode_field_lri(NULL, 0, | |
1127 NGX_HTTP_V3_HEADER_AUTHORITY, | |
1128 NULL, r->headers_in.server.len); | |
1129 | |
1130 if (path->len == 1 && path->data[0] == '/') { | |
1131 len += ngx_http_v3_encode_field_ri(NULL, 0, | |
1132 NGX_HTTP_V3_HEADER_PATH_ROOT); | |
1133 | |
1134 } else { | |
1135 len += ngx_http_v3_encode_field_lri(NULL, 0, | |
1136 NGX_HTTP_V3_HEADER_PATH_ROOT, | |
1137 NULL, path->len); | |
1138 } | |
1139 | |
1140 if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { | |
1141 len += ngx_http_v3_encode_field_ri(NULL, 0, | |
1142 NGX_HTTP_V3_HEADER_SCHEME_HTTPS); | |
1143 | |
1144 } else if (r->schema.len == 4 | |
1145 && ngx_strncmp(r->schema.data, "http", 4) == 0) | |
1146 { | |
1147 len += ngx_http_v3_encode_field_ri(NULL, 0, | |
1148 NGX_HTTP_V3_HEADER_SCHEME_HTTP); | |
1149 | |
1150 } else { | |
1151 len += ngx_http_v3_encode_field_lri(NULL, 0, | |
1152 NGX_HTTP_V3_HEADER_SCHEME_HTTP, | |
1153 NULL, r->schema.len); | |
1154 } | |
1155 | |
1156 if (r->headers_in.accept_encoding) { | |
1157 len += ngx_http_v3_encode_field_lri(NULL, 0, | |
1158 NGX_HTTP_V3_HEADER_ACCEPT_ENCODING, NULL, | |
1159 r->headers_in.accept_encoding->value.len); | |
1160 } | |
1161 | |
1162 if (r->headers_in.accept_language) { | |
1163 len += ngx_http_v3_encode_field_lri(NULL, 0, | |
1164 NGX_HTTP_V3_HEADER_ACCEPT_LANGUAGE, NULL, | |
1165 r->headers_in.accept_language->value.len); | |
1166 } | |
1167 | |
1168 if (r->headers_in.user_agent) { | |
1169 len += ngx_http_v3_encode_field_lri(NULL, 0, | |
1170 NGX_HTTP_V3_HEADER_USER_AGENT, NULL, | |
1171 r->headers_in.user_agent->value.len); | |
1172 } | |
1173 | |
1174 b = ngx_create_temp_buf(r->pool, len); | |
1175 if (b == NULL) { | |
1176 return NULL; | |
1177 } | |
1178 | |
1179 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, push_id); | |
1180 | |
1181 b->last = (u_char *) ngx_http_v3_encode_field_section_prefix(b->last, | |
1182 0, 0, 0); | |
1183 | |
1184 b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0, | |
1185 NGX_HTTP_V3_HEADER_METHOD_GET); | |
1186 | |
1187 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, | |
1188 NGX_HTTP_V3_HEADER_AUTHORITY, | |
1189 r->headers_in.server.data, | |
1190 r->headers_in.server.len); | |
1191 | |
1192 if (path->len == 1 && path->data[0] == '/') { | |
1193 b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0, | |
1194 NGX_HTTP_V3_HEADER_PATH_ROOT); | |
1195 | |
1196 } else { | |
1197 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, | |
1198 NGX_HTTP_V3_HEADER_PATH_ROOT, | |
1199 path->data, path->len); | |
1200 } | |
1201 | |
1202 if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { | |
1203 b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0, | |
1204 NGX_HTTP_V3_HEADER_SCHEME_HTTPS); | |
1205 | |
1206 } else if (r->schema.len == 4 | |
1207 && ngx_strncmp(r->schema.data, "http", 4) == 0) | |
1208 { | |
1209 b->last = (u_char *) ngx_http_v3_encode_field_ri(b->last, 0, | |
1210 NGX_HTTP_V3_HEADER_SCHEME_HTTP); | |
1211 | |
1212 } else { | |
1213 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, | |
1214 NGX_HTTP_V3_HEADER_SCHEME_HTTP, | |
1215 r->schema.data, r->schema.len); | |
1216 } | |
1217 | |
1218 if (r->headers_in.accept_encoding) { | |
1219 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, | |
1220 NGX_HTTP_V3_HEADER_ACCEPT_ENCODING, | |
1221 r->headers_in.accept_encoding->value.data, | |
1222 r->headers_in.accept_encoding->value.len); | |
1223 } | |
1224 | |
1225 if (r->headers_in.accept_language) { | |
1226 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, | |
1227 NGX_HTTP_V3_HEADER_ACCEPT_LANGUAGE, | |
1228 r->headers_in.accept_language->value.data, | |
1229 r->headers_in.accept_language->value.len); | |
1230 } | |
1231 | |
1232 if (r->headers_in.user_agent) { | |
1233 b->last = (u_char *) ngx_http_v3_encode_field_lri(b->last, 0, | |
1234 NGX_HTTP_V3_HEADER_USER_AGENT, | |
1235 r->headers_in.user_agent->value.data, | |
1236 r->headers_in.user_agent->value.len); | |
1237 } | |
1238 | |
1239 cl = ngx_alloc_chain_link(r->pool); | |
1240 if (cl == NULL) { | |
1241 return NULL; | |
1242 } | |
1243 | |
1244 cl->buf = b; | |
1245 cl->next = NULL; | |
1246 | |
1247 n = b->last - b->pos; | |
1248 | |
1249 h3c->payload_bytes += n; | |
1250 | |
1251 len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_PUSH_PROMISE) | |
1252 + ngx_http_v3_encode_varlen_int(NULL, n); | |
1253 | |
1254 b = ngx_create_temp_buf(r->pool, len); | |
1255 if (b == NULL) { | |
1256 return NULL; | |
1257 } | |
1258 | |
1259 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, | |
1260 NGX_HTTP_V3_FRAME_PUSH_PROMISE); | |
1261 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n); | |
1262 | |
1263 hl = ngx_alloc_chain_link(r->pool); | |
1264 if (hl == NULL) { | |
1265 return NULL; | |
1266 } | |
1267 | |
1268 hl->buf = b; | |
1269 hl->next = cl; | |
1270 | |
1271 return hl; | |
1272 } | 587 } |
1273 | 588 |
1274 | 589 |
1275 static ngx_int_t | 590 static ngx_int_t |
1276 ngx_http_v3_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | 591 ngx_http_v3_body_filter(ngx_http_request_t *r, ngx_chain_t *in) |