From: Amaury Denoyelle Date: Fri, 30 May 2025 13:59:04 +0000 (+0200) Subject: MINOR: h3: complete HTTP/3 request method encoding X-Git-Tag: v3.3-dev2~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a0912cf914;p=thirdparty%2Fhaproxy.git 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. --- diff --git a/include/haproxy/qpack-enc.h b/include/haproxy/qpack-enc.h index 26061a6e0..10ad1d415 100644 --- a/include/haproxy/qpack-enc.h +++ b/include/haproxy/qpack-enc.h @@ -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); diff --git a/src/h3.c b/src/h3.c index de236ba4d..1ec2ae440 100644 --- a/src/h3.c +++ b/src/h3.c @@ -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; diff --git a/src/qpack-enc.c b/src/qpack-enc.c index 6c5fd9fb3..4aebc0172 100644 --- a/src/qpack-enc.c +++ b/src/qpack-enc.c @@ -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_GET: idx = 17; break; - default: ABORT_NOW(); + case HTTP_METH_CONNECT: idx = 15; break; + 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) { - /* 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, 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;