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