Skip to content
Permalink
Browse files

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.
  • Loading branch information...
Dridi committed Nov 7, 2019
1 parent 2a5db07 commit 2eb352d2bc4f07518a17bce8108c7ab89e24e4da
Showing with 72 additions and 6 deletions.
  1. +5 −1 bin/varnishd/cache/cache_vrt_var.c
  2. +53 −1 bin/varnishtest/tests/r03079.vtc
  3. +7 −0 include/vrt.h
  4. +5 −3 lib/libvcc/generate.py
  5. +2 −1 lib/libvcc/vcc_action.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) { \
@@ -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
@@ -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.
@@ -216,10 +216,12 @@ def emit(self):
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)
@@ -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 }
};

0 comments on commit 2eb352d

Please sign in to comment.
You can’t perform that action at this time.