]> git.kaiwu.me - haproxy.git/commitdiff
MEDIUM: http-htx: Make authority update optional when replacing a header value
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 24 Apr 2026 09:15:27 +0000 (11:15 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 29 Apr 2026 08:03:39 +0000 (10:03 +0200)
When a header value is replaced, a test is performed to verify if the
authority must be updated or not. But there are some places where we know it
is useless. First, when the caller know the header is not the host
header. Then when the host header value is updated because the authority was
changed.

So now, an extra argument was added to http_replace_header() and
http_replace_header_value() functions to specify if the authority update
must be performed or not.

include/haproxy/http_htx.h
src/flt_http_comp.c
src/http_ana.c
src/http_htx.c

index 784596dd1da41003b309400f48e2586e5702d6e0..7259d29d7aa3edf3c06bd30b3b0c17d879e7abbd 100644 (file)
@@ -52,8 +52,8 @@ int http_replace_res_status(struct htx *htx, const struct ist status, const stru
 int http_replace_res_reason(struct htx *htx, const struct ist reason);
 int http_append_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data);
 int http_prepend_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data);
-int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data);
-int http_replace_header(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist name, const struct ist value);
+int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data, int update_authority);
+int http_replace_header(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist name, const struct ist value, int update_authority);
 int http_remove_header(struct htx *htx, struct http_hdr_ctx *ctx);
 int http_update_authority(struct htx *htx, struct htx_sl *sl, const struct ist host);
 int http_update_host(struct htx *htx, struct htx_sl *sl, const struct ist uri);
index bd5117097b706aa2f06e5355521343893fe3fe42..bbcb083ff1cde4c431cfd2c7af2806eb21f7fd5e 100644 (file)
@@ -477,7 +477,7 @@ set_compression_header(struct comp_state *st, struct stream *s, struct http_msg
                        if (istcat(&v, ist("W/"), trash.size) == -1 || istcat(&v, ctx.value, trash.size) == -1)
                                goto error;
 
-                       if (!http_replace_header_value(htx, &ctx, v))
+                       if (!http_replace_header_value(htx, &ctx, v, 0))
                                goto error;
                }
        }
index 533613fd449e2c948c49fb43c93e11ceae680447..f0a21554acd66a93049b5685320f35708fce01b5 100644 (file)
@@ -2728,7 +2728,7 @@ int http_replace_hdrs(struct stream* s, struct htx *htx, struct ist name,
                output->data = exp_replace(output->area, output->size, ctx.value.ptr, str, pmatch);
                if (output->data == -1)
                        return -1;
-               if (!http_replace_header_value(htx, &ctx, ist2(output->area, output->data)))
+               if (!http_replace_header_value(htx, &ctx, ist2(output->area, output->data), 1))
                        return -1;
        }
        return 0;
@@ -3849,7 +3849,7 @@ static void http_manage_server_side_cookies(struct stream *s, struct channel *re
 
                                        ctx.value = ist2(val_beg, val_end - val_beg);
                                        ctx.lws_before = ctx.lws_after = 0;
-                                       http_replace_header_value(htx, &ctx, ist2(srv->cookie, srv->cklen));
+                                       http_replace_header_value(htx, &ctx, ist2(srv->cookie, srv->cklen), 0);
                                        delta     = srv->cklen - (val_end - val_beg);
                                        sliding   = (ctx.value.ptr - val_beg);
                                        hdr_beg  += sliding;
@@ -3867,7 +3867,7 @@ static void http_manage_server_side_cookies(struct stream *s, struct channel *re
                                        int sliding, delta;
                                        ctx.value = ist2(val_beg, 0);
                                        ctx.lws_before = ctx.lws_after = 0;
-                                       http_replace_header_value(htx, &ctx, ist2(srv->cookie, srv->cklen + 1));
+                                       http_replace_header_value(htx, &ctx, ist2(srv->cookie, srv->cklen + 1), 0);
                                        delta     = srv->cklen + 1;
                                        sliding   = (ctx.value.ptr - val_beg);
                                        hdr_beg  += sliding;
index cc5e4ecad6523fee29ff84f6ae6bc953f9b069e3..aced3f5e4a2fa5a305974654a07335e02973290f 100644 (file)
@@ -650,7 +650,8 @@ int http_prepend_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const s
  * <data>. It returns 1 on success, otherwise it returns 0. The context is
  * updated if necessary.
  */
-int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data)
+int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data,
+                             int update_authority)
 {
        struct htx_blk *blk = ctx->blk;
        struct htx_sl *sl;
@@ -671,6 +672,9 @@ int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const s
                goto fail;
        v = htx_get_blk_value(htx, blk);
 
+       if (!update_authority)
+               goto out;
+
        sl = http_get_stline(htx);
        if (sl && (sl->flags & HTX_SL_F_HAS_AUTHORITY)) {
                struct ist n = htx_get_blk_name(htx, blk);
@@ -684,7 +688,7 @@ int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const s
                        v = htx_get_blk_value(htx, blk);
                }
        }
-
+  out:
        ctx->blk = blk;
        ctx->value = ist2(v.ptr + off, data.len);
        ctx->lws_before = ctx->lws_after = 0;
@@ -699,7 +703,8 @@ int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const s
  * context is updated if necessary.
  */
 int http_replace_header(struct htx *htx, struct http_hdr_ctx *ctx,
-                       const struct ist name, const struct ist value)
+                       const struct ist name, const struct ist value,
+                       int update_authority)
 {
        struct htx_blk *blk = ctx->blk;
        struct htx_sl *sl;
@@ -711,6 +716,9 @@ int http_replace_header(struct htx *htx, struct http_hdr_ctx *ctx,
        if (!blk)
                goto fail;
 
+       if (!update_authority)
+               goto out;
+
        sl = http_get_stline(htx);
        if (sl && (sl->flags & HTX_SL_F_HAS_AUTHORITY) && isteqi(name, ist("host"))) {
                if (!http_update_authority(htx, sl, value))
@@ -720,6 +728,7 @@ int http_replace_header(struct htx *htx, struct http_hdr_ctx *ctx,
                blk = ctx->blk;
        }
 
+  out:
        ctx->blk = blk;
        ctx->value = ist(NULL);
        ctx->lws_before = ctx->lws_after = 0;
@@ -867,7 +876,7 @@ int http_update_host(struct htx *htx, struct htx_sl *sl, const struct ist uri)
                /* Replace header host value */
                ctx.blk = NULL;
                while (http_find_header(htx, ist("host"), &ctx, 1)) {
-                       if (!http_replace_header_value(htx, &ctx, authority))
+                       if (!http_replace_header_value(htx, &ctx, authority, 0))
                                goto fail;
                }
 
@@ -1889,7 +1898,7 @@ int http_scheme_based_normalize(struct htx *htx)
                /* replace every host headers by the normalized host */
                ctx.blk = NULL;
                while (http_find_header(htx, ist("host"), &ctx, 1)) {
-                       if (!http_replace_header_value(htx, &ctx, host)) {
+                       if (!http_replace_header_value(htx, &ctx, host, 0)) {
                                free_trash_chunk(temp);
                                goto fail;
                        }