BUG/MINOR: http-ana: Don't send payload for internal responses to HEAD requests
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 19 Oct 2020 16:01:38 +0000 (18:01 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 3 Nov 2020 15:01:33 +0000 (16:01 +0100)
When an internal response is returned to a client, the message payload must be
skipped if it is a reply to a HEAD request. The payload is removed from the HTX
message just before the message forwarding.

This bugs has been around for a long time. It was already there in the pre-HTX
versions. In legacy HTTP mode, internal errors are not parsed. So this bug
cannot be easily fixed. Thus, this patch should only be backported in all HTX
versions, as far as 2.0. However, the code has significantly changed in the
2.2. Thus in the 2.1 and 2.0, the patch must be entirely reworked.

(cherry picked from commit d6c48366b81e4f95676b038db32d23cdc541735e)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>
(cherry picked from commit 0471ef6514cc9f07e1096b878f3e47baf3692d08)
[cf: adapted for the 2.1, as expected. ]
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

include/common/htx.h
src/http_ana.c

index 9818a3f..4c9d6d0 100644 (file)
@@ -780,6 +780,19 @@ static inline int htx_is_not_empty(const struct htx *htx)
        return (htx->head != -1);
 }
 
+static inline void htx_skip_msg_payload(struct htx *htx)
+{
+       struct htx_blk *blk = htx_get_first_blk(htx);
+
+       while (blk) {
+               enum htx_blk_type type = htx_get_blk_type(blk);
+
+               blk = ((type > HTX_BLK_EOH && type < HTX_BLK_EOM)
+                      ? htx_remove_blk(htx, blk)
+                      : htx_get_next_blk(htx, blk));
+       }
+}
+
 /* Returns the number of used blocks in the HTX message <htx>. Note that it is
  * illegal to call this function with htx == NULL. Note also blocks of type
  * HTX_BLK_UNUSED are part of used blocks.
index db938c1..8b26c21 100644 (file)
@@ -4983,6 +4983,8 @@ void http_server_error(struct stream *s, struct stream_interface *si, int err,
                FLT_STRM_CB(s, flt_http_reply(s, s->txn->status, msg));
                htx = htx_from_buf(&chn->buf);
                if (channel_htx_copy_msg(chn, htx, msg)) {
+                       if (s->txn->meth == HTTP_METH_HEAD)
+                               htx_skip_msg_payload(htx);
                        htx->flags |= HTX_FL_PROXY_RESP;
                        data = htx->data - co_data(chn);
                        c_adv(chn, data);
@@ -5015,6 +5017,8 @@ void http_reply_and_close(struct stream *s, short status, struct buffer *msg)
                FLT_STRM_CB(s, flt_http_reply(s, s->txn->status, msg));
                htx = htx_from_buf(&chn->buf);
                if (channel_htx_copy_msg(chn, htx, msg)) {
+                       if (s->txn->meth == HTTP_METH_HEAD)
+                               htx_skip_msg_payload(htx);
                        htx->flags |= HTX_FL_PROXY_RESP;
                        data = htx->data - co_data(chn);
                        c_adv(chn, data);
@@ -5201,6 +5205,9 @@ static int http_reply_40x_unauthorized(struct stream *s, const char *auth_realm)
        if (!htx_add_endof(htx, HTX_BLK_EOH))
                goto fail;
 
+       if (s->txn->meth == HTTP_METH_HEAD)
+               body.len = 0;
+
        while (body.len) {
                size_t sent = htx_add_data(htx, body);
                if (!sent)