With this change, http_RemoveHdrToken also removes any values of an element
token seperated by equals (like foo=bar)

phk, does this work for you?

Thanks, Nils
>From ed60be21f4a4af6bb69d05c810aa2adf5c4ecbd5 Mon Sep 17 00:00:00 2001
From: Nils Goroll <[email protected]>
Date: Wed, 17 Sep 2014 18:39:09 +0200
Subject: [PATCH 1/2] Add a function to remove an element/token from a header
 value (like Accept-Encoding from Vary)

---
 bin/varnishd/cache/cache.h      |  2 +
 bin/varnishd/cache/cache_http.c | 96 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 98 insertions(+)

diff --git a/bin/varnishd/cache/cache.h b/bin/varnishd/cache/cache.h
index b4e79c4..7b28418 100644
--- a/bin/varnishd/cache/cache.h
+++ b/bin/varnishd/cache/cache.h
@@ -884,6 +884,8 @@ void http_Teardown(struct http *ht);
 int http_GetHdr(const struct http *hp, const char *hdr, char **ptr);
 int http_GetHdrToken(const struct http *hp, const char *hdr,
     const char *token, char **ptr);
+int http_RemoveHdrToken(struct http *hp, const char *hdr,
+    const char *token);
 int http_GetHdrField(const struct http *hp, const char *hdr,
     const char *field, char **ptr);
 double http_GetHdrQ(const struct http *hp, const char *hdr, const char *field);
diff --git a/bin/varnishd/cache/cache_http.c b/bin/varnishd/cache/cache_http.c
index 031b7dd..fd42914 100644
--- a/bin/varnishd/cache/cache_http.c
+++ b/bin/varnishd/cache/cache_http.c
@@ -460,6 +460,102 @@ http_GetHdrToken(const struct http *hp, const char *hdr,
 	return (0);
 }
 
+/*-----------------------------------------------------------------------------
+ * Remove a given data element (token) from a header
+ *
+ * return 1 if header was changed, 0 otherwise
+ */
+
+int
+http_RemoveHdrToken(struct http *hp, const char *hdr,
+    const char *token)
+{
+	char *bp, *tp, *ep, *n, *w;
+	unsigned bl, tl, el, hdrl, l;
+
+	if (! (http_GetHdr(hp, hdr, &bp) &&
+		http_GetHdrToken(hp, hdr, token, &tp)))
+		return (0);
+
+	/* GetHdrToken returns a pointer to the next char after the token */
+	tl = strlen(token);
+	tp -= tl;
+
+	/* skip initial whitespace and commas */
+	while (vct_islws(*bp) || *bp == ',')
+		bp++;
+
+	assert(tp >= bp);
+
+	ep = &tp[tl];
+
+	/* if the token contains a value, skip it */
+	if (*ep == '=')
+		while (*ep && (! (vct_islws(*ep) || *ep == ',')))
+			ep++;
+
+	/* move ep to the next token after the token to be removed */
+	while (vct_islws(*ep) || *ep == ',')
+		ep++;
+
+	bl = (tp - bp);
+	el = strlen(ep);
+
+	if (bl == 0 && el == 0) {
+		/* nothing but the token to be removed */
+		http_Unset(hp, hdr);
+		return (1);
+	}
+
+	if (el == 0) {
+		/* nothing at the end - remove separating whitespace/comma */
+		while (vct_islws(bp[bl - 1]) || bp[bl - 1] == ',')
+			bl--;
+		assert(bl > 0);
+	}
+
+	hdrl = strlen(hdr) - 1;
+	l  = hdrl + 1 + bl + el + 1;
+
+	if (WS_Reserve(hp->ws, l) < l) {
+		http_fail(hp);
+		VSLb(hp->vsl, SLT_LostHeader, hdr);
+		WS_Release(hp->ws, 0);
+		return (0);
+	}
+
+	n = w = hp->ws->f;
+
+	memcpy(w, hdr + 1, hdrl);
+	w += hdrl;
+	*w++ = ' ';
+
+	if (bl) {
+		memcpy(w, bp, bl);
+		w += bl;
+	}
+
+	if (el)	{
+		memcpy(w, ep, el);
+		w += el;
+	}
+
+	*w++ = '\0';
+
+	assert((w - hp->ws->f) == l);
+	WS_Release(hp->ws, l);
+
+	http_Unset(hp, hdr);
+	http_SetHeader(hp, n);
+
+	/*
+	 * strictly speaking we could still loose the header in SetHeader, but
+	 * this is unlikely and we cannot check
+	 */
+	return (1);
+}
+
+
 /*--------------------------------------------------------------------
  * Find a given headerfields Q value.
  */
-- 
2.0.1

_______________________________________________
varnish-dev mailing list
[email protected]
https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev

Reply via email to