]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http_htx: add http_append_header() to append value to header
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 28 Dec 2022 10:21:31 +0000 (11:21 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 27 Jan 2023 14:18:59 +0000 (15:18 +0100)
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.

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

index 71f56bc15b91934b01191ecf469fb45997123a73..47f533640e0aaa469bd93ec92e766fb28eed4516 100644 (file)
@@ -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);
index 58b24183f98ccb771a66fbf1a50d6b8e13210a91..d4fdd0705bdf80fb668d3d188e3387c3eb80ecc2 100644 (file)
@@ -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 <data> after <ctx> value in header
+ * if header is not empty (at least one value exists):
+ *   - ',' delimiter is added before <data> is appended
+ *   - <ctx> 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 <ctx> by
  * <data>. It returns 1 on success, otherwise it returns 0. The context is
  * updated if necessary.