]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http_htx: add http_prepend_header() to prepend value to header
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 5 Jan 2023 16:02:19 +0000 (17:02 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 27 Jan 2023 14:18:59 +0000 (15:18 +0100)
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
src/http_htx.c

index 47f533640e0aaa469bd93ec92e766fb28eed4516..3d01a061f1c8e8646965687c89902b0f3a4eedc2 100644 (file)
@@ -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);
index d4fdd0705bdf80fb668d3d188e3387c3eb80ecc2..c9d01aac8db1ff25955ced841858ef06145f38c7 100644 (file)
@@ -591,6 +591,63 @@ int http_append_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const st
        return 0;
 }
 
+/* Prepend new value <data> before <ctx> value in header
+ * if <ctx> is not first value (at least one value exists):
+ *   - ',' delimiter is added after <data> 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 <ctx> by
  * <data>. It returns 1 on success, otherwise it returns 0. The context is
  * updated if necessary.