comparison src/http/v2/ngx_http_v2_filter_module.c @ 7201:641306096f5b

HTTP/2: server push. Resources to be pushed are configured with the "http2_push" directive. Also, preload links from the Link response headers, as described in https://www.w3.org/TR/preload/#server-push-http-2, can be pushed, if enabled with the "http2_push_preload" directive. Only relative URIs with absolute paths can be pushed. The number of concurrent pushes is normally limited by a client, but cannot exceed a hard limit set by the "http2_max_concurrent_pushes" directive.
author Ruslan Ermilov <ru@nginx.com>
date Thu, 08 Feb 2018 09:55:03 +0300
parents 61d276dcd493
children a49af443656f
comparison
equal deleted inserted replaced
7200:cadb43014c7c 7201:641306096f5b
1 1
2 /* 2 /*
3 * Copyright (C) Nginx, Inc. 3 * Copyright (C) Nginx, Inc.
4 * Copyright (C) Valentin V. Bartenev 4 * Copyright (C) Valentin V. Bartenev
5 * Copyright (C) Ruslan Ermilov
5 */ 6 */
6 7
7 8
8 #include <ngx_config.h> 9 #include <ngx_config.h>
9 #include <ngx_core.h> 10 #include <ngx_core.h>
30 #define ngx_http_v2_write_value(dst, src, len, tmp) \ 31 #define ngx_http_v2_write_value(dst, src, len, tmp) \
31 ngx_http_v2_string_encode(dst, src, len, tmp, 0) 32 ngx_http_v2_string_encode(dst, src, len, tmp, 0)
32 33
33 #define NGX_HTTP_V2_ENCODE_RAW 0 34 #define NGX_HTTP_V2_ENCODE_RAW 0
34 #define NGX_HTTP_V2_ENCODE_HUFF 0x80 35 #define NGX_HTTP_V2_ENCODE_HUFF 0x80
36
37 #define NGX_HTTP_V2_AUTHORITY_INDEX 1
38 #define NGX_HTTP_V2_METHOD_GET_INDEX 2
39 #define NGX_HTTP_V2_PATH_INDEX 4
40
41 #define NGX_HTTP_V2_SCHEME_HTTP_INDEX 6
42 #define NGX_HTTP_V2_SCHEME_HTTPS_INDEX 7
35 43
36 #define NGX_HTTP_V2_STATUS_INDEX 8 44 #define NGX_HTTP_V2_STATUS_INDEX 8
37 #define NGX_HTTP_V2_STATUS_200_INDEX 8 45 #define NGX_HTTP_V2_STATUS_200_INDEX 8
38 #define NGX_HTTP_V2_STATUS_204_INDEX 9 46 #define NGX_HTTP_V2_STATUS_204_INDEX 9
39 #define NGX_HTTP_V2_STATUS_206_INDEX 10 47 #define NGX_HTTP_V2_STATUS_206_INDEX 10
51 #define NGX_HTTP_V2_VARY_INDEX 59 59 #define NGX_HTTP_V2_VARY_INDEX 59
52 60
53 #define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1 61 #define NGX_HTTP_V2_NO_TRAILERS (ngx_http_v2_out_frame_t *) -1
54 62
55 63
64 static ngx_int_t ngx_http_v2_push_resources(ngx_http_request_t *r);
65 static ngx_int_t ngx_http_v2_push_resource(ngx_http_request_t *r,
66 ngx_str_t *path, ngx_str_t *authority);
67
56 static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, 68 static u_char *ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len,
57 u_char *tmp, ngx_uint_t lower); 69 u_char *tmp, ngx_uint_t lower);
58 static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix, 70 static u_char *ngx_http_v2_write_int(u_char *pos, ngx_uint_t prefix,
59 ngx_uint_t value); 71 ngx_uint_t value);
60 static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame( 72 static ngx_http_v2_out_frame_t *ngx_http_v2_create_headers_frame(
61 ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin); 73 ngx_http_request_t *r, u_char *pos, u_char *end, ngx_uint_t fin);
74 static ngx_http_v2_out_frame_t *ngx_http_v2_create_push_frame(
75 ngx_http_request_t *r, u_char *pos, u_char *end);
62 static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame( 76 static ngx_http_v2_out_frame_t *ngx_http_v2_create_trailers_frame(
63 ngx_http_request_t *r); 77 ngx_http_request_t *r);
64 78
65 static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc, 79 static ngx_chain_t *ngx_http_v2_send_chain(ngx_connection_t *fc,
66 ngx_chain_t *in, off_t limit); 80 ngx_chain_t *in, off_t limit);
78 92
79 static ngx_inline ngx_int_t ngx_http_v2_filter_send( 93 static ngx_inline ngx_int_t ngx_http_v2_filter_send(
80 ngx_connection_t *fc, ngx_http_v2_stream_t *stream); 94 ngx_connection_t *fc, ngx_http_v2_stream_t *stream);
81 95
82 static ngx_int_t ngx_http_v2_headers_frame_handler( 96 static ngx_int_t ngx_http_v2_headers_frame_handler(
97 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
98 static ngx_int_t ngx_http_v2_push_frame_handler(
83 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); 99 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
84 static ngx_int_t ngx_http_v2_data_frame_handler( 100 static ngx_int_t ngx_http_v2_data_frame_handler(
85 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame); 101 ngx_http_v2_connection_t *h2c, ngx_http_v2_out_frame_t *frame);
86 static ngx_inline void ngx_http_v2_handle_frame( 102 static ngx_inline void ngx_http_v2_handle_frame(
87 ngx_http_v2_stream_t *stream, ngx_http_v2_out_frame_t *frame); 103 ngx_http_v2_stream_t *stream, ngx_http_v2_out_frame_t *frame);
239 } 255 }
240 } 256 }
241 257
242 h2c = stream->connection; 258 h2c = stream->connection;
243 259
260 if (!h2c->push_disabled && !h2c->goaway
261 && stream->node->id % 2 == 1
262 && r->method != NGX_HTTP_HEAD)
263 {
264 if (ngx_http_v2_push_resources(r) != NGX_OK) {
265 return NGX_ERROR;
266 }
267 }
268
244 len = h2c->table_update ? 1 : 0; 269 len = h2c->table_update ? 1 : 0;
245 270
246 len += status ? 1 : 1 + ngx_http_v2_literal_size("418"); 271 len += status ? 1 : 1 + ngx_http_v2_literal_size("418");
247 272
248 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); 273 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
636 return NGX_ERROR; 661 return NGX_ERROR;
637 } 662 }
638 663
639 ngx_http_v2_queue_blocked_frame(h2c, frame); 664 ngx_http_v2_queue_blocked_frame(h2c, frame);
640 665
641 stream->queued = 1; 666 stream->queued++;
642 667
643 cln = ngx_http_cleanup_add(r, 0); 668 cln = ngx_http_cleanup_add(r, 0);
644 if (cln == NULL) { 669 if (cln == NULL) {
645 return NGX_ERROR; 670 return NGX_ERROR;
646 } 671 }
650 675
651 fc->send_chain = ngx_http_v2_send_chain; 676 fc->send_chain = ngx_http_v2_send_chain;
652 fc->need_last_buf = 1; 677 fc->need_last_buf = 1;
653 678
654 return ngx_http_v2_filter_send(fc, stream); 679 return ngx_http_v2_filter_send(fc, stream);
680 }
681
682
683 static ngx_int_t
684 ngx_http_v2_push_resources(ngx_http_request_t *r)
685 {
686 u_char *start, *end, *last;
687 ngx_int_t rc;
688 ngx_str_t path, authority;
689 ngx_uint_t i, push;
690 ngx_table_elt_t **h;
691 ngx_connection_t *fc;
692 ngx_http_v2_stream_t *stream;
693 ngx_http_v2_loc_conf_t *h2lcf;
694 ngx_http_v2_connection_t *h2c;
695 ngx_http_complex_value_t *pushes;
696
697 fc = r->connection;
698
699 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 push resources");
700
701 stream = r->stream;
702 h2c = stream->connection;
703
704 ngx_str_null(&authority);
705
706 h2lcf = ngx_http_get_module_loc_conf(r, ngx_http_v2_module);
707
708 if (h2lcf->pushes) {
709 pushes = h2lcf->pushes->elts;
710
711 for (i = 0; i < h2lcf->pushes->nelts; i++) {
712
713 if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) {
714 return NGX_ERROR;
715 }
716
717 if (path.len == 0) {
718 continue;
719 }
720
721 if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) {
722 continue;
723 }
724
725 rc = ngx_http_v2_push_resource(r, &path, &authority);
726
727 if (rc == NGX_ERROR) {
728 return NGX_ERROR;
729 }
730
731 if (rc == NGX_ABORT) {
732 return NGX_OK;
733 }
734
735 /* NGX_OK, NGX_DECLINED */
736 }
737 }
738
739 if (!h2lcf->push_preload) {
740 return NGX_OK;
741 }
742
743 h = r->headers_out.link.elts;
744
745 for (i = 0; i < r->headers_out.link.nelts; i++) {
746
747 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
748 "http2 parse link: \"%V\"", &h[i]->value);
749
750 start = h[i]->value.data;
751 end = h[i]->value.data + h[i]->value.len;
752
753 next_link:
754
755 while (start < end && *start == ' ') { start++; }
756
757 if (start == end || *start++ != '<') {
758 continue;
759 }
760
761 while (start < end && *start == ' ') { start++; }
762
763 for (last = start; last < end && *last != '>'; last++) {
764 /* void */
765 }
766
767 if (last == start || last == end) {
768 continue;
769 }
770
771 path.len = last - start;
772 path.data = start;
773
774 start = last + 1;
775
776 while (start < end && *start == ' ') { start++; }
777
778 if (start == end) {
779 continue;
780 }
781
782 if (*start == ',') {
783 start++;
784 goto next_link;
785 }
786
787 if (*start++ != ';') {
788 continue;
789 }
790
791 last = ngx_strlchr(start, end, ',');
792
793 if (last == NULL) {
794 last = end;
795 }
796
797 push = 0;
798
799 for ( ;; ) {
800
801 while (start < last && *start == ' ') { start++; }
802
803 if (last - start >= 6
804 && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0)
805 {
806 start += 6;
807
808 if (start == last || *start == ' ' || *start == ';') {
809 push = 0;
810 break;
811 }
812
813 goto next_param;
814 }
815
816 if (last - start >= 11
817 && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0)
818 {
819 start += 11;
820
821 if (start == last || *start == ' ' || *start == ';') {
822 push = 1;
823 }
824
825 goto next_param;
826 }
827
828 if (last - start >= 4
829 && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0)
830 {
831 start += 4;
832
833 while (start < last && *start == ' ') { start++; }
834
835 if (start == last || *start++ != '"') {
836 goto next_param;
837 }
838
839 for ( ;; ) {
840
841 while (start < last && *start == ' ') { start++; }
842
843 if (last - start >= 7
844 && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0)
845 {
846 start += 7;
847
848 if (start < last && (*start == ' ' || *start == '"')) {
849 push = 1;
850 break;
851 }
852 }
853
854 while (start < last && *start != ' ' && *start != '"') {
855 start++;
856 }
857
858 if (start == last) {
859 break;
860 }
861
862 if (*start == '"') {
863 break;
864 }
865
866 start++;
867 }
868 }
869
870 next_param:
871
872 start = ngx_strlchr(start, last, ';');
873
874 if (start == NULL) {
875 break;
876 }
877
878 start++;
879 }
880
881 if (push) {
882 while (path.len && path.data[path.len - 1] == ' ') {
883 path.len--;
884 }
885 }
886
887 if (push && path.len
888 && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/'))
889 {
890 rc = ngx_http_v2_push_resource(r, &path, &authority);
891
892 if (rc == NGX_ERROR) {
893 return NGX_ERROR;
894 }
895
896 if (rc == NGX_ABORT) {
897 return NGX_OK;
898 }
899
900 /* NGX_OK, NGX_DECLINED */
901 }
902
903 if (last < end) {
904 start = last + 1;
905 goto next_link;
906 }
907 }
908
909 return NGX_OK;
910 }
911
912
913 static ngx_int_t
914 ngx_http_v2_push_resource(ngx_http_request_t *r, ngx_str_t *path,
915 ngx_str_t *authority)
916 {
917 u_char *start, *pos, *tmp;
918 size_t len;
919 ngx_table_elt_t *host;
920 ngx_connection_t *fc;
921 ngx_http_v2_stream_t *stream;
922 ngx_http_v2_out_frame_t *frame;
923 ngx_http_v2_connection_t *h2c;
924
925 fc = r->connection;
926
927 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 push resource");
928
929 stream = r->stream;
930 h2c = stream->connection;
931
932 if (!ngx_path_separator(path->data[0])) {
933 ngx_log_error(NGX_LOG_WARN, fc->log, 0,
934 "non-absolute path \"%V\" not pushed", path);
935 return NGX_DECLINED;
936 }
937
938 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
939 "http2 pushing:%ui limit:%ui",
940 h2c->pushing, h2c->concurrent_pushes);
941
942 if (h2c->pushing >= h2c->concurrent_pushes) {
943 return NGX_ABORT;
944 }
945
946 if (h2c->last_push == 0x7ffffffe) {
947 return NGX_ABORT;
948 }
949
950 if (path->len > NGX_HTTP_V2_MAX_FIELD) {
951 return NGX_DECLINED;
952 }
953
954 host = r->headers_in.host;
955
956 if (authority->len == 0 && host) {
957
958 len = 1 + NGX_HTTP_V2_INT_OCTETS + host->value.len;
959
960 tmp = ngx_palloc(r->pool, len);
961 pos = ngx_pnalloc(r->pool, len);
962
963 if (pos == NULL || tmp == NULL) {
964 return NGX_ERROR;
965 }
966
967 authority->data = pos;
968
969 *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_AUTHORITY_INDEX);
970 pos = ngx_http_v2_write_value(pos, host->value.data, host->value.len,
971 tmp);
972
973 authority->len = pos - authority->data;
974 }
975
976 len = (h2c->table_update ? 1 : 0)
977 + 1
978 + 1 + NGX_HTTP_V2_INT_OCTETS + path->len
979 + authority->len
980 + 1;
981
982 tmp = ngx_palloc(r->pool, len);
983 pos = ngx_pnalloc(r->pool, len);
984
985 if (pos == NULL || tmp == NULL) {
986 return NGX_ERROR;
987 }
988
989 start = pos;
990
991 if (h2c->table_update) {
992 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
993 "http2 table size update: 0");
994 *pos++ = (1 << 5) | 0;
995 h2c->table_update = 0;
996 }
997
998 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
999 "http2 push header: \":method: GET\"");
1000
1001 *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_METHOD_GET_INDEX);
1002
1003 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
1004 "http2 push header: \":path: %V\"", path);
1005
1006 *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_PATH_INDEX);
1007 pos = ngx_http_v2_write_value(pos, path->data, path->len, tmp);
1008
1009 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0,
1010 "http2 push header: \":authority: %V\"", &host->value);
1011
1012 pos = ngx_cpymem(pos, authority->data, authority->len);
1013
1014 #if (NGX_HTTP_SSL)
1015 if (fc->ssl) {
1016 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
1017 "http2 push header: \":scheme: https\"");
1018 *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTPS_INDEX);
1019
1020 } else
1021 #endif
1022 {
1023 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0,
1024 "http2 push header: \":scheme: http\"");
1025 *pos++ = ngx_http_v2_indexed(NGX_HTTP_V2_SCHEME_HTTP_INDEX);
1026 }
1027
1028 frame = ngx_http_v2_create_push_frame(r, start, pos);
1029 if (frame == NULL) {
1030 return NGX_ERROR;
1031 }
1032
1033 ngx_http_v2_queue_blocked_frame(h2c, frame);
1034
1035 stream->queued++;
1036
1037 return ngx_http_v2_push_stream(h2c, stream->node->id, pos - start,
1038 path, &host->value);
655 } 1039 }
656 1040
657 1041
658 static u_char * 1042 static u_char *
659 ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp, 1043 ngx_http_v2_string_encode(u_char *dst, u_char *src, size_t len, u_char *tmp,
800 frame->last = cl; 1184 frame->last = cl;
801 1185
802 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 1186 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
803 "http2:%ui create HEADERS frame %p: len:%uz", 1187 "http2:%ui create HEADERS frame %p: len:%uz",
804 stream->node->id, frame, frame->length); 1188 stream->node->id, frame, frame->length);
1189
1190 return frame;
1191 }
1192 }
1193
1194
1195 static ngx_http_v2_out_frame_t *
1196 ngx_http_v2_create_push_frame(ngx_http_request_t *r, u_char *pos, u_char *end)
1197 {
1198 u_char type, flags;
1199 size_t rest, frame_size, len;
1200 ngx_buf_t *b;
1201 ngx_chain_t *cl, **ll;
1202 ngx_http_v2_stream_t *stream;
1203 ngx_http_v2_out_frame_t *frame;
1204 ngx_http_v2_connection_t *h2c;
1205
1206 stream = r->stream;
1207 h2c = stream->connection;
1208 rest = NGX_HTTP_V2_STREAM_ID_SIZE + (end - pos);
1209
1210 frame = ngx_palloc(r->pool, sizeof(ngx_http_v2_out_frame_t));
1211 if (frame == NULL) {
1212 return NULL;
1213 }
1214
1215 frame->handler = ngx_http_v2_push_frame_handler;
1216 frame->stream = stream;
1217 frame->length = rest;
1218 frame->blocked = 1;
1219 frame->fin = 0;
1220
1221 ll = &frame->first;
1222
1223 type = NGX_HTTP_V2_PUSH_PROMISE_FRAME;
1224 flags = NGX_HTTP_V2_NO_FLAG;
1225 frame_size = h2c->frame_size;
1226
1227 for ( ;; ) {
1228 if (rest <= frame_size) {
1229 frame_size = rest;
1230 flags |= NGX_HTTP_V2_END_HEADERS_FLAG;
1231 }
1232
1233 b = ngx_create_temp_buf(r->pool,
1234 NGX_HTTP_V2_FRAME_HEADER_SIZE
1235 + ((type == NGX_HTTP_V2_PUSH_PROMISE_FRAME)
1236 ? NGX_HTTP_V2_STREAM_ID_SIZE : 0));
1237 if (b == NULL) {
1238 return NULL;
1239 }
1240
1241 b->last = ngx_http_v2_write_len_and_type(b->last, frame_size, type);
1242 *b->last++ = flags;
1243 b->last = ngx_http_v2_write_sid(b->last, stream->node->id);
1244
1245 b->tag = (ngx_buf_tag_t) &ngx_http_v2_module;
1246
1247 if (type == NGX_HTTP_V2_PUSH_PROMISE_FRAME) {
1248 h2c->last_push += 2;
1249
1250 b->last = ngx_http_v2_write_sid(b->last, h2c->last_push);
1251 len = frame_size - NGX_HTTP_V2_STREAM_ID_SIZE;
1252
1253 } else {
1254 len = frame_size;
1255 }
1256
1257 cl = ngx_alloc_chain_link(r->pool);
1258 if (cl == NULL) {
1259 return NULL;
1260 }
1261
1262 cl->buf = b;
1263
1264 *ll = cl;
1265 ll = &cl->next;
1266
1267 b = ngx_calloc_buf(r->pool);
1268 if (b == NULL) {
1269 return NULL;
1270 }
1271
1272 b->pos = pos;
1273
1274 pos += len;
1275
1276 b->last = pos;
1277 b->start = b->pos;
1278 b->end = b->last;
1279 b->temporary = 1;
1280
1281 cl = ngx_alloc_chain_link(r->pool);
1282 if (cl == NULL) {
1283 return NULL;
1284 }
1285
1286 cl->buf = b;
1287
1288 *ll = cl;
1289 ll = &cl->next;
1290
1291 rest -= frame_size;
1292
1293 if (rest) {
1294 frame->length += NGX_HTTP_V2_FRAME_HEADER_SIZE;
1295
1296 type = NGX_HTTP_V2_CONTINUATION_FRAME;
1297 continue;
1298 }
1299
1300 cl->next = NULL;
1301 frame->last = cl;
1302
1303 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1304 "http2:%ui create PUSH_PROMISE frame %p: "
1305 "sid:%ui len:%uz",
1306 stream->node->id, frame, h2c->last_push,
1307 frame->length);
805 1308
806 return frame; 1309 return frame;
807 } 1310 }
808 } 1311 }
809 1312
1375 return NGX_OK; 1878 return NGX_OK;
1376 } 1879 }
1377 1880
1378 1881
1379 static ngx_int_t 1882 static ngx_int_t
1883 ngx_http_v2_push_frame_handler(ngx_http_v2_connection_t *h2c,
1884 ngx_http_v2_out_frame_t *frame)
1885 {
1886 ngx_chain_t *cl, *ln;
1887 ngx_http_v2_stream_t *stream;
1888
1889 stream = frame->stream;
1890 cl = frame->first;
1891
1892 for ( ;; ) {
1893 if (cl->buf->pos != cl->buf->last) {
1894 frame->first = cl;
1895
1896 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1897 "http2:%ui PUSH_PROMISE frame %p was sent partially",
1898 stream->node->id, frame);
1899
1900 return NGX_AGAIN;
1901 }
1902
1903 ln = cl->next;
1904
1905 if (cl->buf->tag == (ngx_buf_tag_t) &ngx_http_v2_module) {
1906 cl->next = stream->free_frame_headers;
1907 stream->free_frame_headers = cl;
1908
1909 } else {
1910 cl->next = stream->free_bufs;
1911 stream->free_bufs = cl;
1912 }
1913
1914 if (cl == frame->last) {
1915 break;
1916 }
1917
1918 cl = ln;
1919 }
1920
1921 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0,
1922 "http2:%ui PUSH_PROMISE frame %p was sent",
1923 stream->node->id, frame);
1924
1925 stream->request->header_size += NGX_HTTP_V2_FRAME_HEADER_SIZE
1926 + frame->length;
1927
1928 ngx_http_v2_handle_frame(stream, frame);
1929
1930 ngx_http_v2_handle_stream(h2c, stream);
1931
1932 return NGX_OK;
1933 }
1934
1935
1936 static ngx_int_t
1380 ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c, 1937 ngx_http_v2_data_frame_handler(ngx_http_v2_connection_t *h2c,
1381 ngx_http_v2_out_frame_t *frame) 1938 ngx_http_v2_out_frame_t *frame)
1382 { 1939 {
1383 ngx_buf_t *buf; 1940 ngx_buf_t *buf;
1384 ngx_chain_t *cl, *ln; 1941 ngx_chain_t *cl, *ln;