]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: h3: use absolute URI form with :authority
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 16 Apr 2025 13:17:57 +0000 (15:17 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 16 Apr 2025 16:32:00 +0000 (18:32 +0200)
Change the representation of the start-line URI when parsing a HTTP/3
request into HTX. Adopt the same conversion as HTTP/2. If :authority
header is used (default case), the URI is encoded using absolute-form,
with scheme, host and path concatenated. If only a plain host header is
used instead, fallback to the origin form.

This commit may cause some configuration to be broken if parsing is
performed on the URI. Indeed, now most of the HTTP/3 requests will be
represented with an absolute-form URI at the stream layer.

Note that prior to this commit a check was performed on the path used as
URI to ensure that it did not contain any invalid characters. Now, this
is directly performed on the URI itself, which may include the path.

This must not be backported.

src/h3.c

index c99619b727fe024795051b80040f62e1d83ae0ba..69528147b82a9a745ea4fc818802892a82fe2f81 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -529,6 +529,7 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        unsigned int flags = HTX_SL_F_NONE;
        struct ist meth = IST_NULL, path = IST_NULL;
        struct ist scheme = IST_NULL, authority = IST_NULL;
+       struct ist uri;
        struct ist v;
        int hdr_idx, ret;
        int cookie = -1, last_cookie = -1, i;
@@ -752,9 +753,26 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                goto out;
        }
 
+       if (!istlen(scheme)) {
+               /* No scheme (CONNECT), use :authority only. */
+               uri = authority;
+       }
+       else if (isttest(authority)) {
+               /* Use absolute URI form as :authority is present. */
+               uri = ist2bin(trash.area, scheme);
+               istcat(&uri, ist("://"), trash.size);
+               istcat(&uri, authority, trash.size);
+               if (!isteq(path, ist("*")))
+                       istcat(&uri, path, trash.size);
+       }
+       else {
+               /* Use origin URI form. */
+               uri = path;
+       }
+
        /* Ensure that final URI does not contains LWS nor CTL characters. */
-       for (i = 0; i < path.len; i++) {
-               unsigned char c = istptr(path)[i];
+       for (i = 0; i < uri.len; i++) {
+               unsigned char c = istptr(uri)[i];
                if (HTTP_IS_LWS(c) || HTTP_IS_CTL(c)) {
                        TRACE_ERROR("invalid character in path", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
                        h3s->err = H3_ERR_MESSAGE_ERROR;
@@ -764,7 +782,7 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                }
        }
 
-       sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, meth, path, ist("HTTP/3.0"));
+       sl = htx_add_stline(htx, HTX_BLK_REQ_SL, flags, meth, uri, ist("HTTP/3.0"));
        if (!sl) {
                len = -1;
                goto out;