[master] 2eb352d2b Fix the behavior of `set BODY = STRING;`

Dridi Boukelmoune dridi.boukelmoune at gmail.com
Mon Dec 2 12:14:07 UTC 2019


commit 2eb352d2bc4f07518a17bce8108c7ab89e24e4da
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date:   Thu Nov 7 10:12:03 2019 +0100

    Fix the behavior of `set BODY = STRING;`
    
    Multiple calls to the synthetic() function result in the accumulation of
    all body parts. The ability to set a [be]resp body accidentally resulted
    in the same behavior.
    
    In other words writing `set resp.body = "string";` in VCL behaves as if
    `set resp.body += "string";` was written instead. This patch introduces
    an enum to distinguish between the two desired actions and enables both
    syntaxes without touching the behavior of the synthetic() function.

diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c
index 7ed80cfd6..3a06d16a4 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -880,13 +880,17 @@ VRT_r_resp_do_esi(VRT_CTX)
 
 #define VRT_BODY_L(which)					\
 VCL_VOID							\
-VRT_l_##which##_body(VRT_CTX, const char *str, ...)		\
+VRT_l_##which##_body(VRT_CTX, enum lbody_e type,		\
+    const char *str, ...)					\
 {								\
 	va_list ap;						\
 	const char *p;						\
 	struct vsb *vsb;					\
 								\
 	CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC);	\
+	assert(type == LBODY_SET || type == LBODY_ADD);		\
+	if (type == LBODY_SET)					\
+		VSB_clear(vsb);					\
 	va_start(ap, str);					\
 	p = str;						\
 	while (p != vrt_magic_string_end) {			\
diff --git a/bin/varnishtest/tests/r03079.vtc b/bin/varnishtest/tests/r03079.vtc
index 5da83f91f..3b2f57204 100644
--- a/bin/varnishtest/tests/r03079.vtc
+++ b/bin/varnishtest/tests/r03079.vtc
@@ -1,4 +1,6 @@
-varnishtest "set VCL_??? += VCL_STRING;"
+varnishtest "set VCL_??? [+]= VCL_???;"
+
+# set STRING|HEADER += STRINGS;
 
 server s1 {
 	rxreq
@@ -23,3 +25,53 @@ client c1 {
 	expect resp.status == 200
 	expect resp.http.x-powered-by == varnishtest1002
 } -run
+
+# set BODY [+]= STRINGS;
+
+varnish v1 -vcl {
+	import blob;
+	backend be none;
+	sub vcl_recv {
+		return (synth(200));
+	}
+	sub vcl_synth {
+		if (req.url ~ "synth") {
+			synthetic("hello");
+			if (req.url ~ "add") {
+				synthetic("world");
+			}
+		}
+		if (req.url ~ "string") {
+			set resp.body = "hello";
+			if (req.url ~ "reset") {
+				set resp.body = "world";
+			}
+			if (req.url ~ "add") {
+				set resp.body += "world";
+			}
+		}
+		return (deliver);
+	}
+}
+
+client c1 {
+	txreq -url "/synth"
+	rxresp
+	expect resp.body == hello
+
+	txreq -url "/synth/add"
+	rxresp
+	expect resp.body == helloworld
+
+	txreq -url "/string"
+	rxresp
+	expect resp.body == hello
+
+	txreq -url "/string/reset"
+	rxresp
+	expect resp.body == world
+
+	txreq -url "/string/add"
+	rxresp
+	expect resp.body == helloworld
+} -run
diff --git a/include/vrt.h b/include/vrt.h
index 863e60f65..5e2543e1c 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -55,6 +55,8 @@
  *	Changed type of vsa_suckaddr_len from int to size_t
  *	New prefix_{ptr|len} fields in vrt_backend
  *	VRT_HashStrands32() added
+ *	VRT_l_resp_body() changed
+ *	VRT_l_beresp_body() changed
  * 10.0 (2019-09-15)
  *	VRT_UpperLowerStrands added.
  *	VRT_synth_page now takes STRANDS argument
@@ -264,6 +266,11 @@ struct vrt_type {
 	size_t				szof;
 };
 
+enum lbody_e {
+	LBODY_SET,
+	LBODY_ADD,
+};
+
 /***********************************************************************
  * This is the composite argument we pass to compiled VCL and VRT
  * functions.
diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py
index d662375fd..83af5c925 100755
--- a/lib/libvcc/generate.py
+++ b/lib/libvcc/generate.py
@@ -216,10 +216,12 @@ class vardef(object):
         elif self.wr:
             fo.write('\tsym->lname = "VRT_l_%s(ctx, ";\n' % cnam)
             s = "void VRT_l_%s(VRT_CTX, " % cnam
-            if self.typ != "STRING" and self.typ != "BODY":
-                s += "VCL_" + self.typ + ")"
-            else:
+            if self.typ == "STRING":
                 s += ctyp.c + ", ...)"
+            elif self.typ == "BODY":
+                s += "enum lbody_e, " + ctyp.c + ", ...)"
+            else:
+                s += "VCL_" + self.typ + ")"
             varproto(s)
         fo.write("\tsym->w_methods =\n")
         restrict(fo, self.wr)
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
index 5899b2b30..7a539fa58 100644
--- a/lib/libvcc/vcc_action.c
+++ b/lib/libvcc/vcc_action.c
@@ -84,7 +84,8 @@ static const struct assign {
 	{ STRING,	'=',		STRING_LIST },
 	{ HEADER,	T_INCR,		STRING_LIST, "VRT_GetHdr(ctx, \v),\n" },
 	{ HEADER,	'=',		STRING_LIST },
-	{ BODY,		'=',		STRING_LIST },
+	{ BODY,		'=',		STRING_LIST, "LBODY_SET,\n" },
+	{ BODY,		T_INCR,		STRING_LIST, "LBODY_ADD,\n" },
 	{ VOID,		'=',		VOID }
 };
 


More information about the varnish-commit mailing list