From: Aurelien DARRAGON Date: Wed, 28 Dec 2022 10:21:31 +0000 (+0100) Subject: MINOR: http_htx: add http_append_header() to append value to header X-Git-Tag: v2.8-dev3~78 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a5a8552cabd05dc2fd3ffac09d33337f1c1807b6;p=thirdparty%2Fhaproxy.git MINOR: http_htx: add http_append_header() to append value to header Calling this function as an alternative to http_replace_header_value() to append a new value to existing header instead of replacing the whole header content. If the header already contains one or multiple values: a ',' is automatically appended before the new value. This function is not meant for prepending (providing empty ctx value), in which case we should consider implementing dedicated prepend alternative function. --- diff --git a/include/haproxy/http_htx.h b/include/haproxy/http_htx.h index 71f56bc15b..47f533640e 100644 --- a/include/haproxy/http_htx.h +++ b/include/haproxy/http_htx.h @@ -50,6 +50,7 @@ int http_replace_req_path(struct htx *htx, const struct ist path, int with_qs); 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_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 58b24183f9..d4fdd0705b 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -537,6 +537,60 @@ int http_replace_res_reason(struct htx *htx, const struct ist reason) return http_replace_stline(htx, vsn, status, reason); } +/* Append new value after value in header + * if header is not empty (at least one value exists): + * - ',' delimiter is added before is appended + * - must be valid and must point to an existing value, + * else it is an error and prepend_value should be used instead. + * + * ctx is updated to point to new value + * + * Returns 1 on success and 0 on failure. + */ +int http_append_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; + + if (!blk) + goto fail; + + v = htx_get_blk_value(htx, blk); + + if (!istlen(v)) { + start = v.ptr; + goto empty; /* header is empty, append without ',' */ + } + if (unlikely(!istlen(ctx->value))) + goto fail; /* invalid: value is empty, not supported */ + + start = istend(ctx->value) + ctx->lws_after; + off = start - v.ptr; + + blk = htx_replace_blk_value(htx, blk, ist2(start, 0), ist(",")); + if (!blk) + goto fail; + off += 1; /* add 1 for ',' */ + v = htx_get_blk_value(htx, blk); + start = v.ptr + off; + + empty: + blk = htx_replace_blk_value(htx, blk, ist2(start, 0), data); + if (!blk) + goto fail; + v = htx_get_blk_value(htx, blk); + + 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.