]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: h3: complete HTTP/3 request method encoding
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 30 May 2025 13:59:04 +0000 (15:59 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 16 Jun 2025 16:11:09 +0000 (18:11 +0200)
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.

include/haproxy/qpack-enc.h
src/h3.c
src/qpack-enc.c

index 26061a6e088ab3a046343393ae33b339fe354576..10ad1d415e052035b23cb0eddb9beff374156cb3 100644 (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);
index de236ba4d7683cb7e2b4699be4b42a8d23d59eaf..1ec2ae44060c30963c19e6e54e2cc77aaadc2649 100644 (file)
--- 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;
index 6c5fd9fb386b4c70ef6263d88585020ee1b0a243..4aebc0172b81ed2a413728e212e1f1f226b7b538 100644 (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_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, <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;