mirror of
https://github.com/nginx/nginx.git
synced 2025-07-31 02:26:15 +08:00
HTTP/3 $request_line variable.
This commit is contained in:
parent
5aa8e519c9
commit
e63accd7bd
@ -1177,7 +1177,7 @@ ngx_http_process_request_line(ngx_event_t *rev)
|
||||
|
||||
r->request_line.len = r->request_end - r->request_start;
|
||||
r->request_line.data = r->request_start;
|
||||
r->request_length = r->header_in->pos - r->request_start;
|
||||
r->request_length = r->header_in->pos - r->request_start; /* XXX */
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http request line: \"%V\"", &r->request_line);
|
||||
@ -1593,7 +1593,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
|
||||
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
|
||||
"http header done");
|
||||
|
||||
r->request_length += r->header_in->pos - r->header_name_start;
|
||||
r->request_length += r->header_in->pos - r->header_name_start; /* XXX */
|
||||
|
||||
r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE;
|
||||
|
||||
|
@ -40,6 +40,8 @@ struct {
|
||||
ngx_int_t
|
||||
ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
{
|
||||
size_t n;
|
||||
u_char *p;
|
||||
ngx_int_t rc;
|
||||
ngx_str_t *name, *value;
|
||||
ngx_connection_t *c;
|
||||
@ -97,23 +99,45 @@ ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b)
|
||||
name = &st->header_rep.header.name;
|
||||
value = &st->header_rep.header.value;
|
||||
|
||||
if (r->state == sw_start
|
||||
&& ngx_http_v3_process_pseudo_header(r, name, value) != NGX_OK)
|
||||
{
|
||||
if (rc == NGX_DONE) {
|
||||
r->state = sw_last;
|
||||
} else {
|
||||
if (r->state == sw_start) {
|
||||
|
||||
if (ngx_http_v3_process_pseudo_header(r, name, value) == NGX_OK) {
|
||||
if (rc == NGX_OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r->state = sw_done;
|
||||
|
||||
} else if (rc == NGX_OK) {
|
||||
r->state = sw_prev;
|
||||
|
||||
} else {
|
||||
r->state = sw_last;
|
||||
}
|
||||
|
||||
n = (r->method_end - r->method_start) + 1
|
||||
+ (r->uri_end - r->uri_start) + 1
|
||||
+ sizeof("HTTP/3") - 1;
|
||||
|
||||
p = ngx_pnalloc(c->pool, n);
|
||||
if (p == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
r->request_start = p;
|
||||
|
||||
p = ngx_cpymem(p, r->method_start, r->method_end - r->method_start);
|
||||
*p++ = ' ';
|
||||
p = ngx_cpymem(p, r->uri_start, r->uri_end - r->uri_start);
|
||||
*p++ = ' ';
|
||||
p = ngx_cpymem(p, "HTTP/3", sizeof("HTTP/3") - 1);
|
||||
|
||||
r->request_end = p;
|
||||
|
||||
} else if (rc == NGX_DONE) {
|
||||
r->state = sw_done;
|
||||
}
|
||||
|
||||
if (r->state == sw_start) {
|
||||
continue;
|
||||
}
|
||||
|
||||
r->header_name_start = name->data;
|
||||
r->header_name_end = name->data + name->len;
|
||||
r->header_start = value->data;
|
||||
@ -139,533 +163,6 @@ done:
|
||||
return NGX_HTTP_PARSE_HEADER_DONE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
ngx_int_t
|
||||
ngx_http_v3_parse_header(ngx_http_request_t *r, ngx_buf_t *b, ngx_uint_t pseudo)
|
||||
{
|
||||
u_char *p, ch;
|
||||
ngx_str_t name, value;
|
||||
ngx_int_t rc;
|
||||
ngx_uint_t length, index, insert_count, sign, base, delta_base,
|
||||
huffman, dynamic, offset;
|
||||
ngx_connection_t *c;
|
||||
ngx_http_v3_header_t *h;
|
||||
enum {
|
||||
sw_start = 0,
|
||||
sw_length,
|
||||
sw_length_1,
|
||||
sw_length_2,
|
||||
sw_length_3,
|
||||
sw_header_block,
|
||||
sw_req_insert_count,
|
||||
sw_delta_base,
|
||||
sw_read_delta_base,
|
||||
sw_header,
|
||||
sw_old_header,
|
||||
sw_header_ri,
|
||||
sw_header_pbi,
|
||||
sw_header_lri,
|
||||
sw_header_lpbi,
|
||||
sw_header_l_name_len,
|
||||
sw_header_l_name,
|
||||
sw_header_value_len,
|
||||
sw_header_read_value_len,
|
||||
sw_header_value
|
||||
} state;
|
||||
|
||||
c = r->connection;
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 parse header, pseudo:%ui", pseudo);
|
||||
|
||||
if (r->state == sw_old_header) {
|
||||
r->state = sw_header;
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
length = r->h3_length;
|
||||
index = r->h3_index;
|
||||
insert_count = r->h3_insert_count;
|
||||
sign = r->h3_sign;
|
||||
delta_base = r->h3_delta_base;
|
||||
huffman = r->h3_huffman;
|
||||
dynamic = r->h3_dynamic;
|
||||
offset = r->h3_offset;
|
||||
|
||||
name.data = r->header_name_start;
|
||||
name.len = r->header_name_end - r->header_name_start;
|
||||
value.data = r->header_start;
|
||||
value.len = r->header_end - r->header_start;
|
||||
|
||||
if (r->state == sw_start) {
|
||||
length = 1;
|
||||
}
|
||||
|
||||
again:
|
||||
|
||||
state = r->state;
|
||||
|
||||
if (state == sw_header && length == 0) {
|
||||
r->state = sw_start;
|
||||
return NGX_HTTP_PARSE_HEADER_DONE;
|
||||
}
|
||||
|
||||
for (p = b->pos; p < b->last; p++) {
|
||||
|
||||
if (state >= sw_header_block && length-- == 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ch = *p;
|
||||
|
||||
switch (state) {
|
||||
|
||||
case sw_start:
|
||||
|
||||
if (ch != NGX_HTTP_V3_FRAME_HEADERS) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
r->request_start = p;
|
||||
state = sw_length;
|
||||
break;
|
||||
|
||||
case sw_length:
|
||||
|
||||
length = ch;
|
||||
if (length & 0xc0) {
|
||||
state = sw_length_1;
|
||||
break;
|
||||
}
|
||||
|
||||
state = sw_header_block;
|
||||
break;
|
||||
|
||||
case sw_length_1:
|
||||
|
||||
length = (length << 8) + ch;
|
||||
if ((length & 0xc000) != 0x4000) {
|
||||
state = sw_length_2;
|
||||
break;
|
||||
}
|
||||
|
||||
length &= 0x3fff;
|
||||
state = sw_header_block;
|
||||
break;
|
||||
|
||||
case sw_length_2:
|
||||
|
||||
length = (length << 8) + ch;
|
||||
if ((length & 0xc00000) != 0x800000) {
|
||||
state = sw_length_3;
|
||||
break;
|
||||
}
|
||||
|
||||
length &= 0x3fffff;
|
||||
state = sw_header_block;
|
||||
break;
|
||||
|
||||
case sw_length_3:
|
||||
|
||||
length = (length << 8) + ch;
|
||||
length &= 0x3fffffff;
|
||||
state = sw_header_block;
|
||||
break;
|
||||
|
||||
case sw_header_block:
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 header block length:%ui", length);
|
||||
|
||||
if (ch != 0xff) {
|
||||
insert_count = ch;
|
||||
state = sw_delta_base;
|
||||
break;
|
||||
}
|
||||
|
||||
insert_count = 0;
|
||||
state = sw_req_insert_count;
|
||||
break;
|
||||
|
||||
case sw_req_insert_count:
|
||||
|
||||
insert_count = (insert_count << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
insert_count += 0xff;
|
||||
state = sw_delta_base;
|
||||
break;
|
||||
|
||||
case sw_delta_base:
|
||||
|
||||
sign = (ch & 0x80) ? 1 : 0;
|
||||
delta_base = ch & 0x7f;
|
||||
|
||||
if (delta_base != 0x7f) {
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 header block "
|
||||
"insert_count:%ui, sign:%ui, delta_base:%ui",
|
||||
insert_count, sign, delta_base);
|
||||
goto done;
|
||||
}
|
||||
|
||||
delta_base = 0;
|
||||
state = sw_read_delta_base;
|
||||
break;
|
||||
|
||||
case sw_read_delta_base:
|
||||
|
||||
delta_base = (delta_base << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
delta_base += 0x7f;
|
||||
|
||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 header block "
|
||||
"insert_count:%ui, sign:%ui, delta_base:%ui",
|
||||
insert_count, sign, delta_base);
|
||||
goto done;
|
||||
|
||||
case sw_header:
|
||||
|
||||
index = 0;
|
||||
huffman = 0;
|
||||
ngx_str_null(&name);
|
||||
ngx_str_null(&value);
|
||||
|
||||
if (ch & 0x80) {
|
||||
/* Indexed Header Field */
|
||||
|
||||
dynamic = (ch & 0x40) ? 0 : 1;
|
||||
index = ch & 0x3f;
|
||||
|
||||
if (index != 0x3f) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
state = sw_header_ri;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch & 0x40) {
|
||||
/* Literal Header Field With Name Reference */
|
||||
|
||||
dynamic = (ch & 0x10) ? 0 : 1;
|
||||
index = ch & 0x0f;
|
||||
|
||||
if (index != 0x0f) {
|
||||
state = sw_header_value_len;
|
||||
break;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
state = sw_header_lri;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch & 0x20) {
|
||||
/* Literal Header Field Without Name Reference */
|
||||
|
||||
huffman = (ch & 0x08) ? 1 : 0;
|
||||
name.len = ch & 0x07;
|
||||
|
||||
if (name.len == 0) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (name.len != 0x07) {
|
||||
offset = 0;
|
||||
state = sw_header_l_name;
|
||||
break;
|
||||
}
|
||||
|
||||
name.len = 0;
|
||||
state = sw_header_l_name_len;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ch & 10) {
|
||||
/* Indexed Header Field With Post-Base Index */
|
||||
|
||||
dynamic = 2;
|
||||
index = ch & 0x0f;
|
||||
|
||||
if (index != 0x0f) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
state = sw_header_pbi;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Literal Header Field With Post-Base Name Reference */
|
||||
|
||||
dynamic = 2;
|
||||
index = ch & 0x07;
|
||||
|
||||
if (index != 0x07) {
|
||||
state = sw_header_value_len;
|
||||
break;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
state = sw_header_lpbi;
|
||||
break;
|
||||
|
||||
case sw_header_ri:
|
||||
|
||||
index = (index << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
index += 0x3f;
|
||||
goto done;
|
||||
|
||||
case sw_header_pbi:
|
||||
|
||||
index = (index << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
index += 0x0f;
|
||||
goto done;
|
||||
|
||||
case sw_header_lri:
|
||||
|
||||
index = (index << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
index += 0x0f;
|
||||
state = sw_header_value_len;
|
||||
break;
|
||||
|
||||
case sw_header_lpbi:
|
||||
|
||||
index = (index << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
index += 0x07;
|
||||
state = sw_header_value_len;
|
||||
break;
|
||||
|
||||
|
||||
case sw_header_l_name_len:
|
||||
|
||||
name.len = (name.len << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
name.len += 0x07;
|
||||
offset = 0;
|
||||
state = sw_header_l_name;
|
||||
break;
|
||||
|
||||
case sw_header_l_name:
|
||||
if (offset++ == 0) {
|
||||
name.data = p;
|
||||
}
|
||||
|
||||
if (offset != name.len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (huffman) {
|
||||
if (ngx_http_v3_decode_huffman(c, &name) != NGX_OK) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
state = sw_header_value_len;
|
||||
break;
|
||||
|
||||
case sw_header_value_len:
|
||||
|
||||
huffman = (ch & 0x80) ? 1 : 0;
|
||||
value.len = ch & 0x7f;
|
||||
|
||||
if (value.len == 0) {
|
||||
value.data = p;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (value.len != 0x7f) {
|
||||
offset = 0;
|
||||
state = sw_header_value;
|
||||
break;
|
||||
}
|
||||
|
||||
value.len = 0;
|
||||
state = sw_header_read_value_len;
|
||||
break;
|
||||
|
||||
case sw_header_read_value_len:
|
||||
|
||||
value.len = (value.len << 7) + (ch & 0x7f);
|
||||
if (ch & 0x80) {
|
||||
break;
|
||||
}
|
||||
|
||||
value.len += 0x7f;
|
||||
offset = 0;
|
||||
state = sw_header_value;
|
||||
break;
|
||||
|
||||
case sw_header_value:
|
||||
|
||||
if (offset++ == 0) {
|
||||
value.data = p;
|
||||
}
|
||||
|
||||
if (offset != value.len) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (huffman) {
|
||||
if (ngx_http_v3_decode_huffman(c, &value) != NGX_OK) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
case sw_old_header:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
b->pos = p;
|
||||
r->state = state;
|
||||
r->h3_length = length;
|
||||
r->h3_index = index;
|
||||
r->h3_insert_count = insert_count;
|
||||
r->h3_sign = sign;
|
||||
r->h3_delta_base = delta_base;
|
||||
r->h3_huffman = huffman;
|
||||
r->h3_dynamic = dynamic;
|
||||
r->h3_offset = offset;
|
||||
|
||||
/* XXX fix large reallocations */
|
||||
r->header_name_start = name.data;
|
||||
r->header_name_end = name.data + name.len;
|
||||
r->header_start = value.data;
|
||||
r->header_end = value.data + value.len;
|
||||
|
||||
/* XXX r->lowcase_index = i; */
|
||||
|
||||
return NGX_AGAIN;
|
||||
|
||||
done:
|
||||
|
||||
b->pos = p + 1;
|
||||
r->state = sw_header;
|
||||
r->h3_length = length;
|
||||
r->h3_insert_count = insert_count;
|
||||
r->h3_sign = sign;
|
||||
r->h3_delta_base = delta_base;
|
||||
|
||||
if (state < sw_header) {
|
||||
if (ngx_http_v3_check_insert_count(c, insert_count) != NGX_OK) {
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (sign == 0) {
|
||||
base = insert_count + delta_base;
|
||||
} else {
|
||||
base = insert_count - delta_base - 1;
|
||||
}
|
||||
|
||||
ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 header %s[%ui], base:%ui, \"%V\":\"%V\"",
|
||||
dynamic ? "dynamic" : "static", index, base, &name, &value);
|
||||
|
||||
if (name.data == NULL) {
|
||||
|
||||
if (dynamic == 2) {
|
||||
index = base - index - 1;
|
||||
} else if (dynamic == 1) {
|
||||
index += base;
|
||||
}
|
||||
|
||||
h = ngx_http_v3_lookup_table(c, dynamic, index);
|
||||
if (h == NULL) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
name = h->name;
|
||||
|
||||
if (value.data == NULL) {
|
||||
value = h->value;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX ugly reallocation for the trailing '\0' */
|
||||
|
||||
p = ngx_pnalloc(c->pool, name.len + value.len + 2);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(p, name.data, name.len);
|
||||
name.data = p;
|
||||
ngx_memcpy(p + name.len + 1, value.data, value.len);
|
||||
value.data = p + name.len + 1;
|
||||
|
||||
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 header \"%V\":\"%V\"", &name, &value);
|
||||
|
||||
if (pseudo) {
|
||||
rc = ngx_http_v3_process_pseudo_header(r, &name, &value);
|
||||
|
||||
if (rc == NGX_ERROR) {
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if (rc == NGX_OK) {
|
||||
r->request_end = p + 1;
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* rc == NGX_DONE */
|
||||
|
||||
r->state = sw_old_header;
|
||||
}
|
||||
|
||||
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||
"http3 header left:%ui", length);
|
||||
|
||||
r->header_name_start = name.data;
|
||||
r->header_name_end = name.data + name.len;
|
||||
r->header_start = value.data;
|
||||
r->header_end = value.data + value.len;
|
||||
r->header_hash = ngx_hash_key(name.data, name.len); /* XXX */
|
||||
|
||||
/* XXX r->lowcase_index = i; */
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
failed:
|
||||
|
||||
return NGX_HTTP_PARSE_INVALID_REQUEST;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
|
||||
@ -675,7 +172,7 @@ ngx_http_v3_process_pseudo_header(ngx_http_request_t *r, ngx_str_t *name,
|
||||
ngx_connection_t *c;
|
||||
|
||||
if (name->len == 0 || name->data[0] != ':') {
|
||||
return NGX_DECLINED;
|
||||
return NGX_DONE;
|
||||
}
|
||||
|
||||
c = r->connection;
|
||||
|
Loading…
Reference in New Issue
Block a user