Mercurial > hg > nginx
annotate src/http/v3/ngx_http_v3_request.c @ 8295:5649079a41f4 quic
Parsing HTTP/3 request body.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 27 Mar 2020 19:41:06 +0300 |
parents | 46e3542d51b3 |
children | 7bd334b8d91a |
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 | |
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 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
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:
8219
diff
changeset
|
42 { |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
43 size_t n; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
44 u_char *p; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
45 ngx_int_t rc; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
46 ngx_str_t *name, *value; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
47 ngx_connection_t *c; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
48 ngx_http_v3_parse_headers_t *st; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
49 enum { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
50 sw_start = 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
51 sw_prev, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
52 sw_headers, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
53 sw_last, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
54 sw_done |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
55 }; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
56 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
57 c = r->connection; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
58 st = r->h3_parse; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
59 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
60 if (st == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
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:
8219
diff
changeset
|
62 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
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:
8219
diff
changeset
|
64 if (st == NULL) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
65 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
66 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
67 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
68 r->h3_parse = st; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
69 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
70 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
71 switch (r->state) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
72 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
73 case sw_prev: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
74 r->state = sw_headers; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
75 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
76 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
77 case sw_done: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
78 goto done; |
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 case sw_last: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
81 r->state = sw_done; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
82 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
83 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
84 default: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
85 break; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
86 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
87 |
8230
31f7c697b6d9
Fixed pointer increment while parsing HTTP/3 header.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
88 while (b->pos < b->last) { |
31f7c697b6d9
Fixed pointer increment while parsing HTTP/3 header.
Roman Arutyunyan <arut@nginx.com>
parents:
8226
diff
changeset
|
89 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
|
90 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
91 if (rc == NGX_ERROR) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
92 goto failed; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
93 } |
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 if (rc == NGX_AGAIN) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
96 continue; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
97 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
98 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
99 name = &st->header_rep.header.name; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
100 value = &st->header_rep.header.value; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
101 |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
102 if (r->state == sw_start) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
103 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
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:
8230
diff
changeset
|
105 if (rc == NGX_OK) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
106 continue; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
107 } |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
108 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
109 r->state = sw_done; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
110 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
111 } else if (rc == NGX_OK) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
112 r->state = sw_prev; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
113 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
114 } else { |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
115 r->state = sw_last; |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
116 } |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
117 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
118 n = (r->method_end - r->method_start) + 1 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
119 + (r->uri_end - r->uri_start) + 1 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
120 + sizeof("HTTP/3") - 1; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
121 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
122 p = ngx_pnalloc(c->pool, n); |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
123 if (p == NULL) { |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
124 goto failed; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
125 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
126 |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
127 r->request_start = p; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
128 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
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:
8230
diff
changeset
|
130 *p++ = ' '; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
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:
8230
diff
changeset
|
132 *p++ = ' '; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
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:
8230
diff
changeset
|
134 |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
135 r->request_end = p; |
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
136 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
137 } else if (rc == NGX_DONE) { |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
138 r->state = sw_done; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
139 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
140 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
141 r->header_name_start = name->data; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
142 r->header_name_end = name->data + name->len; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
143 r->header_start = value->data; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
144 r->header_end = value->data + value->len; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
145 r->header_hash = ngx_hash_key(name->data, name->len); |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
146 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
147 /* XXX r->lowcase_index = i; */ |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
148 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
149 return NGX_OK; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
150 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
151 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
152 return NGX_AGAIN; |
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 failed: |
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 return r->state == sw_start ? NGX_HTTP_PARSE_INVALID_REQUEST |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
157 : NGX_HTTP_PARSE_INVALID_HEADER; |
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 done: |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
160 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
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:
8219
diff
changeset
|
162 |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
163 return NGX_HTTP_PARSE_HEADER_DONE; |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
164 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
165 |
8215 | 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 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
174 if (name->len == 0 || name->data[0] != ':') { |
8233
1e45c02f6376
HTTP/3 $request_line variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8230
diff
changeset
|
175 return NGX_DONE; |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
176 } |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
177 |
8215 | 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 | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
237 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, |
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
238 "http3 unknown pseudo header \"%V\" \"%V\"", name, value); |
8215 | 239 |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
240 return NGX_OK; |
8215 | 241 } |
242 | |
243 | |
8295
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
244 ngx_int_t |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
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:
8292
diff
changeset
|
246 ngx_http_chunked_t *ctx) |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
247 { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
248 ngx_int_t rc; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
249 ngx_connection_t *c; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
250 ngx_http_v3_parse_data_t *st; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
251 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
252 c = r->connection; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
253 st = ctx->h3_parse; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
254 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
255 if (st == NULL) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
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:
8292
diff
changeset
|
257 "http3 parse request body"); |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
258 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
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:
8292
diff
changeset
|
260 if (st == NULL) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
261 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
262 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
263 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
264 r->h3_parse = st; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
265 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
266 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
267 if (ctx->size) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
268 return NGX_OK; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
269 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
270 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
271 while (b->pos < b->last) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
272 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
|
273 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
274 if (rc == NGX_ERROR) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
275 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
276 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
277 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
278 if (rc == NGX_AGAIN) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
279 continue; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
280 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
281 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
282 /* rc == NGX_DONE */ |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
283 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
284 ctx->size = st->length; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
285 return NGX_OK; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
286 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
287 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
288 if (!b->last_buf) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
289 ctx->length = 1; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
290 return NGX_AGAIN; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
291 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
292 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
293 if (st->state) { |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
294 goto failed; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
295 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
296 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
297 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
|
298 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
299 return NGX_DONE; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
300 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
301 failed: |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
302 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
303 return NGX_ERROR; |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
304 } |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
305 |
5649079a41f4
Parsing HTTP/3 request body.
Roman Arutyunyan <arut@nginx.com>
parents:
8292
diff
changeset
|
306 |
8215 | 307 ngx_chain_t * |
308 ngx_http_v3_create_header(ngx_http_request_t *r) | |
309 { | |
310 u_char *p; | |
8253
69365c7bb07f
Removed unused variable.
Roman Arutyunyan <arut@nginx.com>
parents:
8238
diff
changeset
|
311 size_t len, n; |
8215 | 312 ngx_buf_t *b; |
313 ngx_uint_t i, j; | |
314 ngx_chain_t *hl, *cl, *bl; | |
315 ngx_list_part_t *part; | |
316 ngx_table_elt_t *header; | |
317 ngx_connection_t *c; | |
318 ngx_http_core_loc_conf_t *clcf; | |
319 | |
320 c = r->connection; | |
321 | |
322 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 create header"); | |
323 | |
8291 | 324 len = 2; |
8215 | 325 |
326 if (r->headers_out.status == NGX_HTTP_OK) { | |
327 len += ngx_http_v3_encode_prefix_int(NULL, 25, 6); | |
328 | |
329 } else { | |
330 len += 3 + ngx_http_v3_encode_prefix_int(NULL, 25, 4) | |
331 + ngx_http_v3_encode_prefix_int(NULL, 3, 7); | |
332 } | |
333 | |
334 clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); | |
335 | |
336 if (r->headers_out.server == NULL) { | |
337 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
338 n = sizeof(NGINX_VER) - 1; | |
339 | |
340 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
341 n = sizeof(NGINX_VER_BUILD) - 1; | |
342 | |
343 } else { | |
344 n = sizeof("nginx") - 1; | |
345 } | |
346 | |
347 len += ngx_http_v3_encode_prefix_int(NULL, 92, 4) | |
348 + ngx_http_v3_encode_prefix_int(NULL, n, 7) + n; | |
349 } | |
350 | |
351 if (r->headers_out.date == NULL) { | |
352 len += ngx_http_v3_encode_prefix_int(NULL, 6, 4) | |
353 + ngx_http_v3_encode_prefix_int(NULL, ngx_cached_http_time.len, | |
354 7) | |
355 + ngx_cached_http_time.len; | |
356 } | |
357 | |
358 if (r->headers_out.content_type.len) { | |
359 n = r->headers_out.content_type.len; | |
360 | |
361 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
362 && r->headers_out.charset.len) | |
363 { | |
364 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
365 } | |
366 | |
367 len += ngx_http_v3_encode_prefix_int(NULL, 53, 4) | |
368 + ngx_http_v3_encode_prefix_int(NULL, n, 7) + n; | |
369 } | |
370 | |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
371 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:
8233
diff
changeset
|
372 len += ngx_http_v3_encode_prefix_int(NULL, 4, 4) + 1 + NGX_OFF_T_LEN; |
8215 | 373 |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
374 } 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:
8233
diff
changeset
|
375 len += ngx_http_v3_encode_prefix_int(NULL, 4, 6); |
8215 | 376 } |
377 | |
378 if (r->headers_out.last_modified == NULL | |
379 && r->headers_out.last_modified_time != -1) | |
380 { | |
381 len += ngx_http_v3_encode_prefix_int(NULL, 10, 4) + 1 | |
382 + sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT"); | |
383 } | |
384 | |
385 /* XXX location */ | |
386 | |
387 #if (NGX_HTTP_GZIP) | |
388 if (r->gzip_vary) { | |
389 if (clcf->gzip_vary) { | |
390 /* Vary: Accept-Encoding */ | |
391 len += ngx_http_v3_encode_prefix_int(NULL, 59, 6); | |
392 | |
393 } else { | |
394 r->gzip_vary = 0; | |
395 } | |
396 } | |
397 #endif | |
398 | |
399 part = &r->headers_out.headers.part; | |
400 header = part->elts; | |
401 | |
402 for (i = 0; /* void */; i++) { | |
403 | |
404 if (i >= part->nelts) { | |
405 if (part->next == NULL) { | |
406 break; | |
407 } | |
408 | |
409 part = part->next; | |
410 header = part->elts; | |
411 i = 0; | |
412 } | |
413 | |
414 if (header[i].hash == 0) { | |
415 continue; | |
416 } | |
417 | |
418 len += ngx_http_v3_encode_prefix_int(NULL, header[i].key.len, 3) | |
419 + header[i].key.len | |
420 + ngx_http_v3_encode_prefix_int(NULL, header[i].value.len, 7 ) | |
421 + header[i].value.len; | |
422 } | |
423 | |
424 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http3 header len:%uz", len); | |
425 | |
426 b = ngx_create_temp_buf(r->pool, len); | |
427 if (b == NULL) { | |
428 return NULL; | |
429 } | |
430 | |
431 *b->last++ = 0; | |
432 *b->last++ = 0; | |
433 | |
434 if (r->headers_out.status == NGX_HTTP_OK) { | |
435 /* :status: 200 */ | |
436 *b->last = 0xc0; | |
437 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 6); | |
438 | |
439 } else { | |
440 /* :status: 200 */ | |
441 *b->last = 0x70; | |
442 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 25, 4); | |
443 *b->last = 0; | |
444 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 3, 7); | |
8226
268f4389130d
Refactored HTTP/3 parser.
Roman Arutyunyan <arut@nginx.com>
parents:
8219
diff
changeset
|
445 b->last = ngx_sprintf(b->last, "%03ui", r->headers_out.status); |
8215 | 446 } |
447 | |
448 if (r->headers_out.server == NULL) { | |
449 if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_ON) { | |
450 p = (u_char *) NGINX_VER; | |
451 n = sizeof(NGINX_VER) - 1; | |
452 | |
453 } else if (clcf->server_tokens == NGX_HTTP_SERVER_TOKENS_BUILD) { | |
454 p = (u_char *) NGINX_VER_BUILD; | |
455 n = sizeof(NGINX_VER_BUILD) - 1; | |
456 | |
457 } else { | |
458 p = (u_char *) "nginx"; | |
459 n = sizeof("nginx") - 1; | |
460 } | |
461 | |
462 /* server */ | |
463 *b->last = 0x70; | |
464 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 92, 4); | |
465 *b->last = 0; | |
466 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, n, 7); | |
467 b->last = ngx_cpymem(b->last, p, n); | |
468 } | |
469 | |
470 if (r->headers_out.date == NULL) { | |
471 /* date */ | |
472 *b->last = 0x70; | |
473 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 6, 4); | |
474 *b->last = 0; | |
475 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
476 ngx_cached_http_time.len, 7); | |
477 b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, | |
478 ngx_cached_http_time.len); | |
479 } | |
480 | |
481 if (r->headers_out.content_type.len) { | |
482 n = r->headers_out.content_type.len; | |
483 | |
484 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
485 && r->headers_out.charset.len) | |
486 { | |
487 n += sizeof("; charset=") - 1 + r->headers_out.charset.len; | |
488 } | |
489 | |
490 /* content-type: text/plain */ | |
491 *b->last = 0x70; | |
492 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 53, 4); | |
493 *b->last = 0; | |
494 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, n, 7); | |
495 | |
496 p = b->last; | |
497 b->last = ngx_copy(b->last, r->headers_out.content_type.data, | |
498 r->headers_out.content_type.len); | |
499 | |
500 if (r->headers_out.content_type_len == r->headers_out.content_type.len | |
501 && r->headers_out.charset.len) | |
502 { | |
503 b->last = ngx_cpymem(b->last, "; charset=", | |
504 sizeof("; charset=") - 1); | |
505 b->last = ngx_copy(b->last, r->headers_out.charset.data, | |
506 r->headers_out.charset.len); | |
507 | |
508 /* update r->headers_out.content_type for possible logging */ | |
509 | |
510 r->headers_out.content_type.len = b->last - p; | |
511 r->headers_out.content_type.data = p; | |
512 } | |
513 } | |
514 | |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
515 if (r->headers_out.content_length_n > 0) { |
8215 | 516 /* content-length: 0 */ |
517 *b->last = 0x70; | |
518 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 4, 4); | |
519 p = b->last++; | |
520 b->last = ngx_sprintf(b->last, "%O", r->headers_out.content_length_n); | |
521 *p = b->last - p - 1; | |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
522 |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
523 } 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:
8233
diff
changeset
|
524 /* content-length: 0 */ |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
525 *b->last = 0xc0; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
526 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 4, 6); |
8215 | 527 } |
528 | |
529 if (r->headers_out.last_modified == NULL | |
530 && r->headers_out.last_modified_time != -1) | |
531 { | |
532 /* last-modified */ | |
533 *b->last = 0x70; | |
534 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 10, 4); | |
535 p = b->last++; | |
536 b->last = ngx_http_time(b->last, r->headers_out.last_modified_time); | |
537 *p = b->last - p - 1; | |
538 } | |
539 | |
540 #if (NGX_HTTP_GZIP) | |
541 if (r->gzip_vary) { | |
542 /* vary: accept-encoding */ | |
543 *b->last = 0xc0; | |
544 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, 59, 6); | |
545 } | |
546 #endif | |
547 | |
548 part = &r->headers_out.headers.part; | |
549 header = part->elts; | |
550 | |
551 for (i = 0; /* void */; i++) { | |
552 | |
553 if (i >= part->nelts) { | |
554 if (part->next == NULL) { | |
555 break; | |
556 } | |
557 | |
558 part = part->next; | |
559 header = part->elts; | |
560 i = 0; | |
561 } | |
562 | |
563 if (header[i].hash == 0) { | |
564 continue; | |
565 } | |
566 | |
567 *b->last = 0x30; | |
568 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
569 header[i].key.len, | |
570 3); | |
571 for (j = 0; j < header[i].key.len; j++) { | |
572 *b->last++ = ngx_tolower(header[i].key.data[j]); | |
573 } | |
574 | |
575 *b->last = 0; | |
576 b->last = (u_char *) ngx_http_v3_encode_prefix_int(b->last, | |
577 header[i].value.len, | |
578 7); | |
579 b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); | |
580 } | |
581 | |
8238
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
582 if (r->header_only) { |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
583 b->last_buf = 1; |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
584 } |
a3257a725b3d
Fixed header creation for header_only responses in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8233
diff
changeset
|
585 |
8215 | 586 cl = ngx_alloc_chain_link(c->pool); |
587 if (cl == NULL) { | |
588 return NULL; | |
589 } | |
590 | |
591 cl->buf = b; | |
592 cl->next = NULL; | |
593 | |
594 n = b->last - b->pos; | |
595 | |
596 len = 1 + ngx_http_v3_encode_varlen_int(NULL, n); | |
597 | |
598 b = ngx_create_temp_buf(c->pool, len); | |
599 if (b == NULL) { | |
600 return NULL; | |
601 } | |
602 | |
603 *b->last++ = NGX_HTTP_V3_FRAME_HEADERS; | |
604 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, n); | |
605 | |
606 hl = ngx_alloc_chain_link(c->pool); | |
607 if (hl == NULL) { | |
608 return NULL; | |
609 } | |
610 | |
611 hl->buf = b; | |
612 hl->next = cl; | |
613 | |
614 if (r->headers_out.content_length_n >= 0) { | |
615 len = 1 + ngx_http_v3_encode_varlen_int(NULL, | |
616 r->headers_out.content_length_n); | |
617 | |
618 b = ngx_create_temp_buf(c->pool, len); | |
619 if (b == NULL) { | |
620 NULL; | |
621 } | |
622 | |
623 *b->last++ = NGX_HTTP_V3_FRAME_DATA; | |
624 b->last = (u_char *) ngx_http_v3_encode_varlen_int(b->last, | |
625 r->headers_out.content_length_n); | |
626 | |
627 bl = ngx_alloc_chain_link(c->pool); | |
628 if (bl == NULL) { | |
629 return NULL; | |
630 } | |
631 | |
632 bl->buf = b; | |
633 bl->next = NULL; | |
634 cl->next = bl; | |
635 } | |
636 | |
637 return hl; | |
638 } | |
8292
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
639 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
640 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
641 ngx_chain_t * |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
642 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
|
643 { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
644 ngx_buf_t *b; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
645 ngx_chain_t *cl; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
646 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
647 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
|
648 "http3 create trailers"); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
649 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
650 /* XXX */ |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
651 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
652 b = ngx_calloc_buf(r->pool); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
653 if (b == NULL) { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
654 return NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
655 } |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
656 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
657 b->last_buf = 1; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
658 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
659 cl = ngx_alloc_chain_link(r->pool); |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
660 if (cl == NULL) { |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
661 return NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
662 } |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
663 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
664 cl->buf = b; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
665 cl->next = NULL; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
666 |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
667 return cl; |
46e3542d51b3
Chunked response body in HTTP/3.
Roman Arutyunyan <arut@nginx.com>
parents:
8291
diff
changeset
|
668 } |