MINOR: h3: complete HTTP/3 request method encoding

On the backend side, HTX start-line is converted into a HTTP/3 request
message. Previously, GET method was hardcoded. Implement proper method
conversion, by extracting it from the HTX start-line.

qpack_encode_method() has also been extended, so that it is able to
encode any method, either using a static table entry, or with a literal
field line with name ref representation.
This commit is contained in:
Amaury Denoyelle 2025-05-30 15:59:04 +02:00
parent f5342e0a96
commit a0912cf914
3 changed files with 27 additions and 14 deletions

View File

@ -8,7 +8,7 @@ struct buffer;
int qpack_encode_field_section_line(struct buffer *out);
int qpack_encode_int_status(struct buffer *out, unsigned int status);
int qpack_encode_method(struct buffer *out, enum http_meth_t meth);
int qpack_encode_method(struct buffer *out, enum http_meth_t meth, struct ist other);
int qpack_encode_scheme(struct buffer *out);
int qpack_encode_path(struct buffer *out, const struct ist path);
int qpack_encode_header(struct buffer *out, const struct ist n, const struct ist v);

View File

@ -1707,6 +1707,7 @@ static int h3_req_headers_send(struct qcs *qcs, struct htx *htx)
enum htx_blk_type type;
struct htx_blk *blk;
struct htx_sl *sl;
struct ist meth;
int frame_length_size; /* size in bytes of frame length varint field */
int ret, err, hdr;
@ -1724,6 +1725,7 @@ static int h3_req_headers_send(struct qcs *qcs, struct htx *htx)
case HTX_BLK_REQ_SL:
BUG_ON_HOT(sl); /* Only one start-line expected */
sl = htx_get_blk_ptr(htx, blk);
meth = htx_sl_req_meth(sl);
break;
case HTX_BLK_HDR:
@ -1757,10 +1759,8 @@ static int h3_req_headers_send(struct qcs *qcs, struct htx *htx)
if (qpack_encode_field_section_line(&headers_buf))
goto err;
/* :method */
if (qpack_encode_method(&headers_buf, HTTP_METH_GET))
if (qpack_encode_method(&headers_buf, sl->info.req.meth, meth))
goto err;
/* :scheme */
if (qpack_encode_scheme(&headers_buf))
goto err;

View File

@ -133,27 +133,40 @@ int qpack_encode_int_status(struct buffer *out, unsigned int status)
}
/* Returns 0 on success else non-zero. */
int qpack_encode_method(struct buffer *out, enum http_meth_t meth)
int qpack_encode_method(struct buffer *out, enum http_meth_t meth, struct ist other)
{
int size, idx = 0;
int sz, idx = 0;
switch (meth) {
case HTTP_METH_CONNECT: idx = 15; break;
case HTTP_METH_DELETE: idx = 16; break;
case HTTP_METH_GET: idx = 17; break;
default: ABORT_NOW();
case HTTP_METH_HEAD: idx = 18; break;
case HTTP_METH_OPTIONS: idx = 19; break;
case HTTP_METH_POST: idx = 20; break;
case HTTP_METH_PUT: idx = 21; break;
default: break;
}
if (idx) {
/* method present in QPACK static table
* -> indexed field line
*/
size = qpack_get_prefix_int_size(idx, 6);
if (b_room(out) < size)
/* indexed field line */
if (b_room(out) < 2)
return 1;
qpack_encode_prefix_integer(out, idx, 6, 0xc0);
}
else {
ABORT_NOW();
BUG_ON(!istlen(other)); /* non standard method, <other> must be set. */
sz = 2 + qpack_get_prefix_int_size(istlen(other), 7) + istlen(other);
if (b_room(out) < sz)
return 1;
/* literal field line with name ref */
qpack_encode_prefix_integer(out, 15, 4, 0x50);
qpack_encode_prefix_integer(out, istlen(other), 7, 0);
for (size_t i = 0; i < istlen(other); ++i)
b_putchr(out, istptr(other)[i]);
}
return 0;