Mercurial > hg > nginx-quic
annotate src/http/v3/ngx_http_v3_request.c @ 7858:6e100d8c138a quic
Preserve original DCID and unbreak parsing 0-RTT packets.
As per QUIC transport, the first flight of 0-RTT packets obviously uses same
Destination and Source Connection ID values as the client's first Initial.
The fix is to match 0-RTT against original DCID after it has been switched.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Tue, 12 May 2020 18:18:58 +0300 |
parents | 7bd334b8d91a |
children | df18ae7161b8 |
rev | line source |
---|---|
7681 | 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 | |
13 static ngx_int_t ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, | |
14 ngx_str_t *name, ngx_str_t *value); | |
15 | |
16 | |
17 struct { | |
18 ngx_str_t name; | |
19 ngx_uint_t method; | |
20 } ngx_http_v3_methods[] = { | |
21 | |
22 { ngx_string("GET"), NGX_HTTP_GET }, | |
23 { ngx_string("POST"), NGX_HTTP_POST }, | |
24 { ngx_string("HEAD"), NGX_HTTP_HEAD }, | |
25 { ngx_string("OPTIONS"), NGX_HTTP_OPTIONS }, | |
26 { ngx_string("PROPFIND"), NGX_HTTP_PROPFIND }, | |
27 { ngx_string("PUT"), NGX_HTTP_PUT }, | |
28 { ngx_string("MKCOL"), NGX_HTTP_MKCOL }, | |
29 { ngx_string("DELETE"), NGX_HTTP_DELETE }, | |
30 { ngx_string("COPY"), NGX_HTTP_COPY }, | |
31 { ngx_string("MOVE"), NGX_HTTP_MOVE }, | |
32 { ngx_string("PROPPATCH"), NGX_HTTP_PROPPATCH }, | |
33 { ngx_string("LOCK"), NGX_HTTP_LOCK }, | |
34 { ngx_string("UNLOCK"), NGX_HTTP_UNLOCK }, | |
35 { ngx_string("PATCH"), NGX_HTTP_PATCH }, | |
36 { ngx_string("TRACE"), NGX_HTTP_TRACE } | |
37 }; | |
38 | |
39 | |
40 ngx_int_t | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
41 ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b) |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
42 { |
7699
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
43 size_t n; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
44 u_char *p; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
45 ngx_int_t rc; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
46 ngx_str_t *name, *value; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
47 ngx_connection_t *c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
48 ngx_http_v3_parse_headers_t *st; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
49 enum { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
50 sw_start = 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
51 sw_prev, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
52 sw_headers, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
53 sw_last, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
54 sw_done |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
55 }; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
56 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
57 c = r->connection; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
58 st = r->h3_parse; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
59 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
60 if (st == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
61 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
62 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
63 st = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_parse_headers_t)); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
64 if (st == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
65 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
66 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
67 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
68 r->h3_parse = st; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
69 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
70 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
71 switch (r->state) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
72 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
73 case sw_prev: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
74 r->state = sw_headers; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
75 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
76 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
77 case sw_done: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
78 goto done; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
79 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
80 case sw_last: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
81 r->state = sw_done; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
82 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
83 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
84 default: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
85 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
86 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
87 |
7696
31f7c697b6d9
Fixed pointer increment while parsing HTTP/3 header.
Roman Arutyunyan <arut@nginx.com>
parents:
7692
diff
changeset
|
88 while (b->pos < b->last) { |
31f7c697b6d9
Fixed pointer increment while parsing HTTP/3 header.
Roman Arutyunyan <arut@nginx.com>
parents:
7692
diff
changeset
|
89 rc = ngx_http_v3_parse_headers(c, st, *b->pos++); |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
90 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
91 if (rc == NGX_ERROR) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
92 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
93 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
94 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
95 if (rc == NGX_AGAIN) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
96 continue; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
97 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
98 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
99 name = &st->header_rep.header.name; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
100 value = &st->header_rep.header.value; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
101 |
7699
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
102 if (r->state == sw_start) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
103 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
104 if (ngx_http_v3_process_pseudo_header(r, name, value) == NGX_OK) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
105 if (rc == NGX_OK) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
106 continue; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
107 } |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
108 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
109 r->state = sw_done; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
110 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
111 } else if (rc == NGX_OK) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
112 r->state = sw_prev; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
113 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
114 } else { |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
115 r->state = sw_last; |
7699
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
116 } |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
117 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
118 n = (r->method_end - r->method_start) + 1 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
119 + (r->uri_end - r->uri_start) + 1 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
120 + sizeof("HTTP/3") - 1; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
121 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
122 p = ngx_pnalloc(c->pool, n); |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
123 if (p == NULL) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
124 goto failed; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
125 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
126 |
7699
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
127 r->request_start = p; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
128 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
129 p = ngx_cpymem(p, r->method_start, r->method_end - r->method_start); |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
130 *p++ = ' '; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
131 p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start); |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
132 *p++ = ' '; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
133 p = ngx_cpymem(p, "HTTP/3", sizeof("HTTP/3") - 1); |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
134 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
135 r->request_end = p; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
136 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
137 } else if (rc == NGX_DONE) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
138 r->state = sw_done; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
139 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
140 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
141 r->header_name_start = name->data; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
142 r->header_name_end = name->data + name->len; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
143 r->header_start = value->data; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
144 r->header_end = value->data + value->len; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
145 r->header_hash = ngx_hash_key(name->data, name->len); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
146 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
147 /* XXX r->lowcase_index = i; */ |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
148 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
149 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
150 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
151 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
152 return NGX_AGAIN; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
153 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
154 failed: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
155 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
156 return r->state == sw_start ? NGX_HTTP_PARSE_INVALID_REQUEST |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
157 : NGX_HTTP_PARSE_INVALID_HEADER; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
158 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
159 done: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
160 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
161 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 parse header done"); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
162 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
163 return NGX_HTTP_PARSE_HEADER_DONE; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
164 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
165 |
7681 | 166 |
167 static ngx_int_t | |
168 ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name, | |
169 ngx_str_t *value) | |
170 { | |
171 ngx_uint_t i; | |
172 ngx_connection_t *c; | |
173 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
174 if (name->len == 0 || name->data[0] != ':') { |
7699
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7696
diff
changeset
|
175 return NGX_DONE; |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
176 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
177 |
7681 | 178 c = r->connection; |
179 | |
180 if (name->len == 7 && ngx_strncmp(name->data, ":method", 7) == 0) { | |
181 r->method_start = value->data; | |
182 r->method_end = value->data + value->len; | |
183 | |
184 for (i = 0; i < sizeof(ngx_http_v3_methods) | |
185 / sizeof(ngx_http_v3_methods[0]); i++) | |
186 { | |
187 if (value->len == ngx_http_v3_methods[i].name.len | |
188 && ngx_strncmp(value->data, ngx_http_v3_methods[i].name.data, | |
189 value->len) == 0) | |
190 { | |
191 r->method = ngx_http_v3_methods[i].method; | |
192 break; | |
193 } | |
194 } | |
195 | |
196 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
197 "http3 method \"%V\" %ui", value, r->method); | |
198 return NGX_OK; | |
199 } | |
200 | |
201 if (name->len == 5 && ngx_strncmp(name->data, ":path", 5) == 0) { | |
202 r->uri_start = value->data; | |
203 r->uri_end = value->data + value->len; | |
204 | |
205 if (ngx_http_parse_uri(r) != NGX_OK) { | |
206 ngx_log_error(NGX_LOG_INFO, c->log, 0, | |
207 "client sent invalid :path header: \"%V\"", value); | |
208 return NGX_ERROR; | |
209 } | |
210 | |
211 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
212 "http3 path \"%V\"", value); | |
213 | |
214 return NGX_OK; | |
215 } | |
216 | |
217 if (name->len == 7 && ngx_strncmp(name->data, ":scheme", 7) == 0) { | |
218 r->schema_start = value->data; | |
219 r->schema_end = value->data + value->len; | |
220 | |
221 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
222 "http3 schema \"%V\"", value); | |
223 | |
224 return NGX_OK; | |
225 } | |
226 | |
227 if (name->len == 10 && ngx_strncmp(name->data, ":authority", 10) == 0) { | |
228 r->host_start = value->data; | |
229 r->host_end = value->data + value->len; | |
230 | |
231 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, | |
232 "http3 authority \"%V\"", value); | |
233 | |
234 return NGX_OK; | |
235 } | |
236 | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
237 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
238 "http3 unknown pseudo header \"%V\" \"%V\"", name, value); |
7681 | 239 |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
240 return NGX_OK; |
7681 | 241 } |
242 | |
243 | |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
244 ngx_int_t |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
245 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:
7758
diff
changeset
|
246 ngx_http_chunked_t *ctx) |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
247 { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
248 ngx_int_t rc; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
249 ngx_connection_t *c; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
250 ngx_http_v3_parse_data_t *st; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
251 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
252 c = r->connection; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
253 st = ctx->h3_parse; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
254 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
255 if (st == NULL) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
256 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
257 "http3 parse request body"); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
258 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
259 st = ngx_pcalloc(c->pool, sizeof(ngx_http_v3_parse_data_t)); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
260 if (st == NULL) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
261 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
262 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
263 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
264 r->h3_parse = st; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
265 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
266 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
267 if (ctx->size) { |
7795
7bd334b8d91a
HTTP/3: fixed reading request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7761
diff
changeset
|
268 ctx->length = ctx->size + 1; |
7bd334b8d91a
HTTP/3: fixed reading request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7761
diff
changeset
|
269 return (b->pos == b->last) ? NGX_AGAIN : NGX_OK; |
7761
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
270 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
271 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
272 while (b->pos < b->last) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
273 rc = ngx_http_v3_parse_data(c, st, *b->pos++); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
274 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
275 if (rc == NGX_ERROR) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
276 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
277 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
278 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
279 if (rc == NGX_AGAIN) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
280 continue; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
281 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
282 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
283 /* rc == NGX_DONE */ |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
284 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
285 ctx->size = st->length; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
286 return NGX_OK; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
287 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
288 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
289 if (!b->last_buf) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
290 ctx->length = 1; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
291 return NGX_AGAIN; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
292 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
293 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
294 if (st->state) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
295 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
296 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
297 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
298 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:
7758
diff
changeset
|
299 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
300 return NGX_DONE; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
301 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
302 failed: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
303 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
304 return NGX_ERROR; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
305 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
306 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
7758
diff
changeset
|
307 |
7681 | 308 ngx_chain_t * |
309 ngx_http_v3_create_header(ngx_http_request_t *r) | |
310 { | |
311 u_char *p; | |
7719
69365c7bb07f
Removed unused variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7704
diff
changeset
|
312 size_t len, n; |
7681 | 313 ngx_buf_t *b; |
314 ngx_uint_t i, j; | |
315 ngx_chain_t *hl, *cl, *bl; | |
316 ngx_list_part_t *part; | |
317 ngx_table_elt_t *header; | |
318 ngx_connection_t *c; | |
319 ngx_http_core_loc_conf_t *clcf; | |
320 | |
321 c = r->connection; | |
322 | |
323 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 create header"); | |
324 | |
7757 | 325 len = 2; |
7681 | 326 |
327 if (r->headers_out.status == NGX_HTTP_OK) { | |
328 len += ngx_http_v3_encode_prefix_int(NULL, 25, 6); | |
329 | |
330 } else { | |
331 len += 3 + ngx_http_v3_encode_prefix_int(NULL, 25, 4) | |
332 + ngx_http_v3_encode_prefix_int(NULL, 3, 7); | |
333 } | |
334 | |
335 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
336 | |
337 if (r->headers_out.server == NULL) { | |
338 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
339 n = sizeof(NGINX_VER) - 1; | |
340 | |
341 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
342 n = sizeof(NGINX_VER_BUILD) - 1; | |
343 | |
344 } else { | |
345 n = sizeof("nginx") - 1; | |
346 } | |
347 | |
348 len += ngx_http_v3_encode_prefix_int(NULL, 92, 4) | |
349 + ngx_http_v3_encode_prefix_int(NULL, n, 7) + n; | |
350 } | |
351 | |
352 if (r->headers_out.date == NULL) { | |
353 len += ngx_http_v3_encode_prefix_int(NULL, 6, 4) | |
354 + ngx_http_v3_encode_prefix_int(NULL, ngx_cached_http_time.len, | |
355 7) | |
356 + ngx_cached_http_time.len; | |
357 } | |
358 | |
359 if (r->headers_out.content_type.len) { | |
360 n = r->headers_out.content_type.len; | |
361 | |
362 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
363 && r->headers_out.charset.len) | |
364 { | |
365 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
366 } | |
367 | |
368 len += ngx_http_v3_encode_prefix_int(NULL, 53, 4) | |
369 + ngx_http_v3_encode_prefix_int(NULL, n, 7) + n; | |
370 } | |
371 | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
372 if (r->headers_out.content_length_n > 0) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
373 len += ngx_http_v3_encode_prefix_int(NULL, 4, 4) + 1 + NGX_OFF_T_LEN; |
7681 | 374 |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
375 } else if (r->headers_out.content_length_n == 0) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
376 len += ngx_http_v3_encode_prefix_int(NULL, 4, 6); |
7681 | 377 } |
378 | |
379 if (r->headers_out.last_modified == NULL | |
380 && r->headers_out.last_modified_time != -1) | |
381 { | |
382 len += ngx_http_v3_encode_prefix_int(NULL, 10, 4) + 1 | |
383 + sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT"); | |
384 } | |
385 | |
386 /* XXX location */ | |
387 | |
388 #if (NGX_HTTP_GZIP) | |
389 if (r->gzip_vary) { | |
390 if (clcf->gzip_vary) { | |
391 /* Vary: Accept-Encoding */ | |
392 len += ngx_http_v3_encode_prefix_int(NULL, 59, 6); | |
393 | |
394 } else { | |
395 r->gzip_vary = 0; | |
396 } | |
397 } | |
398 #endif | |
399 | |
400 part = &r->headers_out.headers.part; | |
401 header = part->elts; | |
402 | |
403 for (i = 0; /* void */; i++) { | |
404 | |
405 if (i >= part->nelts) { | |
406 if (part->next == NULL) { | |
407 break; | |
408 } | |
409 | |
410 part = part->next; | |
411 header = part->elts; | |
412 i = 0; | |
413 } | |
414 | |
415 if (header[i].hash == 0) { | |
416 continue; | |
417 } | |
418 | |
419 len += ngx_http_v3_encode_prefix_int(NULL, header[i].key.len, 3) | |
420 + header[i].key.len | |
421 + ngx_http_v3_encode_prefix_int(NULL, header[i].value.len, 7 ) | |
422 + header[i].value.len; | |
423 } | |
424 | |
425 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 header len:%uz", len); | |
426 | |
427 b = ngx_create_temp_buf(r->pool, len); | |
428 if (b == NULL) { | |
429 return NULL; | |
430 } | |
431 | |
432 *b->last++ = 0; | |
433 *b->last++ = 0; | |
434 | |
435 if (r->headers_out.status == NGX_HTTP_OK) { | |
436 /* :status: 200 */ | |
437 *b->last = 0xc0; | |
438 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 6); | |
439 | |
440 } else { | |
441 /* :status: 200 */ | |
442 *b->last = 0x70; | |
443 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 4); | |
444 *b->last = 0; | |
445 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 3, 7); | |
7692
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
7685
diff
changeset
|
446 b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); |
7681 | 447 } |
448 | |
449 if (r->headers_out.server == NULL) { | |
450 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
451 p = (u_char *) NGINX_VER; | |
452 n = sizeof(NGINX_VER) - 1; | |
453 | |
454 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
455 p = (u_char *) NGINX_VER_BUILD; | |
456 n = sizeof(NGINX_VER_BUILD) - 1; | |
457 | |
458 } else { | |
459 p = (u_char *) "nginx"; | |
460 n = sizeof("nginx") - 1; | |
461 } | |
462 | |
463 /* server */ | |
464 *b->last = 0x70; | |
465 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 92, 4); | |
466 *b->last = 0; | |
467 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, n, 7); | |
468 b->last = ngx_cpymem(b->last, p, n); | |
469 } | |
470 | |
471 if (r->headers_out.date == NULL) { | |
472 /* date */ | |
473 *b->last = 0x70; | |
474 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 6, 4); | |
475 *b->last = 0; | |
476 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
477 ngx_cached_http_time.len, 7); | |
478 b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, | |
479 ngx_cached_http_time.len); | |
480 } | |
481 | |
482 if (r->headers_out.content_type.len) { | |
483 n = r->headers_out.content_type.len; | |
484 | |
485 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
486 && r->headers_out.charset.len) | |
487 { | |
488 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
489 } | |
490 | |
491 /* content-type: text/plain */ | |
492 *b->last = 0x70; | |
493 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 53, 4); | |
494 *b->last = 0; | |
495 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, n, 7); | |
496 | |
497 p = b->last; | |
498 b->last = ngx_copy(b->last, r->headers_out.content_type.data, | |
499 r->headers_out.content_type.len); | |
500 | |
501 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
502 && r->headers_out.charset.len) | |
503 { | |
504 b->last = ngx_cpymem(b->last, "; charset=", | |
505 sizeof("; charset=") - 1); | |
506 b->last = ngx_copy(b->last, r->headers_out.charset.data, | |
507 r->headers_out.charset.len); | |
508 | |
509 /* update r->headers_out.content_type for possible logging */ | |
510 | |
511 r->headers_out.content_type.len = b->last - p; | |
512 r->headers_out.content_type.data = p; | |
513 } | |
514 } | |
515 | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
516 if (r->headers_out.content_length_n > 0) { |
7681 | 517 /* content-length: 0 */ |
518 *b->last = 0x70; | |
519 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 4, 4); | |
520 p = b->last++; | |
521 b->last = ngx_sprintf(b->last, "%O", r->headers_out.content_length_n); | |
522 *p = b->last - p - 1; | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
523 |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
524 } else if (r->headers_out.content_length_n == 0) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
525 /* content-length: 0 */ |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
526 *b->last = 0xc0; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
527 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 4, 6); |
7681 | 528 } |
529 | |
530 if (r->headers_out.last_modified == NULL | |
531 && r->headers_out.last_modified_time != -1) | |
532 { | |
533 /* last-modified */ | |
534 *b->last = 0x70; | |
535 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 10, 4); | |
536 p = b->last++; | |
537 b->last = ngx_http_time(b->last, r->headers_out.last_modified_time); | |
538 *p = b->last - p - 1; | |
539 } | |
540 | |
541 #if (NGX_HTTP_GZIP) | |
542 if (r->gzip_vary) { | |
543 /* vary: accept-encoding */ | |
544 *b->last = 0xc0; | |
545 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 59, 6); | |
546 } | |
547 #endif | |
548 | |
549 part = &r->headers_out.headers.part; | |
550 header = part->elts; | |
551 | |
552 for (i = 0; /* void */; i++) { | |
553 | |
554 if (i >= part->nelts) { | |
555 if (part->next == NULL) { | |
556 break; | |
557 } | |
558 | |
559 part = part->next; | |
560 header = part->elts; | |
561 i = 0; | |
562 } | |
563 | |
564 if (header[i].hash == 0) { | |
565 continue; | |
566 } | |
567 | |
568 *b->last = 0x30; | |
569 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
570 header[i].key.len, | |
571 3); | |
572 for (j = 0; j < header[i].key.len; j++) { | |
573 *b->last++ = ngx_tolower(header[i].key.data[j]); | |
574 } | |
575 | |
576 *b->last = 0; | |
577 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
578 header[i].value.len, | |
579 7); | |
580 b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); | |
581 } | |
582 | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
583 if (r->header_only) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
584 b->last_buf = 1; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
585 } |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
586 |
7681 | 587 cl = ngx_alloc_chain_link(c->pool); |
588 if (cl == NULL) { | |
589 return NULL; | |
590 } | |
591 | |
592 cl->buf = b; | |
593 cl->next = NULL; | |
594 | |
595 n = b->last - b->pos; | |
596 | |
597 len = 1 + ngx_http_v3_encode_varlen_int(NULL, n); | |
598 | |
599 b = ngx_create_temp_buf(c->pool, len); | |
600 if (b == NULL) { | |
601 return NULL; | |
602 } | |
603 | |
604 *b->last++ = NGX_HTTP_V3_FRAME_HEADERS; | |
605 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n); | |
606 | |
607 hl = ngx_alloc_chain_link(c->pool); | |
608 if (hl == NULL) { | |
609 return NULL; | |
610 } | |
611 | |
612 hl->buf = b; | |
613 hl->next = cl; | |
614 | |
615 if (r->headers_out.content_length_n >= 0) { | |
616 len = 1 + ngx_http_v3_encode_varlen_int(NULL, | |
617 r->headers_out.content_length_n); | |
618 | |
619 b = ngx_create_temp_buf(c->pool, len); | |
620 if (b == NULL) { | |
621 NULL; | |
622 } | |
623 | |
624 *b->last++ = NGX_HTTP_V3_FRAME_DATA; | |
625 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, | |
626 r->headers_out.content_length_n); | |
627 | |
628 bl = ngx_alloc_chain_link(c->pool); | |
629 if (bl == NULL) { | |
630 return NULL; | |
631 } | |
632 | |
633 bl->buf = b; | |
634 bl->next = NULL; | |
635 cl->next = bl; | |
636 } | |
637 | |
638 return hl; | |
639 } | |
7758
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
640 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
641 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
642 ngx_chain_t * |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
643 ngx_http_v3_create_trailers(ngx_http_request_t *r) |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
644 { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
645 ngx_buf_t *b; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
646 ngx_chain_t *cl; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
647 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
648 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
649 "http3 create trailers"); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
650 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
651 /* XXX */ |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
652 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
653 b = ngx_calloc_buf(r->pool); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
654 if (b == NULL) { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
655 return NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
656 } |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
657 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
658 b->last_buf = 1; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
659 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
660 cl = ngx_alloc_chain_link(r->pool); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
661 if (cl == NULL) { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
662 return NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
663 } |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
664 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
665 cl->buf = b; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
666 cl->next = NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
667 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
668 return cl; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7757
diff
changeset
|
669 } |