]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: hq-interop: decode response into HTX for backend side support
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 6 Jun 2025 14:23:22 +0000 (16:23 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 12 Jun 2025 09:28:54 +0000 (11:28 +0200)
Implement transcoding of a HTTP/0.9 response into a HTX message.

HTTP/0.9 is a really simple substract of HTTP spec. The response does
not have any status line and is contains only the payload body. Response
is finished when the underlying connection/stream is closed.

A status line is generated to be compliant with HTX. This is performed
on the first invokation of rcv_buf for the current stream. Status code
is set to 200. Payload body if present is then copied using
htx_add_data().

src/hq_interop.c

index 6a1ec2db00c30d0c16004c983c234a1c5e59c5b7..46a456ef1d81f043ede0afbd38d9ec37f3a54e3a 100644 (file)
@@ -12,8 +12,8 @@
 #include <haproxy/quic_utils.h>
 #include <haproxy/trace.h>
 
-/* Returns the amount of decoded bytes from <b> or a negative error code. */
-static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
+/* HTTP/0.9 request -> HTX. */
+static ssize_t hq_interop_rcv_buf_req(struct qcs *qcs, struct buffer *b, int fin)
 {
        struct htx *htx;
        struct htx_sl *sl;
@@ -93,6 +93,66 @@ static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
        return b_data(b);
 }
 
+/* HTTP/0.9 response -> HTX. */
+static ssize_t hq_interop_rcv_buf_res(struct qcs *qcs, struct buffer *b, int fin)
+{
+       ssize_t ret = 0;
+       struct htx *htx;
+       struct htx_sl *sl;
+       struct buffer *htx_buf;
+       const struct stream *strm = __sc_strm(qcs->sd->sc);
+       const unsigned int flags = HTX_SL_F_VER_11|HTX_SL_F_XFER_LEN;
+       size_t htx_sent;
+
+       htx_buf = qcc_get_stream_rxbuf(qcs);
+       BUG_ON(!htx_buf);
+       htx = htx_from_buf(htx_buf);
+
+       if (htx_is_empty(htx) && !strm->res.total) {
+               /* First data transfer, add HTX response start-line first. */
+               sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags,
+                                   ist("HTTP/1.0"), ist("200"), ist(""));
+               BUG_ON(!sl);
+               if (fin && !b_data(b))
+                       sl->flags |= HTX_SL_F_BODYLESS;
+               htx_add_endof(htx, HTX_BLK_EOH);
+       }
+
+       if (!b_data(b)) {
+               if (fin && quic_stream_is_bidi(qcs->id)) {
+                       if (qcs_http_handle_standalone_fin(qcs)) {
+                               htx_to_buf(htx, htx_buf);
+                               return -1;
+                       }
+               }
+       }
+       else {
+               BUG_ON(b_data(b) > htx_free_data_space(htx)); /* TODO */
+               BUG_ON(b_head(b) + b_data(b) > b_wrap(b));    /* TODO */
+
+               htx_sent = htx_add_data(htx, ist2(b_head(b), b_data(b)));
+               BUG_ON(htx_sent < b_data(b)); /* TODO */
+               ret = htx_sent;
+
+               if (fin && b_data(b) == htx_sent)
+                       htx->flags |= HTX_FL_EOM;
+       }
+
+       htx_to_buf(htx, htx_buf);
+       return ret;
+}
+
+/* Returns the amount of decoded bytes from <b> or a negative error code. */
+static ssize_t hq_interop_rcv_buf(struct qcs *qcs, struct buffer *b, int fin)
+{
+       /* hq-interop parser does not support buffer wrapping. */
+       BUG_ON(b_data(b) != b_contig_data(b, 0));
+
+       return !(qcs->qcc->flags & QC_CF_IS_BACK) ?
+         hq_interop_rcv_buf_req(qcs, b, fin) :
+         hq_interop_rcv_buf_res(qcs, b, fin);
+}
+
 /* Returns the amount of consumed bytes from <buf>. */
 static size_t hq_interop_snd_buf(struct qcs *qcs, struct buffer *buf,
                                  size_t count)