From: Amaury Denoyelle Date: Wed, 16 Apr 2025 13:17:57 +0000 (+0200) Subject: MEDIUM: h3: use absolute URI form with :authority X-Git-Tag: v3.2-dev11~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c3d656f8;p=thirdparty%2Fhaproxy.git MEDIUM: h3: use absolute URI form with :authority 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. --- diff --git a/src/h3.c b/src/h3.c index c99619b72..69528147b 100644 --- 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;