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_field_section_line(struct buffer *out);
int qpack_encode_int_status(struct buffer *out, unsigned int status); 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_scheme(struct buffer *out);
int qpack_encode_path(struct buffer *out, const struct ist path); 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); 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; enum htx_blk_type type;
struct htx_blk *blk; struct htx_blk *blk;
struct htx_sl *sl; struct htx_sl *sl;
struct ist meth;
int frame_length_size; /* size in bytes of frame length varint field */ int frame_length_size; /* size in bytes of frame length varint field */
int ret, err, hdr; 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: case HTX_BLK_REQ_SL:
BUG_ON_HOT(sl); /* Only one start-line expected */ BUG_ON_HOT(sl); /* Only one start-line expected */
sl = htx_get_blk_ptr(htx, blk); sl = htx_get_blk_ptr(htx, blk);
meth = htx_sl_req_meth(sl);
break; break;
case HTX_BLK_HDR: 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)) if (qpack_encode_field_section_line(&headers_buf))
goto err; goto err;
/* :method */ if (qpack_encode_method(&headers_buf, sl->info.req.meth, meth))
if (qpack_encode_method(&headers_buf, HTTP_METH_GET))
goto err; goto err;
/* :scheme */
if (qpack_encode_scheme(&headers_buf)) if (qpack_encode_scheme(&headers_buf))
goto err; 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. */ /* 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) { switch (meth) {
case HTTP_METH_GET: idx = 17; break; case HTTP_METH_CONNECT: idx = 15; break;
default: ABORT_NOW(); case HTTP_METH_DELETE: idx = 16; break;
case HTTP_METH_GET: idx = 17; break;
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) { if (idx) {
/* method present in QPACK static table /* indexed field line */
* -> indexed field line if (b_room(out) < 2)
*/
size = qpack_get_prefix_int_size(idx, 6);
if (b_room(out) < size)
return 1; return 1;
qpack_encode_prefix_integer(out, idx, 6, 0xc0); qpack_encode_prefix_integer(out, idx, 6, 0xc0);
} }
else { 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; return 0;