MEDIUM: http-htx: Make authority update optional when replacing a header value

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.
This commit is contained in:
Christopher Faulet 2026-04-24 11:15:27 +02:00
parent 8d2ea3c1ce
commit 9368f4eaa2
4 changed files with 20 additions and 11 deletions

View 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);

View 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;
}
}

View 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;

View 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;
}