Mercurial > hg > nginx-quic
annotate src/http/v3/ngx_http_v3_request.c @ 7728:66f59c67adf4 quic
Skip unknown transport parameters.
author | Vladimir Homutov <vl@nginx.com> |
---|---|
date | Mon, 23 Mar 2020 12:57:24 +0300 |
parents | 69365c7bb07f |
children | 4feae8bc0ca9 |
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 | |
244 ngx_chain_t * | |
245 ngx_http_v3_create_header(ngx_http_request_t *r) | |
246 { | |
247 u_char *p; | |
7719
69365c7bb07f
Removed unused variable.
Roman Arutyunyan <arut@nginx.com>
parents:
7704
diff
changeset
|
248 size_t len, n; |
7681 | 249 ngx_buf_t *b; |
250 ngx_uint_t i, j; | |
251 ngx_chain_t *hl, *cl, *bl; | |
252 ngx_list_part_t *part; | |
253 ngx_table_elt_t *header; | |
254 ngx_connection_t *c; | |
255 ngx_http_core_loc_conf_t *clcf; | |
256 | |
257 c = r->connection; | |
258 | |
259 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 create header"); | |
260 | |
261 /* XXX support chunked body in the chunked filter */ | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
262 if (!r->header_only && r->headers_out.content_length_n == -1) { |
7681 | 263 return NULL; |
264 } | |
265 | |
266 len = 0; | |
267 | |
268 if (r->headers_out.status == NGX_HTTP_OK) { | |
269 len += ngx_http_v3_encode_prefix_int(NULL, 25, 6); | |
270 | |
271 } else { | |
272 len += 3 + ngx_http_v3_encode_prefix_int(NULL, 25, 4) | |
273 + ngx_http_v3_encode_prefix_int(NULL, 3, 7); | |
274 } | |
275 | |
276 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
277 | |
278 if (r->headers_out.server == NULL) { | |
279 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
280 n = sizeof(NGINX_VER) - 1; | |
281 | |
282 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
283 n = sizeof(NGINX_VER_BUILD) - 1; | |
284 | |
285 } else { | |
286 n = sizeof("nginx") - 1; | |
287 } | |
288 | |
289 len += ngx_http_v3_encode_prefix_int(NULL, 92, 4) | |
290 + ngx_http_v3_encode_prefix_int(NULL, n, 7) + n; | |
291 } | |
292 | |
293 if (r->headers_out.date == NULL) { | |
294 len += ngx_http_v3_encode_prefix_int(NULL, 6, 4) | |
295 + ngx_http_v3_encode_prefix_int(NULL, ngx_cached_http_time.len, | |
296 7) | |
297 + ngx_cached_http_time.len; | |
298 } | |
299 | |
300 if (r->headers_out.content_type.len) { | |
301 n = r->headers_out.content_type.len; | |
302 | |
303 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
304 && r->headers_out.charset.len) | |
305 { | |
306 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
307 } | |
308 | |
309 len += ngx_http_v3_encode_prefix_int(NULL, 53, 4) | |
310 + ngx_http_v3_encode_prefix_int(NULL, n, 7) + n; | |
311 } | |
312 | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
313 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
|
314 len += ngx_http_v3_encode_prefix_int(NULL, 4, 4) + 1 + NGX_OFF_T_LEN; |
7681 | 315 |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
316 } 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
|
317 len += ngx_http_v3_encode_prefix_int(NULL, 4, 6); |
7681 | 318 } |
319 | |
320 if (r->headers_out.last_modified == NULL | |
321 && r->headers_out.last_modified_time != -1) | |
322 { | |
323 len += ngx_http_v3_encode_prefix_int(NULL, 10, 4) + 1 | |
324 + sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT"); | |
325 } | |
326 | |
327 /* XXX location */ | |
328 | |
329 #if (NGX_HTTP_GZIP) | |
330 if (r->gzip_vary) { | |
331 if (clcf->gzip_vary) { | |
332 /* Vary: Accept-Encoding */ | |
333 len += ngx_http_v3_encode_prefix_int(NULL, 59, 6); | |
334 | |
335 } else { | |
336 r->gzip_vary = 0; | |
337 } | |
338 } | |
339 #endif | |
340 | |
341 part = &r->headers_out.headers.part; | |
342 header = part->elts; | |
343 | |
344 for (i = 0; /* void */; i++) { | |
345 | |
346 if (i >= part->nelts) { | |
347 if (part->next == NULL) { | |
348 break; | |
349 } | |
350 | |
351 part = part->next; | |
352 header = part->elts; | |
353 i = 0; | |
354 } | |
355 | |
356 if (header[i].hash == 0) { | |
357 continue; | |
358 } | |
359 | |
360 len += ngx_http_v3_encode_prefix_int(NULL, header[i].key.len, 3) | |
361 + header[i].key.len | |
362 + ngx_http_v3_encode_prefix_int(NULL, header[i].value.len, 7 ) | |
363 + header[i].value.len; | |
364 } | |
365 | |
366 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 header len:%uz", len); | |
367 | |
368 b = ngx_create_temp_buf(r->pool, len); | |
369 if (b == NULL) { | |
370 return NULL; | |
371 } | |
372 | |
373 *b->last++ = 0; | |
374 *b->last++ = 0; | |
375 | |
376 if (r->headers_out.status == NGX_HTTP_OK) { | |
377 /* :status: 200 */ | |
378 *b->last = 0xc0; | |
379 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 6); | |
380 | |
381 } else { | |
382 /* :status: 200 */ | |
383 *b->last = 0x70; | |
384 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 4); | |
385 *b->last = 0; | |
386 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
|
387 b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); |
7681 | 388 } |
389 | |
390 if (r->headers_out.server == NULL) { | |
391 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
392 p = (u_char *) NGINX_VER; | |
393 n = sizeof(NGINX_VER) - 1; | |
394 | |
395 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
396 p = (u_char *) NGINX_VER_BUILD; | |
397 n = sizeof(NGINX_VER_BUILD) - 1; | |
398 | |
399 } else { | |
400 p = (u_char *) "nginx"; | |
401 n = sizeof("nginx") - 1; | |
402 } | |
403 | |
404 /* server */ | |
405 *b->last = 0x70; | |
406 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 92, 4); | |
407 *b->last = 0; | |
408 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, n, 7); | |
409 b->last = ngx_cpymem(b->last, p, n); | |
410 } | |
411 | |
412 if (r->headers_out.date == NULL) { | |
413 /* date */ | |
414 *b->last = 0x70; | |
415 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 6, 4); | |
416 *b->last = 0; | |
417 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
418 ngx_cached_http_time.len, 7); | |
419 b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, | |
420 ngx_cached_http_time.len); | |
421 } | |
422 | |
423 if (r->headers_out.content_type.len) { | |
424 n = r->headers_out.content_type.len; | |
425 | |
426 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
427 && r->headers_out.charset.len) | |
428 { | |
429 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
430 } | |
431 | |
432 /* content-type: text/plain */ | |
433 *b->last = 0x70; | |
434 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 53, 4); | |
435 *b->last = 0; | |
436 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, n, 7); | |
437 | |
438 p = b->last; | |
439 b->last = ngx_copy(b->last, r->headers_out.content_type.data, | |
440 r->headers_out.content_type.len); | |
441 | |
442 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
443 && r->headers_out.charset.len) | |
444 { | |
445 b->last = ngx_cpymem(b->last, "; charset=", | |
446 sizeof("; charset=") - 1); | |
447 b->last = ngx_copy(b->last, r->headers_out.charset.data, | |
448 r->headers_out.charset.len); | |
449 | |
450 /* update r->headers_out.content_type for possible logging */ | |
451 | |
452 r->headers_out.content_type.len = b->last - p; | |
453 r->headers_out.content_type.data = p; | |
454 } | |
455 } | |
456 | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
457 if (r->headers_out.content_length_n > 0) { |
7681 | 458 /* content-length: 0 */ |
459 *b->last = 0x70; | |
460 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 4, 4); | |
461 p = b->last++; | |
462 b->last = ngx_sprintf(b->last, "%O", r->headers_out.content_length_n); | |
463 *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
|
464 |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
465 } 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
|
466 /* content-length: 0 */ |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
467 *b->last = 0xc0; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
468 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 4, 6); |
7681 | 469 } |
470 | |
471 if (r->headers_out.last_modified == NULL | |
472 && r->headers_out.last_modified_time != -1) | |
473 { | |
474 /* last-modified */ | |
475 *b->last = 0x70; | |
476 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 10, 4); | |
477 p = b->last++; | |
478 b->last = ngx_http_time(b->last, r->headers_out.last_modified_time); | |
479 *p = b->last - p - 1; | |
480 } | |
481 | |
482 #if (NGX_HTTP_GZIP) | |
483 if (r->gzip_vary) { | |
484 /* vary: accept-encoding */ | |
485 *b->last = 0xc0; | |
486 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 59, 6); | |
487 } | |
488 #endif | |
489 | |
490 part = &r->headers_out.headers.part; | |
491 header = part->elts; | |
492 | |
493 for (i = 0; /* void */; i++) { | |
494 | |
495 if (i >= part->nelts) { | |
496 if (part->next == NULL) { | |
497 break; | |
498 } | |
499 | |
500 part = part->next; | |
501 header = part->elts; | |
502 i = 0; | |
503 } | |
504 | |
505 if (header[i].hash == 0) { | |
506 continue; | |
507 } | |
508 | |
509 *b->last = 0x30; | |
510 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
511 header[i].key.len, | |
512 3); | |
513 for (j = 0; j < header[i].key.len; j++) { | |
514 *b->last++ = ngx_tolower(header[i].key.data[j]); | |
515 } | |
516 | |
517 *b->last = 0; | |
518 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
519 header[i].value.len, | |
520 7); | |
521 b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); | |
522 } | |
523 | |
7704
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
524 if (r->header_only) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
525 b->last_buf = 1; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
526 } |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
7699
diff
changeset
|
527 |
7681 | 528 cl = ngx_alloc_chain_link(c->pool); |
529 if (cl == NULL) { | |
530 return NULL; | |
531 } | |
532 | |
533 cl->buf = b; | |
534 cl->next = NULL; | |
535 | |
536 n = b->last - b->pos; | |
537 | |
538 len = 1 + ngx_http_v3_encode_varlen_int(NULL, n); | |
539 | |
540 b = ngx_create_temp_buf(c->pool, len); | |
541 if (b == NULL) { | |
542 return NULL; | |
543 } | |
544 | |
545 *b->last++ = NGX_HTTP_V3_FRAME_HEADERS; | |
546 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n); | |
547 | |
548 hl = ngx_alloc_chain_link(c->pool); | |
549 if (hl == NULL) { | |
550 return NULL; | |
551 } | |
552 | |
553 hl->buf = b; | |
554 hl->next = cl; | |
555 | |
556 if (r->headers_out.content_length_n >= 0) { | |
557 len = 1 + ngx_http_v3_encode_varlen_int(NULL, | |
558 r->headers_out.content_length_n); | |
559 | |
560 b = ngx_create_temp_buf(c->pool, len); | |
561 if (b == NULL) { | |
562 NULL; | |
563 } | |
564 | |
565 *b->last++ = NGX_HTTP_V3_FRAME_DATA; | |
566 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, | |
567 r->headers_out.content_length_n); | |
568 | |
569 bl = ngx_alloc_chain_link(c->pool); | |
570 if (bl == NULL) { | |
571 return NULL; | |
572 } | |
573 | |
574 bl->buf = b; | |
575 bl->next = NULL; | |
576 cl->next = bl; | |
577 } | |
578 | |
579 return hl; | |
580 } |