Mercurial > hg > nginx
annotate src/http/v3/ngx_http_v3_request.c @ 8542:d3489d225f8f quic
QUIC: update packet length for short packets too.
During long packet header parsing, pkt->len is updated with the Length
field value that is used to find next coalesced packets in a datagram.
For short packets it still contained the whole QUIC packet size.
This change uniforms packet length handling to always contain the total
length of the packet number and protected packet payload in pkt->len.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 08 Sep 2020 13:27:39 +0300 |
parents | 830680e78b24 |
children | 9ffef6054abf |
rev | line source |
---|---|
8215 | 1 |
2 /* | |
3 * Copyright (C) Roman Arutyunyan | |
4 * Copyright (C) Nginx, Inc. | |
5 */ | |
6 | |
7 | |
8 #include <ngx_config.h> | |
9 #include <ngx_core.h> | |
10 #include <ngx_http.h> | |
11 | |
12 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
13 /* static table indices */ |
8497 | 14 #define NGX_HTTP_V3_HEADER_AUTHORITY 0 |
15 #define NGX_HTTP_V3_HEADER_PATH_ROOT 1 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
16 #define NGX_HTTP_V3_HEADER_CONTENT_LENGTH_ZERO 4 |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
17 #define NGX_HTTP_V3_HEADER_DATE 6 |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
18 #define NGX_HTTP_V3_HEADER_LAST_MODIFIED 10 |
8489
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
19 #define NGX_HTTP_V3_HEADER_LOCATION 12 |
8497 | 20 #define NGX_HTTP_V3_HEADER_METHOD_GET 17 |
21 #define NGX_HTTP_V3_HEADER_SCHEME_HTTP 22 | |
22 #define NGX_HTTP_V3_HEADER_SCHEME_HTTPS 23 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
23 #define NGX_HTTP_V3_HEADER_STATUS_200 25 |
8497 | 24 #define NGX_HTTP_V3_HEADER_ACCEPT_ENCODING 31 |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
25 #define NGX_HTTP_V3_HEADER_CONTENT_TYPE_TEXT_PLAIN 53 |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
26 #define NGX_HTTP_V3_HEADER_VARY_ACCEPT_ENCODING 59 |
8497 | 27 #define NGX_HTTP_V3_HEADER_ACCEPT_LANGUAGE 72 |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
28 #define NGX_HTTP_V3_HEADER_SERVER 92 |
8497 | 29 #define NGX_HTTP_V3_HEADER_USER_AGENT 95 |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
30 |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
31 |
8215 | 32 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, |
33 ngx_str_t *name, ngx_str_t *value); | |
8497 | 34 static ngx_int_t ngx_http_v3_push_resources(ngx_http_request_t *r, |
35 ngx_chain_t ***out); | |
36 static ngx_int_t ngx_http_v3_push_resource(ngx_http_request_t *r, | |
37 ngx_str_t *path, ngx_chain_t ***out); | |
38 static ngx_int_t ngx_http_v3_create_push_request( | |
39 ngx_http_request_t *pr, ngx_str_t *path, uint64_t push_id); | |
40 static ngx_int_t ngx_http_v3_set_push_header(ngx_http_request_t *r, | |
41 const char *name, ngx_str_t *value); | |
42 static void ngx_http_v3_push_request_handler(ngx_event_t *ev); | |
43 static ngx_chain_t *ngx_http_v3_create_push_promise(ngx_http_request_t *r, | |
44 ngx_str_t *path, uint64_t push_id); | |
8215 | 45 |
46 | |
47 struct { | |
48 ngx_str_t name; | |
49 ngx_uint_t method; | |
50 } ngx_http_v3_methods[] = { | |
51 | |
52 { ngx_string("GET"), NGX_HTTP_GET }, | |
53 { ngx_string("POST"), NGX_HTTP_POST }, | |
54 { ngx_string("HEAD"), NGX_HTTP_HEAD }, | |
55 { ngx_string("OPTIONS"), NGX_HTTP_OPTIONS }, | |
56 { ngx_string("PROPFIND"), NGX_HTTP_PROPFIND }, | |
57 { ngx_string("PUT"), NGX_HTTP_PUT }, | |
58 { ngx_string("MKCOL"), NGX_HTTP_MKCOL }, | |
59 { ngx_string("DELETE"), NGX_HTTP_DELETE }, | |
60 { ngx_string("COPY"), NGX_HTTP_COPY }, | |
61 { ngx_string("MOVE"), NGX_HTTP_MOVE }, | |
62 { ngx_string("PROPPATCH"), NGX_HTTP_PROPPATCH }, | |
63 { ngx_string("LOCK"), NGX_HTTP_LOCK }, | |
64 { ngx_string("UNLOCK"), NGX_HTTP_UNLOCK }, | |
65 { ngx_string("PATCH"), NGX_HTTP_PATCH }, | |
66 { ngx_string("TRACE"), NGX_HTTP_TRACE } | |
67 }; | |
68 | |
69 | |
70 ngx_int_t | |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
71 ngx_http_v3_parse_request(ngx_http_request_t *r, ngx_buf_t *b) |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
72 { |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
73 size_t len; |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
74 u_char *p; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
75 ngx_int_t rc, n; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
76 ngx_str_t *name, *value; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
77 ngx_connection_t *c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
78 ngx_http_v3_parse_headers_t *st; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
79 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
80 c = r->connection; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
81 st = r->h3_parse; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
82 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
83 if (st == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
84 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
85 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
86 st = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_parse_headers_t)); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
87 if (st == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
88 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
89 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
90 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
91 r->h3_parse = st; |
8407
d6feece1288a
Fixed $request_length for HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8406
diff
changeset
|
92 r->parse_start = b->pos; |
8408
5b367070cc9c
Fixed client buffer reallocation for HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8407
diff
changeset
|
93 r->state = 1; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
94 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
95 |
8230
31f7c697b6d9
Fixed pointer increment while parsing HTTP/3 header.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
96 while (b->pos < b->last) { |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
97 rc = ngx_http_v3_parse_headers(c, st, *b->pos); |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
98 |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
99 if (rc > 0) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
100 ngx_http_v3_finalize_connection(c, rc, |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
101 "could not parse request headers"); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
102 goto failed; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
103 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
104 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
105 if (rc == NGX_ERROR) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
106 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
107 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
108 |
8456
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
109 if (rc == NGX_BUSY) { |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
110 return NGX_BUSY; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
111 } |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
112 |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
113 b->pos++; |
c9538aef3211
HTTP/3: refactored dynamic table implementation.
Roman Arutyunyan <arut@nginx.com>
parents:
8452
diff
changeset
|
114 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
115 if (rc == NGX_AGAIN) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
116 continue; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
117 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
118 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
119 name = &st->header_rep.header.name; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
120 value = &st->header_rep.header.value; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
121 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
122 n = ngx_http_v3_process_pseudo_header(r, name, value); |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
123 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
124 if (n == NGX_ERROR) { |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
125 goto failed; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
126 } |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
127 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
128 if (n == NGX_OK && rc == NGX_OK) { |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
129 continue; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
130 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
131 |
8494
e334ca1b23ba
HTTP/3: support $server_protocol variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8490
diff
changeset
|
132 ngx_str_set(&r->http_protocol, "HTTP/3.0"); |
e334ca1b23ba
HTTP/3: support $server_protocol variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8490
diff
changeset
|
133 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
134 len = (r->method_end - r->method_start) + 1 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
135 + (r->uri_end - r->uri_start) + 1 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
136 + sizeof("HTTP/3") - 1; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
137 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
138 p = ngx_pnalloc(c->pool, len); |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
139 if (p == NULL) { |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
140 goto failed; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
141 } |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
142 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
143 r->request_start = p; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
144 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
145 p = ngx_cpymem(p, r->method_start, r->method_end - r->method_start); |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
146 *p++ = ' '; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
147 p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start); |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
148 *p++ = ' '; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
149 p = ngx_cpymem(p, "HTTP/3", sizeof("HTTP/3") - 1); |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
150 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
151 r->request_end = p; |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
152 r->state = 0; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
153 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
154 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
155 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
156 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
157 return NGX_AGAIN; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
158 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
159 failed: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
160 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
161 return NGX_HTTP_PARSE_INVALID_REQUEST; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
162 } |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
163 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
164 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
165 ngx_int_t |
8406
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
166 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
167 ngx_uint_t allow_underscores) |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
168 { |
8406
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
169 u_char ch; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
170 ngx_int_t rc; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
171 ngx_str_t *name, *value; |
8406
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
172 ngx_uint_t hash, i, n; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
173 ngx_connection_t *c; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
174 ngx_http_v3_parse_headers_t *st; |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
175 enum { |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
176 sw_start = 0, |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
177 sw_done, |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
178 sw_next, |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
179 sw_header |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
180 }; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
181 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
182 c = r->connection; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
183 st = r->h3_parse; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
184 |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
185 switch (r->state) { |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
186 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
187 case sw_start: |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
188 r->parse_start = b->pos; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
189 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
190 if (st->state) { |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
191 r->state = sw_next; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
192 goto done; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
193 } |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
194 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
195 name = &st->header_rep.header.name; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
196 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
197 if (name->len && name->data[0] != ':') { |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
198 r->state = sw_done; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
199 goto done; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
200 } |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
201 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
202 /* fall through */ |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
203 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
204 case sw_done: |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
205 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
206 "http3 parse header done"); |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
207 return NGX_HTTP_PARSE_HEADER_DONE; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
208 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
209 case sw_next: |
8407
d6feece1288a
Fixed $request_length for HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8406
diff
changeset
|
210 r->parse_start = b->pos; |
8406
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
211 r->invalid_header = 0; |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
212 break; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
213 |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
214 case sw_header: |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
215 break; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
216 } |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
217 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
218 while (b->pos < b->last) { |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
219 rc = ngx_http_v3_parse_headers(c, st, *b->pos++); |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
220 |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
221 if (rc > 0) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
222 ngx_http_v3_finalize_connection(c, rc, |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
223 "could not parse request headers"); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
224 return NGX_HTTP_PARSE_INVALID_HEADER; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
225 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
226 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
227 if (rc == NGX_ERROR) { |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
228 return NGX_HTTP_PARSE_INVALID_HEADER; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
229 } |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
230 |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
231 if (rc == NGX_DONE) { |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
232 r->state = sw_done; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
233 goto done; |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
234 } |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
235 |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
236 if (rc == NGX_OK) { |
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
237 r->state = sw_next; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
238 goto done; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
239 } |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
240 } |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
241 |
8452
a6675a976560
HTTP/3: fixed dropping first non-pseudo header.
Roman Arutyunyan <arut@nginx.com>
parents:
8451
diff
changeset
|
242 r->state = sw_header; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
243 return NGX_AGAIN; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
244 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
245 done: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
246 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
247 name = &st->header_rep.header.name; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
248 value = &st->header_rep.header.value; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
249 |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
250 r->header_name_start = name->data; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
251 r->header_name_end = name->data + name->len; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
252 r->header_start = value->data; |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
253 r->header_end = value->data + value->len; |
8406
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
254 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
255 hash = 0; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
256 i = 0; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
257 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
258 for (n = 0; n < name->len; n++) { |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
259 ch = name->data[n]; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
260 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
261 if (ch >= 'A' && ch <= 'Z') { |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
262 /* |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
263 * A request or response containing uppercase |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
264 * header field names MUST be treated as malformed |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
265 */ |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
266 return NGX_HTTP_PARSE_INVALID_HEADER; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
267 } |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
268 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
269 if (ch == '\0') { |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
270 return NGX_HTTP_PARSE_INVALID_HEADER; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
271 } |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
272 |
8406
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
273 if (ch == '_' && !allow_underscores) { |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
274 r->invalid_header = 1; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
275 continue; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
276 } |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
277 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
278 if ((ch < 'a' || ch > 'z') |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
279 && (ch < '0' || ch > '9') |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
280 && ch != '-' && ch != '_') |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
281 { |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
282 r->invalid_header = 1; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
283 continue; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
284 } |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
285 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
286 hash = ngx_hash(hash, ch); |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
287 r->lowcase_header[i++] = ch; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
288 i &= (NGX_HTTP_LC_HEADER_LEN - 1); |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
289 } |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
290 |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
291 r->header_hash = hash; |
66feab03d9b7
HTTP/3: restricted symbols in header names.
Roman Arutyunyan <arut@nginx.com>
parents:
8405
diff
changeset
|
292 r->lowcase_index = i; |
8405
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
293 |
d2759e4cc437
HTTP/3: split header parser in two functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8394
diff
changeset
|
294 return NGX_OK; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
295 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
296 |
8215 | 297 |
298 static ngx_int_t | |
299 ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, | |
300 ngx_str_t *value) | |
301 { | |
302 ngx_uint_t i; | |
303 ngx_connection_t *c; | |
304 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
305 if (name->len == 0 || name->data[0] != ':') { |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
306 return NGX_DONE; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
307 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
308 |
8215 | 309 c = r->connection; |
310 | |
311 if (name->len == 7 && ngx_strncmp(name->data, ":method", 7) == 0) { | |
312 r->method_start = value->data; | |
313 r->method_end = value->data + value->len; | |
314 | |
315 for (i = 0; i < sizeof(ngx_http_v3_methods) | |
316 / sizeof(ngx_http_v3_methods[0]); i++) | |
317 { | |
318 if (value->len == ngx_http_v3_methods[i].name.len | |
319 && ngx_strncmp(value->data, ngx_http_v3_methods[i].name.data, | |
320 value->len) == 0) | |
321 { | |
322 r->method = ngx_http_v3_methods[i].method; | |
323 break; | |
324 } | |
325 } | |
326 | |
327 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
328 "http3 method \"%V\" %ui", value, r->method); | |
329 return NGX_OK; | |
330 } | |
331 | |
332 if (name->len == 5 && ngx_strncmp(name->data, ":path", 5) == 0) { | |
333 r->uri_start = value->data; | |
334 r->uri_end = value->data + value->len; | |
335 | |
336 if (ngx_http_parse_uri(r) != NGX_OK) { | |
337 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
338 "client sent invalid :path header: \"%V\"", value); | |
339 return NGX_ERROR; | |
340 } | |
341 | |
342 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
343 "http3 path \"%V\"", value); | |
344 | |
345 return NGX_OK; | |
346 } | |
347 | |
348 if (name->len == 7 && ngx_strncmp(name->data, ":scheme", 7) == 0) { | |
349 r->schema_start = value->data; | |
350 r->schema_end = value->data + value->len; | |
351 | |
352 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
353 "http3 schema \"%V\"", value); | |
354 | |
355 return NGX_OK; | |
356 } | |
357 | |
358 if (name->len == 10 && ngx_strncmp(name->data, ":authority", 10) == 0) { | |
359 r->host_start = value->data; | |
360 r->host_end = value->data + value->len; | |
361 | |
362 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
363 "http3 authority \"%V\"", value); | |
364 | |
365 return NGX_OK; | |
366 } | |
367 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
368 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
369 "http3 unknown pseudo header \"%V\" \"%V\"", name, value); |
8215 | 370 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
371 return NGX_OK; |
8215 | 372 } |
373 | |
374 | |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
375 ngx_int_t |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
376 ngx_http_v3_parse_request_body(ngx_http_request_t *r, ngx_buf_t *b, |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
377 ngx_http_chunked_t *ctx) |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
378 { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
379 ngx_int_t rc; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
380 ngx_connection_t *c; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
381 ngx_http_v3_parse_data_t *st; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
382 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
383 c = r->connection; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
384 st = ctx->h3_parse; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
385 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
386 if (st == NULL) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
387 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
388 "http3 parse request body"); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
389 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
390 st = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_parse_data_t)); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
391 if (st == NULL) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
392 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
393 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
394 |
8511
830680e78b24
HTTP/3: fixed context storage in request body parser.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8497
diff
changeset
|
395 ctx->h3_parse = st; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
396 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
397 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
398 if (ctx->size) { |
8329
7bd334b8d91a
HTTP/3: fixed reading request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8295
diff
changeset
|
399 ctx->length = ctx->size + 1; |
7bd334b8d91a
HTTP/3: fixed reading request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8295
diff
changeset
|
400 return (b->pos == b->last) ? NGX_AGAIN : NGX_OK; |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
401 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
402 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
403 while (b->pos < b->last) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
404 rc = ngx_http_v3_parse_data(c, st, *b->pos++); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
405 |
8460
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
406 if (rc > 0) { |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
407 ngx_http_v3_finalize_connection(c, rc, |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
408 "could not parse request body"); |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
409 goto failed; |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
410 } |
72f9ff4e0a88
HTTP/3: close QUIC connection with HTTP/QPACK errors when needed.
Roman Arutyunyan <arut@nginx.com>
parents:
8456
diff
changeset
|
411 |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
412 if (rc == NGX_ERROR) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
413 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
414 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
415 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
416 if (rc == NGX_AGAIN) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
417 continue; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
418 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
419 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
420 /* rc == NGX_DONE */ |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
421 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
422 ctx->size = st->length; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
423 return NGX_OK; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
424 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
425 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
426 if (!b->last_buf) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
427 ctx->length = 1; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
428 return NGX_AGAIN; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
429 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
430 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
431 if (st->state) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
432 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
433 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
434 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
435 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header done"); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
436 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
437 return NGX_DONE; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
438 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
439 failed: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
440 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
441 return NGX_ERROR; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
442 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
443 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
444 |
8215 | 445 ngx_chain_t * |
446 ngx_http_v3_create_header(ngx_http_request_t *r) | |
447 { | |
448 u_char *p; | |
8253
69365c7bb07f
Removed unused variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8238
diff
changeset
|
449 size_t len, n; |
8215 | 450 ngx_buf_t *b; |
8489
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
451 ngx_str_t host; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
452 ngx_uint_t i, port; |
8497 | 453 ngx_chain_t *out, *hl, *cl, **ll; |
8215 | 454 ngx_list_part_t *part; |
455 ngx_table_elt_t *header; | |
456 ngx_connection_t *c; | |
457 ngx_http_core_loc_conf_t *clcf; | |
8489
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
458 ngx_http_core_srv_conf_t *cscf; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
459 u_char addr[NGX_SOCKADDR_STRLEN]; |
8215 | 460 |
461 c = r->connection; | |
462 | |
463 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 create header"); | |
464 | |
8497 | 465 out = NULL; |
466 ll = &out; | |
467 | |
468 if ((c->qs->id & NGX_QUIC_STREAM_UNIDIRECTIONAL) == 0 | |
469 && r->method != NGX_HTTP_HEAD) | |
470 { | |
471 if (ngx_http_v3_push_resources(r, &ll) != NGX_OK) { | |
472 return NULL; | |
473 } | |
474 } | |
475 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
476 len = ngx_http_v3_encode_header_block_prefix(NULL, 0, 0, 0); |
8215 | 477 |
478 if (r->headers_out.status == NGX_HTTP_OK) { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
479 len += ngx_http_v3_encode_header_ri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
480 NGX_HTTP_V3_HEADER_STATUS_200); |
8215 | 481 |
482 } else { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
483 len += ngx_http_v3_encode_header_lri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
484 NGX_HTTP_V3_HEADER_STATUS_200, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
485 NULL, 3); |
8215 | 486 } |
487 | |
488 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
489 | |
490 if (r->headers_out.server == NULL) { | |
491 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
492 n = sizeof(NGINX_VER) - 1; | |
493 | |
494 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
495 n = sizeof(NGINX_VER_BUILD) - 1; | |
496 | |
497 } else { | |
498 n = sizeof("nginx") - 1; | |
499 } | |
500 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
501 len += ngx_http_v3_encode_header_lri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
502 NGX_HTTP_V3_HEADER_SERVER, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
503 NULL, n); |
8215 | 504 } |
505 | |
506 if (r->headers_out.date == NULL) { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
507 len += ngx_http_v3_encode_header_lri(NULL, 0, NGX_HTTP_V3_HEADER_DATE, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
508 NULL, ngx_cached_http_time.len); |
8215 | 509 } |
510 | |
511 if (r->headers_out.content_type.len) { | |
512 n = r->headers_out.content_type.len; | |
513 | |
514 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
515 && r->headers_out.charset.len) | |
516 { | |
517 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
518 } | |
519 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
520 len += ngx_http_v3_encode_header_lri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
521 NGX_HTTP_V3_HEADER_CONTENT_TYPE_TEXT_PLAIN, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
522 NULL, n); |
8215 | 523 } |
524 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
525 if (r->headers_out.content_length == NULL) { |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
526 if (r->headers_out.content_length_n > 0) { |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
527 len += ngx_http_v3_encode_header_lri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
528 NGX_HTTP_V3_HEADER_CONTENT_LENGTH_ZERO, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
529 NULL, NGX_OFF_T_LEN); |
8215 | 530 |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
531 } else if (r->headers_out.content_length_n == 0) { |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
532 len += ngx_http_v3_encode_header_ri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
533 NGX_HTTP_V3_HEADER_CONTENT_LENGTH_ZERO); |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
534 } |
8215 | 535 } |
536 | |
537 if (r->headers_out.last_modified == NULL | |
538 && r->headers_out.last_modified_time != -1) | |
539 { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
540 len += ngx_http_v3_encode_header_lri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
541 NGX_HTTP_V3_HEADER_LAST_MODIFIED, NULL, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
542 sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1); |
8215 | 543 } |
544 | |
8489
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
545 if (r->headers_out.location |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
546 && r->headers_out.location->value.len |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
547 && r->headers_out.location->value.data[0] == '/' |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
548 && clcf->absolute_redirect) |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
549 { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
550 r->headers_out.location->hash = 0; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
551 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
552 if (clcf->server_name_in_redirect) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
553 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
554 host = cscf->server_name; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
555 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
556 } else if (r->headers_in.server.len) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
557 host = r->headers_in.server; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
558 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
559 } else { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
560 host.len = NGX_SOCKADDR_STRLEN; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
561 host.data = addr; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
562 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
563 if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
564 return NULL; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
565 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
566 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
567 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
568 port = ngx_inet_get_port(c->local_sockaddr); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
569 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
570 n = sizeof("https://") - 1 + host.len |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
571 + r->headers_out.location->value.len; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
572 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
573 if (clcf->port_in_redirect) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
574 port = (port == 443) ? 0 : port; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
575 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
576 } else { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
577 port = 0; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
578 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
579 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
580 if (port) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
581 n += sizeof(":65535") - 1; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
582 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
583 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
584 len += ngx_http_v3_encode_header_lri(NULL, 0, |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
585 NGX_HTTP_V3_HEADER_LOCATION, NULL, n); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
586 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
587 } else { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
588 ngx_str_null(&host); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
589 port = 0; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
590 } |
8215 | 591 |
592 #if (NGX_HTTP_GZIP) | |
593 if (r->gzip_vary) { | |
594 if (clcf->gzip_vary) { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
595 len += ngx_http_v3_encode_header_ri(NULL, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
596 NGX_HTTP_V3_HEADER_VARY_ACCEPT_ENCODING); |
8215 | 597 |
598 } else { | |
599 r->gzip_vary = 0; | |
600 } | |
601 } | |
602 #endif | |
603 | |
604 part = &r->headers_out.headers.part; | |
605 header = part->elts; | |
606 | |
607 for (i = 0; /* void */; i++) { | |
608 | |
609 if (i >= part->nelts) { | |
610 if (part->next == NULL) { | |
611 break; | |
612 } | |
613 | |
614 part = part->next; | |
615 header = part->elts; | |
616 i = 0; | |
617 } | |
618 | |
619 if (header[i].hash == 0) { | |
620 continue; | |
621 } | |
622 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
623 len += ngx_http_v3_encode_header_l(NULL, &header[i].key, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
624 &header[i].value); |
8215 | 625 } |
626 | |
627 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 header len:%uz", len); | |
628 | |
629 b = ngx_create_temp_buf(r->pool, len); | |
630 if (b == NULL) { | |
631 return NULL; | |
632 } | |
633 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
634 b->last = (u_char *) ngx_http_v3_encode_header_block_prefix(b->last, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
635 0, 0, 0); |
8215 | 636 |
637 if (r->headers_out.status == NGX_HTTP_OK) { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
638 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
639 NGX_HTTP_V3_HEADER_STATUS_200); |
8215 | 640 |
641 } else { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
642 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
643 NGX_HTTP_V3_HEADER_STATUS_200, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
644 NULL, 3); |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
645 b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); |
8215 | 646 } |
647 | |
648 if (r->headers_out.server == NULL) { | |
649 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
650 p = (u_char *) NGINX_VER; | |
651 n = sizeof(NGINX_VER) - 1; | |
652 | |
653 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
654 p = (u_char *) NGINX_VER_BUILD; | |
655 n = sizeof(NGINX_VER_BUILD) - 1; | |
656 | |
657 } else { | |
658 p = (u_char *) "nginx"; | |
659 n = sizeof("nginx") - 1; | |
660 } | |
661 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
662 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
663 NGX_HTTP_V3_HEADER_SERVER, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
664 p, n); |
8215 | 665 } |
666 | |
667 if (r->headers_out.date == NULL) { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
668 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
669 NGX_HTTP_V3_HEADER_DATE, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
670 ngx_cached_http_time.data, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
671 ngx_cached_http_time.len); |
8215 | 672 } |
673 | |
674 if (r->headers_out.content_type.len) { | |
675 n = r->headers_out.content_type.len; | |
676 | |
677 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
678 && r->headers_out.charset.len) | |
679 { | |
680 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
681 } | |
682 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
683 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
684 NGX_HTTP_V3_HEADER_CONTENT_TYPE_TEXT_PLAIN, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
685 NULL, n); |
8215 | 686 |
687 p = b->last; | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
688 b->last = ngx_cpymem(b->last, r->headers_out.content_type.data, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
689 r->headers_out.content_type.len); |
8215 | 690 |
691 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
692 && r->headers_out.charset.len) | |
693 { | |
694 b->last = ngx_cpymem(b->last, "; charset=", | |
695 sizeof("; charset=") - 1); | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
696 b->last = ngx_cpymem(b->last, r->headers_out.charset.data, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
697 r->headers_out.charset.len); |
8215 | 698 |
699 /* update r->headers_out.content_type for possible logging */ | |
700 | |
701 r->headers_out.content_type.len = b->last - p; | |
702 r->headers_out.content_type.data = p; | |
703 } | |
704 } | |
705 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
706 if (r->headers_out.content_length == NULL) { |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
707 if (r->headers_out.content_length_n > 0) { |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
708 p = ngx_sprintf(b->last, "%O", r->headers_out.content_length_n); |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
709 n = p - b->last; |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
710 |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
711 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
712 NGX_HTTP_V3_HEADER_CONTENT_LENGTH_ZERO, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
713 NULL, n); |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
714 |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
715 b->last = ngx_sprintf(b->last, "%O", |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
716 r->headers_out.content_length_n); |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
717 |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
718 } else if (r->headers_out.content_length_n == 0) { |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
719 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
720 NGX_HTTP_V3_HEADER_CONTENT_LENGTH_ZERO); |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
721 } |
8215 | 722 } |
723 | |
724 if (r->headers_out.last_modified == NULL | |
725 && r->headers_out.last_modified_time != -1) | |
726 { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
727 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
728 NGX_HTTP_V3_HEADER_LAST_MODIFIED, NULL, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
729 sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1); |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
730 |
8215 | 731 b->last = ngx_http_time(b->last, r->headers_out.last_modified_time); |
732 } | |
733 | |
8489
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
734 if (host.data) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
735 n = sizeof("https://") - 1 + host.len |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
736 + r->headers_out.location->value.len; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
737 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
738 if (port) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
739 n += ngx_sprintf(b->last, ":%ui", port) - b->last; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
740 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
741 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
742 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
743 NGX_HTTP_V3_HEADER_LOCATION, |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
744 NULL, n); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
745 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
746 p = b->last; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
747 b->last = ngx_cpymem(b->last, "https://", sizeof("https://") - 1); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
748 b->last = ngx_cpymem(b->last, host.data, host.len); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
749 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
750 if (port) { |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
751 b->last = ngx_sprintf(b->last, ":%ui", port); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
752 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
753 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
754 b->last = ngx_cpymem(b->last, r->headers_out.location->value.data, |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
755 r->headers_out.location->value.len); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
756 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
757 /* update r->headers_out.location->value for possible logging */ |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
758 |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
759 r->headers_out.location->value.len = b->last - p; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
760 r->headers_out.location->value.data = p; |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
761 ngx_str_set(&r->headers_out.location->key, "Location"); |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
762 } |
5d2e285677a7
HTTP/3: generate Location response header for absolute redirects.
Roman Arutyunyan <arut@nginx.com>
parents:
8488
diff
changeset
|
763 |
8215 | 764 #if (NGX_HTTP_GZIP) |
765 if (r->gzip_vary) { | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
766 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
767 NGX_HTTP_V3_HEADER_VARY_ACCEPT_ENCODING); |
8215 | 768 } |
769 #endif | |
770 | |
771 part = &r->headers_out.headers.part; | |
772 header = part->elts; | |
773 | |
774 for (i = 0; /* void */; i++) { | |
775 | |
776 if (i >= part->nelts) { | |
777 if (part->next == NULL) { | |
778 break; | |
779 } | |
780 | |
781 part = part->next; | |
782 header = part->elts; | |
783 i = 0; | |
784 } | |
785 | |
786 if (header[i].hash == 0) { | |
787 continue; | |
788 } | |
789 | |
8488
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
790 b->last = (u_char *) ngx_http_v3_encode_header_l(b->last, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
791 &header[i].key, |
79125ef2e39f
HTTP/3: header encoding functions.
Roman Arutyunyan <arut@nginx.com>
parents:
8460
diff
changeset
|
792 &header[i].value); |
8215 | 793 } |
794 | |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
795 if (r->header_only) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
796 b->last_buf = 1; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
797 } |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
798 |
8215 | 799 cl = ngx_alloc_chain_link(c->pool); |
800 if (cl == NULL) { | |
801 return NULL; | |
802 } | |
803 | |
804 cl->buf = b; | |
805 cl->next = NULL; | |
806 | |
807 n = b->last - b->pos; | |
808 | |
8490
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
809 len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_HEADERS) |
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
810 + ngx_http_v3_encode_varlen_int(NULL, n); |
8215 | 811 |
812 b = ngx_create_temp_buf(c->pool, len); | |
813 if (b == NULL) { | |
814 return NULL; | |
815 } | |
816 | |
8490
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
817 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, |
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
818 NGX_HTTP_V3_FRAME_HEADERS); |
8215 | 819 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n); |
820 | |
821 hl = ngx_alloc_chain_link(c->pool); | |
822 if (hl == NULL) { | |
823 return NULL; | |
824 } | |
825 | |
826 hl->buf = b; | |
827 hl->next = cl; | |
828 | |
8497 | 829 *ll = hl; |
830 ll = &cl->next; | |
831 | |
8451
908cae4f3078
HTTP/3: do not emit a DATA frame header for header_only responses.
Sergey Kandaurov <pluknet@nginx.com>
parents:
8408
diff
changeset
|
832 if (r->headers_out.content_length_n >= 0 && !r->header_only) { |
8490
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
833 len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_DATA) |
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
834 + ngx_http_v3_encode_varlen_int(NULL, |
8215 | 835 r->headers_out.content_length_n); |
836 | |
837 b = ngx_create_temp_buf(c->pool, len); | |
838 if (b == NULL) { | |
8394 | 839 return NULL; |
8215 | 840 } |
841 | |
8490
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
842 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, |
e24f7b50ba1d
HTTP/3: encode frame ids with ngx_http_v3_encode_varlen_int().
Roman Arutyunyan <arut@nginx.com>
parents:
8489
diff
changeset
|
843 NGX_HTTP_V3_FRAME_DATA); |
8215 | 844 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, |
845 r->headers_out.content_length_n); | |
846 | |
8497 | 847 cl = ngx_alloc_chain_link(c->pool); |
848 if (cl == NULL) { | |
8215 | 849 return NULL; |
850 } | |
851 | |
8497 | 852 cl->buf = b; |
853 cl->next = NULL; | |
854 | |
855 *ll = cl; | |
8215 | 856 } |
857 | |
8497 | 858 return out; |
8215 | 859 } |
8292
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
860 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
861 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
862 ngx_chain_t * |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
863 ngx_http_v3_create_trailers(ngx_http_request_t *r) |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
864 { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
865 ngx_buf_t *b; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
866 ngx_chain_t *cl; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
867 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
868 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
869 "http3 create trailers"); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
870 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
871 /* XXX */ |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
872 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
873 b = ngx_calloc_buf(r->pool); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
874 if (b == NULL) { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
875 return NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
876 } |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
877 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
878 b->last_buf = 1; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
879 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
880 cl = ngx_alloc_chain_link(r->pool); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
881 if (cl == NULL) { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
882 return NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
883 } |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
884 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
885 cl->buf = b; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
886 cl->next = NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
887 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
888 return cl; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
889 } |
8497 | 890 |
891 | |
892 static ngx_int_t | |
893 ngx_http_v3_push_resources(ngx_http_request_t *r, ngx_chain_t ***out) | |
894 { | |
895 u_char *start, *end, *last; | |
896 ngx_str_t path; | |
897 ngx_int_t rc; | |
898 ngx_uint_t i, push; | |
899 ngx_table_elt_t **h; | |
900 ngx_http_v3_loc_conf_t *h3lcf; | |
901 ngx_http_complex_value_t *pushes; | |
902 | |
903 h3lcf = ngx_http_get_module_loc_conf(r, ngx_http_v3_module); | |
904 | |
905 if (h3lcf->pushes) { | |
906 pushes = h3lcf->pushes->elts; | |
907 | |
908 for (i = 0; i < h3lcf->pushes->nelts; i++) { | |
909 | |
910 if (ngx_http_complex_value(r, &pushes[i], &path) != NGX_OK) { | |
911 return NGX_ERROR; | |
912 } | |
913 | |
914 if (path.len == 0) { | |
915 continue; | |
916 } | |
917 | |
918 if (path.len == 3 && ngx_strncmp(path.data, "off", 3) == 0) { | |
919 continue; | |
920 } | |
921 | |
922 rc = ngx_http_v3_push_resource(r, &path, out); | |
923 | |
924 if (rc == NGX_ERROR) { | |
925 return NGX_ERROR; | |
926 } | |
927 | |
928 if (rc == NGX_ABORT) { | |
929 return NGX_OK; | |
930 } | |
931 | |
932 /* NGX_OK, NGX_DECLINED */ | |
933 } | |
934 } | |
935 | |
936 if (!h3lcf->push_preload) { | |
937 return NGX_OK; | |
938 } | |
939 | |
940 h = r->headers_out.link.elts; | |
941 | |
942 for (i = 0; i < r->headers_out.link.nelts; i++) { | |
943 | |
944 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
945 "http3 parse link: \"%V\"", &h[i]->value); | |
946 | |
947 start = h[i]->value.data; | |
948 end = h[i]->value.data + h[i]->value.len; | |
949 | |
950 next_link: | |
951 | |
952 while (start < end && *start == ' ') { start++; } | |
953 | |
954 if (start == end || *start++ != '<') { | |
955 continue; | |
956 } | |
957 | |
958 while (start < end && *start == ' ') { start++; } | |
959 | |
960 for (last = start; last < end && *last != '>'; last++) { | |
961 /* void */ | |
962 } | |
963 | |
964 if (last == start || last == end) { | |
965 continue; | |
966 } | |
967 | |
968 path.len = last - start; | |
969 path.data = start; | |
970 | |
971 start = last + 1; | |
972 | |
973 while (start < end && *start == ' ') { start++; } | |
974 | |
975 if (start == end) { | |
976 continue; | |
977 } | |
978 | |
979 if (*start == ',') { | |
980 start++; | |
981 goto next_link; | |
982 } | |
983 | |
984 if (*start++ != ';') { | |
985 continue; | |
986 } | |
987 | |
988 last = ngx_strlchr(start, end, ','); | |
989 | |
990 if (last == NULL) { | |
991 last = end; | |
992 } | |
993 | |
994 push = 0; | |
995 | |
996 for ( ;; ) { | |
997 | |
998 while (start < last && *start == ' ') { start++; } | |
999 | |
1000 if (last - start >= 6 | |
1001 && ngx_strncasecmp(start, (u_char *) "nopush", 6) == 0) | |
1002 { | |
1003 start += 6; | |
1004 | |
1005 if (start == last || *start == ' ' || *start == ';') { | |
1006 push = 0; | |
1007 break; | |
1008 } | |
1009 | |
1010 goto next_param; | |
1011 } | |
1012 | |
1013 if (last - start >= 11 | |
1014 && ngx_strncasecmp(start, (u_char *) "rel=preload", 11) == 0) | |
1015 { | |
1016 start += 11; | |
1017 | |
1018 if (start == last || *start == ' ' || *start == ';') { | |
1019 push = 1; | |
1020 } | |
1021 | |
1022 goto next_param; | |
1023 } | |
1024 | |
1025 if (last - start >= 4 | |
1026 && ngx_strncasecmp(start, (u_char *) "rel=", 4) == 0) | |
1027 { | |
1028 start += 4; | |
1029 | |
1030 while (start < last && *start == ' ') { start++; } | |
1031 | |
1032 if (start == last || *start++ != '"') { | |
1033 goto next_param; | |
1034 } | |
1035 | |
1036 for ( ;; ) { | |
1037 | |
1038 while (start < last && *start == ' ') { start++; } | |
1039 | |
1040 if (last - start >= 7 | |
1041 && ngx_strncasecmp(start, (u_char *) "preload", 7) == 0) | |
1042 { | |
1043 start += 7; | |
1044 | |
1045 if (start < last && (*start == ' ' || *start == '"')) { | |
1046 push = 1; | |
1047 break; | |
1048 } | |
1049 } | |
1050 | |
1051 while (start < last && *start != ' ' && *start != '"') { | |
1052 start++; | |
1053 } | |
1054 | |
1055 if (start == last) { | |
1056 break; | |
1057 } | |
1058 | |
1059 if (*start == '"') { | |
1060 break; | |
1061 } | |
1062 | |
1063 start++; | |
1064 } | |
1065 } | |
1066 | |
1067 next_param: | |
1068 | |
1069 start = ngx_strlchr(start, last, ';'); | |
1070 | |
1071 if (start == NULL) { | |
1072 break; | |
1073 } | |
1074 | |
1075 start++; | |
1076 } | |
1077 | |
1078 if (push) { | |
1079 while (path.len && path.data[path.len - 1] == ' ') { | |
1080 path.len--; | |
1081 } | |
1082 } | |
1083 | |
1084 if (push && path.len | |
1085 && !(path.len > 1 && path.data[0] == '/' && path.data[1] == '/')) | |
1086 { | |
1087 rc = ngx_http_v3_push_resource(r, &path, out); | |
1088 | |
1089 if (rc == NGX_ERROR) { | |
1090 return NGX_ERROR; | |
1091 } | |
1092 | |
1093 if (rc == NGX_ABORT) { | |
1094 return NGX_OK; | |
1095 } | |
1096 | |
1097 /* NGX_OK, NGX_DECLINED */ | |
1098 } | |
1099 | |
1100 if (last < end) { | |
1101 start = last + 1; | |
1102 goto next_link; | |
1103 } | |
1104 } | |
1105 | |
1106 return NGX_OK; | |
1107 } | |
1108 | |
1109 | |
1110 static ngx_int_t | |
1111 ngx_http_v3_push_resource(ngx_http_request_t *r, ngx_str_t *path, | |
1112 ngx_chain_t ***ll) | |
1113 { | |
1114 uint64_t push_id; | |
1115 ngx_int_t rc; | |
1116 ngx_chain_t *cl; | |
1117 ngx_connection_t *c; | |
1118 ngx_http_v3_srv_conf_t *h3scf; | |
1119 ngx_http_v3_connection_t *h3c; | |
1120 | |
1121 c = r->connection; | |
1122 h3c = c->qs->parent->data; | |
1123 h3scf = ngx_http_get_module_srv_conf(r, ngx_http_v3_module); | |
1124 | |
1125 ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1126 "http3 push \"%V\" pushing:%ui/%ui id:%uL/%uL", | |
1127 path, h3c->npushing, h3scf->max_concurrent_pushes, | |
1128 h3c->next_push_id, h3c->max_push_id); | |
1129 | |
1130 if (!ngx_path_separator(path->data[0])) { | |
1131 ngx_log_error(NGX_LOG_WARN, c->log, 0, | |
1132 "non-absolute path \"%V\" not pushed", path); | |
1133 return NGX_DECLINED; | |
1134 } | |
1135 | |
1136 if (h3c->next_push_id > h3c->max_push_id) { | |
1137 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1138 "http3 abort pushes due to max_push_id"); | |
1139 return NGX_ABORT; | |
1140 } | |
1141 | |
1142 if (h3c->npushing >= h3scf->max_concurrent_pushes) { | |
1143 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
1144 "http3 abort pushes due to max_concurrent_pushes"); | |
1145 return NGX_ABORT; | |
1146 } | |
1147 | |
1148 push_id = h3c->next_push_id++; | |
1149 | |
1150 rc = ngx_http_v3_create_push_request(r, path, push_id); | |
1151 if (rc != NGX_OK) { | |
1152 return rc; | |
1153 } | |
1154 | |
1155 cl = ngx_http_v3_create_push_promise(r, path, push_id); | |
1156 if (cl == NULL) { | |
1157 return NGX_ERROR; | |
1158 } | |
1159 | |
1160 for (**ll = cl; **ll; *ll = &(**ll)->next); | |
1161 | |
1162 return NGX_OK; | |
1163 } | |
1164 | |
1165 | |
1166 static ngx_int_t | |
1167 ngx_http_v3_create_push_request(ngx_http_request_t *pr, ngx_str_t *path, | |
1168 uint64_t push_id) | |
1169 { | |
1170 ngx_pool_t *pool; | |
1171 ngx_connection_t *c, *pc; | |
1172 ngx_http_request_t *r; | |
1173 ngx_http_log_ctx_t *ctx; | |
1174 ngx_http_connection_t *hc; | |
1175 ngx_http_core_srv_conf_t *cscf; | |
1176 ngx_http_v3_connection_t *h3c; | |
1177 | |
1178 pc = pr->connection; | |
1179 | |
1180 r = NULL; | |
1181 | |
1182 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, | |
1183 "http3 create push request id:%uL", push_id); | |
1184 | |
1185 c = ngx_http_v3_create_push_stream(pc, push_id); | |
1186 if (c == NULL) { | |
1187 return NGX_ABORT; | |
1188 } | |
1189 | |
1190 hc = ngx_palloc(c->pool, sizeof(ngx_http_connection_t)); | |
1191 if (hc == NULL) { | |
1192 goto failed; | |
1193 } | |
1194 | |
1195 h3c = c->qs->parent->data; | |
1196 ngx_memcpy(hc, h3c, sizeof(ngx_http_connection_t)); | |
1197 c->data = hc; | |
1198 | |
1199 ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); | |
1200 if (ctx == NULL) { | |
1201 goto failed; | |
1202 } | |
1203 | |
1204 ctx->connection = c; | |
1205 ctx->request = NULL; | |
1206 ctx->current_request = NULL; | |
1207 | |
1208 c->log->handler = ngx_http_log_error; | |
1209 c->log->data = ctx; | |
1210 c->log->action = "processing pushed request headers"; | |
1211 | |
1212 c->log_error = NGX_ERROR_INFO; | |
1213 | |
1214 r = ngx_http_create_request(c); | |
1215 if (r == NULL) { | |
1216 goto failed; | |
1217 } | |
1218 | |
1219 c->data = r; | |
1220 | |
1221 ngx_str_set(&r->http_protocol, "HTTP/3.0"); | |
1222 | |
1223 r->method_name = ngx_http_core_get_method; | |
1224 r->method = NGX_HTTP_GET; | |
1225 | |
1226 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); | |
1227 | |
1228 r->header_in = ngx_create_temp_buf(r->pool, | |
1229 cscf->client_header_buffer_size); | |
1230 if (r->header_in == NULL) { | |
1231 goto failed; | |
1232 } | |
1233 | |
1234 if (ngx_list_init(&r->headers_in.headers, r->pool, 4, | |
1235 sizeof(ngx_table_elt_t)) | |
1236 != NGX_OK) | |
1237 { | |
1238 goto failed; | |
1239 } | |
1240 | |
1241 r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; | |
1242 | |
1243 r->schema.data = ngx_pstrdup(r->pool, &pr->schema); | |
1244 if (r->schema.data == NULL) { | |
1245 goto failed; | |
1246 } | |
1247 | |
1248 r->schema.len = pr->schema.len; | |
1249 | |
1250 r->uri_start = ngx_pstrdup(r->pool, path); | |
1251 if (r->uri_start == NULL) { | |
1252 goto failed; | |
1253 } | |
1254 | |
1255 r->uri_end = r->uri_start + path->len; | |
1256 | |
1257 if (ngx_http_parse_uri(r) != NGX_OK) { | |
1258 goto failed; | |
1259 } | |
1260 | |
1261 if (ngx_http_process_request_uri(r) != NGX_OK) { | |
1262 goto failed; | |
1263 } | |
1264 | |
1265 if (ngx_http_v3_set_push_header(r, "host", &pr->headers_in.server) | |
1266 != NGX_OK) | |
1267 { | |
1268 goto failed; | |
1269 } | |
1270 | |
1271 if (pr->headers_in.accept_encoding) { | |
1272 if (ngx_http_v3_set_push_header(r, "accept-encoding", | |
1273 &pr->headers_in.accept_encoding->value) | |
1274 != NGX_OK) | |
1275 { | |
1276 goto failed; | |
1277 } | |
1278 } | |
1279 | |
1280 if (pr->headers_in.accept_language) { | |
1281 if (ngx_http_v3_set_push_header(r, "accept-language", | |
1282 &pr->headers_in.accept_language->value) | |
1283 != NGX_OK) | |
1284 { | |
1285 goto failed; | |
1286 } | |
1287 } | |
1288 | |
1289 if (pr->headers_in.user_agent) { | |
1290 if (ngx_http_v3_set_push_header(r, "user-agent", | |
1291 &pr->headers_in.user_agent->value) | |
1292 != NGX_OK) | |
1293 { | |
1294 goto failed; | |
1295 } | |
1296 } | |
1297 | |
1298 c->read->handler = ngx_http_v3_push_request_handler; | |
1299 c->read->handler = ngx_http_v3_push_request_handler; | |
1300 | |
1301 ngx_post_event(c->read, &ngx_posted_events); | |
1302 | |
1303 return NGX_OK; | |
1304 | |
1305 failed: | |
1306 | |
1307 if (r) { | |
1308 ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); | |
1309 } | |
1310 | |
1311 c->destroyed = 1; | |
1312 | |
1313 pool = c->pool; | |
1314 | |
1315 ngx_close_connection(c); | |
1316 | |
1317 ngx_destroy_pool(pool); | |
1318 | |
1319 return NGX_ERROR; | |
1320 } | |
1321 | |
1322 | |
1323 static ngx_int_t | |
1324 ngx_http_v3_set_push_header(ngx_http_request_t *r, const char *name, | |
1325 ngx_str_t *value) | |
1326 { | |
1327 u_char *p; | |
1328 ngx_table_elt_t *h; | |
1329 ngx_http_header_t *hh; | |
1330 ngx_http_core_main_conf_t *cmcf; | |
1331 | |
1332 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1333 "http3 push header \"%s\": \"%V\"", name, value); | |
1334 | |
1335 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
1336 | |
1337 p = ngx_pnalloc(r->pool, value->len + 1); | |
1338 if (p == NULL) { | |
1339 return NGX_ERROR; | |
1340 } | |
1341 | |
1342 ngx_memcpy(p, value->data, value->len); | |
1343 p[value->len] = '\0'; | |
1344 | |
1345 h = ngx_list_push(&r->headers_in.headers); | |
1346 if (h == NULL) { | |
1347 return NGX_ERROR; | |
1348 } | |
1349 | |
1350 h->key.data = (u_char *) name; | |
1351 h->key.len = ngx_strlen(name); | |
1352 h->hash = ngx_hash_key(h->key.data, h->key.len); | |
1353 h->lowcase_key = (u_char *) name; | |
1354 h->value.data = p; | |
1355 h->value.len = value->len; | |
1356 | |
1357 hh = ngx_hash_find(&cmcf->headers_in_hash, h->hash, | |
1358 h->lowcase_key, h->key.len); | |
1359 | |
1360 if (hh && hh->handler(r, h, hh->offset) != NGX_OK) { | |
1361 return NGX_ERROR; | |
1362 } | |
1363 | |
1364 return NGX_OK; | |
1365 } | |
1366 | |
1367 | |
1368 static void | |
1369 ngx_http_v3_push_request_handler(ngx_event_t *ev) | |
1370 { | |
1371 ngx_connection_t *c; | |
1372 ngx_http_request_t *r; | |
1373 | |
1374 c = ev->data; | |
1375 r = c->data; | |
1376 | |
1377 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 push request handler"); | |
1378 | |
1379 ngx_http_process_request(r); | |
1380 } | |
1381 | |
1382 | |
1383 static ngx_chain_t * | |
1384 ngx_http_v3_create_push_promise(ngx_http_request_t *r, ngx_str_t *path, | |
1385 uint64_t push_id) | |
1386 { | |
1387 size_t n, len; | |
1388 ngx_buf_t *b; | |
1389 ngx_chain_t *hl, *cl; | |
1390 | |
1391 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
1392 "http3 create push promise id:%uL", push_id); | |
1393 | |
1394 len = ngx_http_v3_encode_varlen_int(NULL, push_id); | |
1395 | |
1396 len += ngx_http_v3_encode_header_block_prefix(NULL, 0, 0, 0); | |
1397 | |
1398 len += ngx_http_v3_encode_header_ri(NULL, 0, | |
1399 NGX_HTTP_V3_HEADER_METHOD_GET); | |
1400 | |
1401 len += ngx_http_v3_encode_header_lri(NULL, 0, | |
1402 NGX_HTTP_V3_HEADER_AUTHORITY, | |
1403 NULL, r->headers_in.server.len); | |
1404 | |
1405 if (path->len == 1 && path->data[0] == '/') { | |
1406 len += ngx_http_v3_encode_header_ri(NULL, 0, | |
1407 NGX_HTTP_V3_HEADER_PATH_ROOT); | |
1408 | |
1409 } else { | |
1410 len += ngx_http_v3_encode_header_lri(NULL, 0, | |
1411 NGX_HTTP_V3_HEADER_PATH_ROOT, | |
1412 NULL, path->len); | |
1413 } | |
1414 | |
1415 if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { | |
1416 len += ngx_http_v3_encode_header_ri(NULL, 0, | |
1417 NGX_HTTP_V3_HEADER_SCHEME_HTTPS); | |
1418 | |
1419 } else if (r->schema.len == 4 | |
1420 && ngx_strncmp(r->schema.data, "http", 4) == 0) | |
1421 { | |
1422 len += ngx_http_v3_encode_header_ri(NULL, 0, | |
1423 NGX_HTTP_V3_HEADER_SCHEME_HTTP); | |
1424 | |
1425 } else { | |
1426 len += ngx_http_v3_encode_header_lri(NULL, 0, | |
1427 NGX_HTTP_V3_HEADER_SCHEME_HTTP, | |
1428 NULL, r->schema.len); | |
1429 } | |
1430 | |
1431 if (r->headers_in.accept_encoding) { | |
1432 len += ngx_http_v3_encode_header_lri(NULL, 0, | |
1433 NGX_HTTP_V3_HEADER_ACCEPT_ENCODING, NULL, | |
1434 r->headers_in.accept_encoding->value.len); | |
1435 } | |
1436 | |
1437 if (r->headers_in.accept_language) { | |
1438 len += ngx_http_v3_encode_header_lri(NULL, 0, | |
1439 NGX_HTTP_V3_HEADER_ACCEPT_LANGUAGE, NULL, | |
1440 r->headers_in.accept_language->value.len); | |
1441 } | |
1442 | |
1443 if (r->headers_in.user_agent) { | |
1444 len += ngx_http_v3_encode_header_lri(NULL, 0, | |
1445 NGX_HTTP_V3_HEADER_USER_AGENT, NULL, | |
1446 r->headers_in.user_agent->value.len); | |
1447 } | |
1448 | |
1449 b = ngx_create_temp_buf(r->pool, len); | |
1450 if (b == NULL) { | |
1451 return NULL; | |
1452 } | |
1453 | |
1454 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, push_id); | |
1455 | |
1456 b->last = (u_char *) ngx_http_v3_encode_header_block_prefix(b->last, | |
1457 0, 0, 0); | |
1458 | |
1459 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, | |
1460 NGX_HTTP_V3_HEADER_METHOD_GET); | |
1461 | |
1462 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, | |
1463 NGX_HTTP_V3_HEADER_AUTHORITY, | |
1464 r->headers_in.server.data, | |
1465 r->headers_in.server.len); | |
1466 | |
1467 if (path->len == 1 && path->data[0] == '/') { | |
1468 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, | |
1469 NGX_HTTP_V3_HEADER_PATH_ROOT); | |
1470 | |
1471 } else { | |
1472 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, | |
1473 NGX_HTTP_V3_HEADER_PATH_ROOT, | |
1474 path->data, path->len); | |
1475 } | |
1476 | |
1477 if (r->schema.len == 5 && ngx_strncmp(r->schema.data, "https", 5) == 0) { | |
1478 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, | |
1479 NGX_HTTP_V3_HEADER_SCHEME_HTTPS); | |
1480 | |
1481 } else if (r->schema.len == 4 | |
1482 && ngx_strncmp(r->schema.data, "http", 4) == 0) | |
1483 { | |
1484 b->last = (u_char *) ngx_http_v3_encode_header_ri(b->last, 0, | |
1485 NGX_HTTP_V3_HEADER_SCHEME_HTTP); | |
1486 | |
1487 } else { | |
1488 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, | |
1489 NGX_HTTP_V3_HEADER_SCHEME_HTTP, | |
1490 r->schema.data, r->schema.len); | |
1491 } | |
1492 | |
1493 if (r->headers_in.accept_encoding) { | |
1494 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, | |
1495 NGX_HTTP_V3_HEADER_ACCEPT_ENCODING, | |
1496 r->headers_in.accept_encoding->value.data, | |
1497 r->headers_in.accept_encoding->value.len); | |
1498 } | |
1499 | |
1500 if (r->headers_in.accept_language) { | |
1501 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, | |
1502 NGX_HTTP_V3_HEADER_ACCEPT_LANGUAGE, | |
1503 r->headers_in.accept_language->value.data, | |
1504 r->headers_in.accept_language->value.len); | |
1505 } | |
1506 | |
1507 if (r->headers_in.user_agent) { | |
1508 b->last = (u_char *) ngx_http_v3_encode_header_lri(b->last, 0, | |
1509 NGX_HTTP_V3_HEADER_USER_AGENT, | |
1510 r->headers_in.user_agent->value.data, | |
1511 r->headers_in.user_agent->value.len); | |
1512 } | |
1513 | |
1514 cl = ngx_alloc_chain_link(r->pool); | |
1515 if (cl == NULL) { | |
1516 return NULL; | |
1517 } | |
1518 | |
1519 cl->buf = b; | |
1520 cl->next = NULL; | |
1521 | |
1522 n = b->last - b->pos; | |
1523 | |
1524 len = ngx_http_v3_encode_varlen_int(NULL, NGX_HTTP_V3_FRAME_PUSH_PROMISE) | |
1525 + ngx_http_v3_encode_varlen_int(NULL, n); | |
1526 | |
1527 b = ngx_create_temp_buf(r->pool, len); | |
1528 if (b == NULL) { | |
1529 return NULL; | |
1530 } | |
1531 | |
1532 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, | |
1533 NGX_HTTP_V3_FRAME_PUSH_PROMISE); | |
1534 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n); | |
1535 | |
1536 hl = ngx_alloc_chain_link(r->pool); | |
1537 if (hl == NULL) { | |
1538 return NULL; | |
1539 } | |
1540 | |
1541 hl->buf = b; | |
1542 hl->next = cl; | |
1543 | |
1544 return hl; | |
1545 } |