Mercurial > hg > nginx
comparison src/http/v2/ngx_http_v2.c @ 9121:262c01782566
HTTP/2: removed server push (ticket #2432).
Although it has better implementation status than HTTP/3 server push,
it remains of limited use, with adoption numbers seen as negligible.
Per IETF 102 materials, server push was used only in 0.04% of sessions.
It was considered to be "difficult to use effectively" in RFC 9113.
Its use is further limited by badly matching to fetch/cache/connection
models in browsers, see related discussions linked from [1].
Server push was disabled in Chrome 106 [2].
The http2_push, http2_push_preload, and http2_max_concurrent_pushes
directives are made obsolete. In particular, this essentially reverts
7201:641306096f5b and 7207:3d2b0b02bd3d.
[1] https://jakearchibald.com/2017/h2-push-tougher-than-i-thought/
[2] https://chromestatus.com/feature/6302414934114304
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Thu, 08 Jun 2023 16:56:46 +0400 |
parents | 08ef02ad5c54 |
children | cdda286c0f1b |
comparison
equal
deleted
inserted
replaced
9120:0aaa09927703 | 9121:262c01782566 |
---|---|
7 | 7 |
8 #include <ngx_config.h> | 8 #include <ngx_config.h> |
9 #include <ngx_core.h> | 9 #include <ngx_core.h> |
10 #include <ngx_http.h> | 10 #include <ngx_http.h> |
11 #include <ngx_http_v2_module.h> | 11 #include <ngx_http_v2_module.h> |
12 | |
13 | |
14 typedef struct { | |
15 ngx_str_t name; | |
16 ngx_uint_t offset; | |
17 ngx_uint_t hash; | |
18 ngx_http_header_t *hh; | |
19 } ngx_http_v2_parse_header_t; | |
20 | 12 |
21 | 13 |
22 /* errors */ | 14 /* errors */ |
23 #define NGX_HTTP_V2_NO_ERROR 0x0 | 15 #define NGX_HTTP_V2_NO_ERROR 0x0 |
24 #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 | 16 #define NGX_HTTP_V2_PROTOCOL_ERROR 0x1 |
124 | 116 |
125 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, | 117 static ngx_int_t ngx_http_v2_parse_int(ngx_http_v2_connection_t *h2c, |
126 u_char **pos, u_char *end, ngx_uint_t prefix); | 118 u_char **pos, u_char *end, ngx_uint_t prefix); |
127 | 119 |
128 static ngx_http_v2_stream_t *ngx_http_v2_create_stream( | 120 static ngx_http_v2_stream_t *ngx_http_v2_create_stream( |
129 ngx_http_v2_connection_t *h2c, ngx_uint_t push); | 121 ngx_http_v2_connection_t *h2c); |
130 static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( | 122 static ngx_http_v2_node_t *ngx_http_v2_get_node_by_id( |
131 ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); | 123 ngx_http_v2_connection_t *h2c, ngx_uint_t sid, ngx_uint_t alloc); |
132 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( | 124 static ngx_http_v2_node_t *ngx_http_v2_get_closed_node( |
133 ngx_http_v2_connection_t *h2c); | 125 ngx_http_v2_connection_t *h2c); |
134 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) | 126 #define ngx_http_v2_index_size(h2scf) (h2scf->streams_index_mask + 1) |
160 ngx_str_t *value); | 152 ngx_str_t *value); |
161 static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r, | 153 static ngx_int_t ngx_http_v2_parse_scheme(ngx_http_request_t *r, |
162 ngx_str_t *value); | 154 ngx_str_t *value); |
163 static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, | 155 static ngx_int_t ngx_http_v2_parse_authority(ngx_http_request_t *r, |
164 ngx_str_t *value); | 156 ngx_str_t *value); |
165 static ngx_int_t ngx_http_v2_parse_header(ngx_http_request_t *r, | |
166 ngx_http_v2_parse_header_t *header, ngx_str_t *value); | |
167 static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); | 157 static ngx_int_t ngx_http_v2_construct_request_line(ngx_http_request_t *r); |
168 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, | 158 static ngx_int_t ngx_http_v2_cookie(ngx_http_request_t *r, |
169 ngx_http_v2_header_t *header); | 159 ngx_http_v2_header_t *header); |
170 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); | 160 static ngx_int_t ngx_http_v2_construct_cookie_header(ngx_http_request_t *r); |
171 static void ngx_http_v2_run_request(ngx_http_request_t *r); | 161 static void ngx_http_v2_run_request(ngx_http_request_t *r); |
172 static void ngx_http_v2_run_request_handler(ngx_event_t *ev); | |
173 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, | 162 static ngx_int_t ngx_http_v2_process_request_body(ngx_http_request_t *r, |
174 u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); | 163 u_char *pos, size_t size, ngx_uint_t last, ngx_uint_t flush); |
175 static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); | 164 static ngx_int_t ngx_http_v2_filter_request_body(ngx_http_request_t *r); |
176 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); | 165 static void ngx_http_v2_read_client_request_body_handler(ngx_http_request_t *r); |
177 | 166 |
208 | 197 |
209 #define NGX_HTTP_V2_FRAME_STATES \ | 198 #define NGX_HTTP_V2_FRAME_STATES \ |
210 (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) | 199 (sizeof(ngx_http_v2_frame_states) / sizeof(ngx_http_v2_handler_pt)) |
211 | 200 |
212 | 201 |
213 static ngx_http_v2_parse_header_t ngx_http_v2_parse_headers[] = { | |
214 { ngx_string("host"), | |
215 offsetof(ngx_http_headers_in_t, host), 0, NULL }, | |
216 | |
217 { ngx_string("accept-encoding"), | |
218 offsetof(ngx_http_headers_in_t, accept_encoding), 0, NULL }, | |
219 | |
220 { ngx_string("accept-language"), | |
221 offsetof(ngx_http_headers_in_t, accept_language), 0, NULL }, | |
222 | |
223 { ngx_string("user-agent"), | |
224 offsetof(ngx_http_headers_in_t, user_agent), 0, NULL }, | |
225 | |
226 { ngx_null_string, 0, 0, NULL } | |
227 }; | |
228 | |
229 | |
230 void | 202 void |
231 ngx_http_v2_init(ngx_event_t *rev) | 203 ngx_http_v2_init(ngx_event_t *rev) |
232 { | 204 { |
233 u_char *p, *end; | 205 u_char *p, *end; |
234 ngx_connection_t *c; | 206 ngx_connection_t *c; |
273 | 245 |
274 h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; | 246 h2c->frame_size = NGX_HTTP_V2_DEFAULT_FRAME_SIZE; |
275 | 247 |
276 h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); | 248 h2scf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_v2_module); |
277 | 249 |
278 h2c->concurrent_pushes = h2scf->concurrent_pushes; | |
279 h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); | 250 h2c->priority_limit = ngx_max(h2scf->concurrent_streams, 100); |
280 | 251 |
281 h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); | 252 h2c->pool = ngx_create_pool(h2scf->pool_size, h2c->connection->log); |
282 if (h2c->pool == NULL) { | 253 if (h2c->pool == NULL) { |
283 ngx_http_close_connection(c); | 254 ngx_http_close_connection(c); |
383 if (c->error) { | 354 if (c->error) { |
384 ngx_http_v2_finalize_connection(h2c, 0); | 355 ngx_http_v2_finalize_connection(h2c, 0); |
385 return; | 356 return; |
386 } | 357 } |
387 | 358 |
388 if (!h2c->processing && !h2c->pushing) { | 359 if (!h2c->processing) { |
389 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); | 360 ngx_http_v2_finalize_connection(h2c, NGX_HTTP_V2_NO_ERROR); |
390 return; | 361 return; |
391 } | 362 } |
392 | 363 |
393 if (!h2c->goaway) { | 364 if (!h2c->goaway) { |
426 | 397 |
427 if (n == NGX_AGAIN) { | 398 if (n == NGX_AGAIN) { |
428 break; | 399 break; |
429 } | 400 } |
430 | 401 |
431 if (n == 0 | 402 if (n == 0 && (h2c->state.incomplete || h2c->processing)) { |
432 && (h2c->state.incomplete || h2c->processing || h2c->pushing)) | |
433 { | |
434 ngx_log_error(NGX_LOG_INFO, c->log, 0, | 403 ngx_log_error(NGX_LOG_INFO, c->log, 0, |
435 "client prematurely closed connection"); | 404 "client prematurely closed connection"); |
436 } | 405 } |
437 | 406 |
438 if (n == 0 || n == NGX_ERROR) { | 407 if (n == 0 || n == NGX_ERROR) { |
651 { | 620 { |
652 ngx_int_t rc; | 621 ngx_int_t rc; |
653 ngx_connection_t *c; | 622 ngx_connection_t *c; |
654 ngx_http_core_loc_conf_t *clcf; | 623 ngx_http_core_loc_conf_t *clcf; |
655 | 624 |
656 if (h2c->last_out || h2c->processing || h2c->pushing) { | 625 if (h2c->last_out || h2c->processing) { |
657 return; | 626 return; |
658 } | 627 } |
659 | 628 |
660 c = h2c->connection; | 629 c = h2c->connection; |
661 | 630 |
1336 if (node->parent) { | 1305 if (node->parent) { |
1337 ngx_queue_remove(&node->reuse); | 1306 ngx_queue_remove(&node->reuse); |
1338 h2c->closed_nodes--; | 1307 h2c->closed_nodes--; |
1339 } | 1308 } |
1340 | 1309 |
1341 stream = ngx_http_v2_create_stream(h2c, 0); | 1310 stream = ngx_http_v2_create_stream(h2c); |
1342 if (stream == NULL) { | 1311 if (stream == NULL) { |
1343 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); | 1312 return ngx_http_v2_connection_error(h2c, NGX_HTTP_V2_INTERNAL_ERROR); |
1344 } | 1313 } |
1345 | 1314 |
1346 h2c->state.stream = stream; | 1315 h2c->state.stream = stream; |
2125 case NGX_HTTP_V2_CANCEL: | 2094 case NGX_HTTP_V2_CANCEL: |
2126 ngx_log_error(NGX_LOG_INFO, fc->log, 0, | 2095 ngx_log_error(NGX_LOG_INFO, fc->log, 0, |
2127 "client canceled stream %ui", h2c->state.sid); | 2096 "client canceled stream %ui", h2c->state.sid); |
2128 break; | 2097 break; |
2129 | 2098 |
2130 case NGX_HTTP_V2_REFUSED_STREAM: | |
2131 ngx_log_error(NGX_LOG_INFO, fc->log, 0, | |
2132 "client refused stream %ui", h2c->state.sid); | |
2133 break; | |
2134 | |
2135 case NGX_HTTP_V2_INTERNAL_ERROR: | 2099 case NGX_HTTP_V2_INTERNAL_ERROR: |
2136 ngx_log_error(NGX_LOG_INFO, fc->log, 0, | 2100 ngx_log_error(NGX_LOG_INFO, fc->log, 0, |
2137 "client terminated stream %ui due to internal error", | 2101 "client terminated stream %ui due to internal error", |
2138 h2c->state.sid); | 2102 h2c->state.sid); |
2139 break; | 2103 break; |
2197 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, | 2161 ngx_http_v2_state_settings_params(ngx_http_v2_connection_t *h2c, u_char *pos, |
2198 u_char *end) | 2162 u_char *end) |
2199 { | 2163 { |
2200 ssize_t window_delta; | 2164 ssize_t window_delta; |
2201 ngx_uint_t id, value; | 2165 ngx_uint_t id, value; |
2202 ngx_http_v2_srv_conf_t *h2scf; | |
2203 ngx_http_v2_out_frame_t *frame; | 2166 ngx_http_v2_out_frame_t *frame; |
2204 | 2167 |
2205 window_delta = 0; | 2168 window_delta = 0; |
2206 | 2169 |
2207 while (h2c->state.length) { | 2170 while (h2c->state.length) { |
2259 | 2222 |
2260 return ngx_http_v2_connection_error(h2c, | 2223 return ngx_http_v2_connection_error(h2c, |
2261 NGX_HTTP_V2_PROTOCOL_ERROR); | 2224 NGX_HTTP_V2_PROTOCOL_ERROR); |
2262 } | 2225 } |
2263 | 2226 |
2264 h2c->push_disabled = !value; | |
2265 break; | |
2266 | |
2267 case NGX_HTTP_V2_MAX_STREAMS_SETTING: | |
2268 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, | |
2269 ngx_http_v2_module); | |
2270 | |
2271 h2c->concurrent_pushes = ngx_min(value, h2scf->concurrent_pushes); | |
2272 break; | 2227 break; |
2273 | 2228 |
2274 case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: | 2229 case NGX_HTTP_V2_HEADER_TABLE_SIZE_SETTING: |
2275 | 2230 |
2276 h2c->table_update = 1; | 2231 h2c->table_update = 1; |
2718 if (end == start + NGX_HTTP_V2_INT_OCTETS) { | 2673 if (end == start + NGX_HTTP_V2_INT_OCTETS) { |
2719 return NGX_DECLINED; | 2674 return NGX_DECLINED; |
2720 } | 2675 } |
2721 | 2676 |
2722 return NGX_AGAIN; | 2677 return NGX_AGAIN; |
2723 } | |
2724 | |
2725 | |
2726 ngx_http_v2_stream_t * | |
2727 ngx_http_v2_push_stream(ngx_http_v2_stream_t *parent, ngx_str_t *path) | |
2728 { | |
2729 ngx_int_t rc; | |
2730 ngx_str_t value; | |
2731 ngx_pool_t *pool; | |
2732 ngx_uint_t index; | |
2733 ngx_table_elt_t **h; | |
2734 ngx_connection_t *fc; | |
2735 ngx_http_request_t *r; | |
2736 ngx_http_v2_node_t *node; | |
2737 ngx_http_v2_stream_t *stream; | |
2738 ngx_http_v2_srv_conf_t *h2scf; | |
2739 ngx_http_v2_connection_t *h2c; | |
2740 ngx_http_v2_parse_header_t *header; | |
2741 | |
2742 h2c = parent->connection; | |
2743 | |
2744 pool = ngx_create_pool(1024, h2c->connection->log); | |
2745 if (pool == NULL) { | |
2746 goto rst_stream; | |
2747 } | |
2748 | |
2749 node = ngx_http_v2_get_node_by_id(h2c, h2c->last_push, 1); | |
2750 | |
2751 if (node == NULL) { | |
2752 ngx_destroy_pool(pool); | |
2753 goto rst_stream; | |
2754 } | |
2755 | |
2756 stream = ngx_http_v2_create_stream(h2c, 1); | |
2757 if (stream == NULL) { | |
2758 | |
2759 if (node->parent == NULL) { | |
2760 h2scf = ngx_http_get_module_srv_conf(h2c->http_connection->conf_ctx, | |
2761 ngx_http_v2_module); | |
2762 | |
2763 index = ngx_http_v2_index(h2scf, h2c->last_push); | |
2764 h2c->streams_index[index] = node->index; | |
2765 | |
2766 ngx_queue_insert_tail(&h2c->closed, &node->reuse); | |
2767 h2c->closed_nodes++; | |
2768 } | |
2769 | |
2770 ngx_destroy_pool(pool); | |
2771 goto rst_stream; | |
2772 } | |
2773 | |
2774 if (node->parent) { | |
2775 ngx_queue_remove(&node->reuse); | |
2776 h2c->closed_nodes--; | |
2777 } | |
2778 | |
2779 stream->pool = pool; | |
2780 | |
2781 r = stream->request; | |
2782 fc = r->connection; | |
2783 | |
2784 stream->in_closed = 1; | |
2785 stream->node = node; | |
2786 | |
2787 node->stream = stream; | |
2788 | |
2789 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, | |
2790 "http2 push stream sid:%ui " | |
2791 "depends on %ui excl:0 weight:16", | |
2792 h2c->last_push, parent->node->id); | |
2793 | |
2794 node->weight = NGX_HTTP_V2_DEFAULT_WEIGHT; | |
2795 ngx_http_v2_set_dependency(h2c, node, parent->node->id, 0); | |
2796 | |
2797 r->method_name = ngx_http_core_get_method; | |
2798 r->method = NGX_HTTP_GET; | |
2799 | |
2800 r->schema.data = ngx_pstrdup(pool, &parent->request->schema); | |
2801 if (r->schema.data == NULL) { | |
2802 goto close; | |
2803 } | |
2804 | |
2805 r->schema.len = parent->request->schema.len; | |
2806 | |
2807 value.data = ngx_pstrdup(pool, path); | |
2808 if (value.data == NULL) { | |
2809 goto close; | |
2810 } | |
2811 | |
2812 value.len = path->len; | |
2813 | |
2814 rc = ngx_http_v2_parse_path(r, &value); | |
2815 | |
2816 if (rc != NGX_OK) { | |
2817 goto error; | |
2818 } | |
2819 | |
2820 for (header = ngx_http_v2_parse_headers; header->name.len; header++) { | |
2821 h = (ngx_table_elt_t **) | |
2822 ((char *) &parent->request->headers_in + header->offset); | |
2823 | |
2824 if (*h == NULL) { | |
2825 continue; | |
2826 } | |
2827 | |
2828 value.len = (*h)->value.len; | |
2829 | |
2830 value.data = ngx_pnalloc(pool, value.len + 1); | |
2831 if (value.data == NULL) { | |
2832 goto close; | |
2833 } | |
2834 | |
2835 ngx_memcpy(value.data, (*h)->value.data, value.len); | |
2836 value.data[value.len] = '\0'; | |
2837 | |
2838 rc = ngx_http_v2_parse_header(r, header, &value); | |
2839 | |
2840 if (rc != NGX_OK) { | |
2841 goto error; | |
2842 } | |
2843 } | |
2844 | |
2845 fc->write->handler = ngx_http_v2_run_request_handler; | |
2846 ngx_post_event(fc->write, &ngx_posted_events); | |
2847 | |
2848 return stream; | |
2849 | |
2850 error: | |
2851 | |
2852 if (rc == NGX_ABORT) { | |
2853 /* header handler has already finalized request */ | |
2854 ngx_http_run_posted_requests(fc); | |
2855 return NULL; | |
2856 } | |
2857 | |
2858 if (rc == NGX_DECLINED) { | |
2859 ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); | |
2860 ngx_http_run_posted_requests(fc); | |
2861 return NULL; | |
2862 } | |
2863 | |
2864 close: | |
2865 | |
2866 ngx_http_v2_close_stream(stream, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
2867 | |
2868 return NULL; | |
2869 | |
2870 rst_stream: | |
2871 | |
2872 if (ngx_http_v2_send_rst_stream(h2c, h2c->last_push, | |
2873 NGX_HTTP_INTERNAL_SERVER_ERROR) | |
2874 != NGX_OK) | |
2875 { | |
2876 h2c->connection->error = 1; | |
2877 } | |
2878 | |
2879 return NULL; | |
2880 } | 2678 } |
2881 | 2679 |
2882 | 2680 |
2883 static ngx_int_t | 2681 static ngx_int_t |
2884 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) | 2682 ngx_http_v2_send_settings(ngx_http_v2_connection_t *h2c) |
3149 return NGX_OK; | 2947 return NGX_OK; |
3150 } | 2948 } |
3151 | 2949 |
3152 | 2950 |
3153 static ngx_http_v2_stream_t * | 2951 static ngx_http_v2_stream_t * |
3154 ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c, ngx_uint_t push) | 2952 ngx_http_v2_create_stream(ngx_http_v2_connection_t *h2c) |
3155 { | 2953 { |
3156 ngx_log_t *log; | 2954 ngx_log_t *log; |
3157 ngx_event_t *rev, *wev; | 2955 ngx_event_t *rev, *wev; |
3158 ngx_connection_t *fc; | 2956 ngx_connection_t *fc; |
3159 ngx_http_log_ctx_t *ctx; | 2957 ngx_http_log_ctx_t *ctx; |
3204 } | 3002 } |
3205 | 3003 |
3206 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); | 3004 ngx_memcpy(log, h2c->connection->log, sizeof(ngx_log_t)); |
3207 | 3005 |
3208 log->data = ctx; | 3006 log->data = ctx; |
3209 | 3007 log->action = "reading client request headers"; |
3210 if (push) { | |
3211 log->action = "processing pushed request headers"; | |
3212 | |
3213 } else { | |
3214 log->action = "reading client request headers"; | |
3215 } | |
3216 | 3008 |
3217 ngx_memzero(rev, sizeof(ngx_event_t)); | 3009 ngx_memzero(rev, sizeof(ngx_event_t)); |
3218 | 3010 |
3219 rev->data = fc; | 3011 rev->data = fc; |
3220 rev->ready = 1; | 3012 rev->ready = 1; |
3282 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); | 3074 h2scf = ngx_http_get_module_srv_conf(r, ngx_http_v2_module); |
3283 | 3075 |
3284 stream->send_window = h2c->init_window; | 3076 stream->send_window = h2c->init_window; |
3285 stream->recv_window = h2scf->preread_size; | 3077 stream->recv_window = h2scf->preread_size; |
3286 | 3078 |
3287 if (push) { | 3079 h2c->processing++; |
3288 h2c->pushing++; | |
3289 | |
3290 } else { | |
3291 h2c->processing++; | |
3292 } | |
3293 | 3080 |
3294 h2c->priority_limit += h2scf->concurrent_streams; | 3081 h2c->priority_limit += h2scf->concurrent_streams; |
3295 | 3082 |
3296 if (h2c->connection->read->timer_set) { | 3083 if (h2c->connection->read->timer_set) { |
3297 ngx_del_timer(h2c->connection->read); | 3084 ngx_del_timer(h2c->connection->read); |
3710 | 3497 |
3711 | 3498 |
3712 static ngx_int_t | 3499 static ngx_int_t |
3713 ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) | 3500 ngx_http_v2_parse_authority(ngx_http_request_t *r, ngx_str_t *value) |
3714 { | 3501 { |
3715 return ngx_http_v2_parse_header(r, &ngx_http_v2_parse_headers[0], value); | |
3716 } | |
3717 | |
3718 | |
3719 static ngx_int_t | |
3720 ngx_http_v2_parse_header(ngx_http_request_t *r, | |
3721 ngx_http_v2_parse_header_t *header, ngx_str_t *value) | |
3722 { | |
3723 ngx_table_elt_t *h; | 3502 ngx_table_elt_t *h; |
3503 ngx_http_header_t *hh; | |
3724 ngx_http_core_main_conf_t *cmcf; | 3504 ngx_http_core_main_conf_t *cmcf; |
3505 | |
3506 static ngx_str_t host = ngx_string("host"); | |
3725 | 3507 |
3726 h = ngx_list_push(&r->headers_in.headers); | 3508 h = ngx_list_push(&r->headers_in.headers); |
3727 if (h == NULL) { | 3509 if (h == NULL) { |
3728 return NGX_ERROR; | 3510 return NGX_ERROR; |
3729 } | 3511 } |
3730 | 3512 |
3731 h->key.len = header->name.len; | 3513 h->hash = ngx_hash(ngx_hash(ngx_hash('h', 'o'), 's'), 't'); |
3732 h->key.data = header->name.data; | 3514 |
3733 h->lowcase_key = header->name.data; | 3515 h->key.len = host.len; |
3734 | 3516 h->key.data = host.data; |
3735 if (header->hh == NULL) { | |
3736 header->hash = ngx_hash_key(header->name.data, header->name.len); | |
3737 | |
3738 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
3739 | |
3740 header->hh = ngx_hash_find(&cmcf->headers_in_hash, header->hash, | |
3741 h->lowcase_key, h->key.len); | |
3742 if (header->hh == NULL) { | |
3743 return NGX_ERROR; | |
3744 } | |
3745 } | |
3746 | |
3747 h->hash = header->hash; | |
3748 | 3517 |
3749 h->value.len = value->len; | 3518 h->value.len = value->len; |
3750 h->value.data = value->data; | 3519 h->value.data = value->data; |
3751 | 3520 |
3752 if (header->hh->handler(r, h, header->hh->offset) != NGX_OK) { | 3521 h->lowcase_key = host.data; |
3753 /* header handler has already finalized request */ | 3522 |
3523 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
3524 | |
3525 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, | |
3526 h->lowcase_key, h->key.len); | |
3527 | |
3528 if (hh == NULL) { | |
3529 return NGX_ERROR; | |
3530 } | |
3531 | |
3532 if (hh->handler(r, h, hh->offset) != NGX_OK) { | |
3533 /* | |
3534 * request has been finalized already | |
3535 * in ngx_http_process_host() | |
3536 */ | |
3754 return NGX_ABORT; | 3537 return NGX_ABORT; |
3755 } | 3538 } |
3756 | 3539 |
3757 return NGX_OK; | 3540 return NGX_OK; |
3758 } | 3541 } |
3988 ngx_http_process_request(r); | 3771 ngx_http_process_request(r); |
3989 | 3772 |
3990 failed: | 3773 failed: |
3991 | 3774 |
3992 ngx_http_run_posted_requests(fc); | 3775 ngx_http_run_posted_requests(fc); |
3993 } | |
3994 | |
3995 | |
3996 static void | |
3997 ngx_http_v2_run_request_handler(ngx_event_t *ev) | |
3998 { | |
3999 ngx_connection_t *fc; | |
4000 ngx_http_request_t *r; | |
4001 | |
4002 fc = ev->data; | |
4003 r = fc->data; | |
4004 | |
4005 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, | |
4006 "http2 run request handler"); | |
4007 | |
4008 ngx_http_v2_run_request(r); | |
4009 } | 3776 } |
4010 | 3777 |
4011 | 3778 |
4012 ngx_int_t | 3779 ngx_int_t |
4013 ngx_http_v2_read_request_body(ngx_http_request_t *r) | 3780 ngx_http_v2_read_request_body(ngx_http_request_t *r) |
4610 | 4377 |
4611 void | 4378 void |
4612 ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) | 4379 ngx_http_v2_close_stream(ngx_http_v2_stream_t *stream, ngx_int_t rc) |
4613 { | 4380 { |
4614 ngx_pool_t *pool; | 4381 ngx_pool_t *pool; |
4615 ngx_uint_t push; | |
4616 ngx_event_t *ev; | 4382 ngx_event_t *ev; |
4617 ngx_connection_t *fc; | 4383 ngx_connection_t *fc; |
4618 ngx_http_v2_node_t *node; | 4384 ngx_http_v2_node_t *node; |
4619 ngx_http_v2_connection_t *h2c; | 4385 ngx_http_v2_connection_t *h2c; |
4620 | 4386 |
4621 h2c = stream->connection; | 4387 h2c = stream->connection; |
4622 node = stream->node; | 4388 node = stream->node; |
4623 | 4389 |
4624 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, | 4390 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, h2c->connection->log, 0, |
4625 "http2 close stream %ui, queued %ui, " | 4391 "http2 close stream %ui, queued %ui, processing %ui", |
4626 "processing %ui, pushing %ui", | 4392 node->id, stream->queued, h2c->processing); |
4627 node->id, stream->queued, h2c->processing, h2c->pushing); | |
4628 | 4393 |
4629 fc = stream->request->connection; | 4394 fc = stream->request->connection; |
4630 | 4395 |
4631 if (stream->queued) { | 4396 if (stream->queued) { |
4632 fc->error = 1; | 4397 fc->error = 1; |
4657 | 4422 |
4658 if (h2c->state.stream == stream) { | 4423 if (h2c->state.stream == stream) { |
4659 h2c->state.stream = NULL; | 4424 h2c->state.stream = NULL; |
4660 } | 4425 } |
4661 | 4426 |
4662 push = stream->node->id % 2 == 0; | |
4663 | |
4664 node->stream = NULL; | 4427 node->stream = NULL; |
4665 | 4428 |
4666 ngx_queue_insert_tail(&h2c->closed, &node->reuse); | 4429 ngx_queue_insert_tail(&h2c->closed, &node->reuse); |
4667 h2c->closed_nodes++; | 4430 h2c->closed_nodes++; |
4668 | 4431 |
4708 } | 4471 } |
4709 | 4472 |
4710 fc->data = h2c->free_fake_connections; | 4473 fc->data = h2c->free_fake_connections; |
4711 h2c->free_fake_connections = fc; | 4474 h2c->free_fake_connections = fc; |
4712 | 4475 |
4713 if (push) { | 4476 h2c->processing--; |
4714 h2c->pushing--; | 4477 |
4715 | 4478 if (h2c->processing || h2c->blocked) { |
4716 } else { | |
4717 h2c->processing--; | |
4718 } | |
4719 | |
4720 if (h2c->processing || h2c->pushing || h2c->blocked) { | |
4721 return; | 4479 return; |
4722 } | 4480 } |
4723 | 4481 |
4724 ev = h2c->connection->read; | 4482 ev = h2c->connection->read; |
4725 | 4483 |
4891 if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { | 4649 if (ngx_http_v2_send_goaway(h2c, status) != NGX_ERROR) { |
4892 (void) ngx_http_v2_send_output_queue(h2c); | 4650 (void) ngx_http_v2_send_output_queue(h2c); |
4893 } | 4651 } |
4894 } | 4652 } |
4895 | 4653 |
4896 if (!h2c->processing && !h2c->pushing) { | 4654 if (!h2c->processing) { |
4897 goto done; | 4655 goto done; |
4898 } | 4656 } |
4899 | 4657 |
4900 c->read->handler = ngx_http_empty_handler; | 4658 c->read->handler = ngx_http_empty_handler; |
4901 c->write->handler = ngx_http_empty_handler; | 4659 c->write->handler = ngx_http_empty_handler; |
4939 } | 4697 } |
4940 } | 4698 } |
4941 | 4699 |
4942 h2c->blocked = 0; | 4700 h2c->blocked = 0; |
4943 | 4701 |
4944 if (h2c->processing || h2c->pushing) { | 4702 if (h2c->processing) { |
4945 c->error = 1; | 4703 c->error = 1; |
4946 return; | 4704 return; |
4947 } | 4705 } |
4948 | 4706 |
4949 done: | 4707 done: |