From 38ebffaf10d6bb23c9e6be3efcf7ec134b57b617 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Thu, 5 Jan 2023 17:02:19 +0100 Subject: [PATCH] MINOR: http_htx: add http_prepend_header() to prepend value to header Just like http_append_header(), but this time to insert new value before an existing one. If the header already contains one or multiple values, ',' is automatically inserted after the new value. --- include/haproxy/http_htx.h | 1 + src/http_htx.c | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/include/haproxy/http_htx.h b/include/haproxy/http_htx.h index 47f533640..3d01a061f 100644 --- a/include/haproxy/http_htx.h +++ b/include/haproxy/http_htx.h @@ -51,6 +51,7 @@ int http_replace_req_query(struct htx *htx, const struct ist query); int http_replace_res_status(struct htx *htx, const struct ist status, const struct ist reason); 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_remove_header(struct htx *htx, struct http_hdr_ctx *ctx); diff --git a/src/http_htx.c b/src/http_htx.c index d4fdd0705..c9d01aac8 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -591,6 +591,63 @@ int http_append_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const st return 0; } +/* Prepend new value before value in header + * if is not first value (at least one value exists): + * - ',' delimiter is added after is prepended + * + * ctx is updated to point to new value + * + * Returns 1 on success and 0 on failure. + */ +int http_prepend_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data) +{ + char *start; + struct htx_blk *blk = ctx->blk; + struct ist v; + uint32_t off = 0; + uint8_t first = 0; + + if (!blk) + goto fail; + + v = htx_get_blk_value(htx, blk); + + if (!istlen(v)) { + start = v.ptr; + first = 1; + } + if (unlikely(!istlen(ctx->value))) + goto fail; /* invalid: value is empty, not supported */ + + if (!first) + start = istptr(ctx->value) - ctx->lws_before; + off = start - v.ptr; + + blk = htx_replace_blk_value(htx, blk, ist2(start, 0), data); + if (!blk) + goto fail; + v = htx_get_blk_value(htx, blk); + + if (first) + goto end; /* header is empty, don't append ',' */ + + start = v.ptr + off + data.len; + + blk = htx_replace_blk_value(htx, blk, ist2(start, 0), ist(",")); + if (!blk) + goto fail; + v = htx_get_blk_value(htx, blk); + + end: + ctx->blk = blk; + ctx->value = ist2(v.ptr + off, data.len); + ctx->lws_before = ctx->lws_after = 0; + + return 1; + fail: + return 0; +} + /* Replaces a part of a header value referenced in the context by * . It returns 1 on success, otherwise it returns 0. The context is * updated if necessary.