[master] cb446a38d vcc: set BODY [+]= STRINGS|BLOB
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Tue Dec 7 06:51:06 UTC 2021
commit cb446a38d75c7768b5c5f7b4330f45d69375ba4a
Author: Dridi Boukelmoune <dridi.boukelmoune at gmail.com>
Date: Mon Nov 29 18:35:57 2021 +0100
vcc: set BODY [+]= STRINGS|BLOB
This reuses the stringform concept and introduces a similar bodyform
flag for STRINGS and BLOB types. We can now assign either a STRING or
a BLOB to [be]resp.body, without breaking the VRT ABI and API. In fact,
the VRT API now uses a void* C type for the BODY VCL type and finds
which type to use based on enum lbody_e.
The enum completely changed but macros were added to maintain the API,
and because of this change, enum lbody_e literals are formatted in two
steps. As a result the BODY type grew another noindent flag. It prevents
the insertion of white space between the LBODY_{ADD,SET}_ prefix and the
type name suffix (BLOB or STRANDS).
diff --git a/bin/varnishd/cache/cache_vrt_var.c b/bin/varnishd/cache/cache_vrt_var.c
index 64b7257d4..d80b96526 100644
--- a/bin/varnishd/cache/cache_vrt_var.c
+++ b/bin/varnishd/cache/cache_vrt_var.c
@@ -965,17 +965,29 @@ VRT_r_resp_do_esi(VRT_CTX)
#define VRT_BODY_L(which) \
VCL_VOID \
VRT_l_##which##_body(VRT_CTX, enum lbody_e type, \
- const char *str, VCL_STRANDS s) \
+ const char *str, VCL_BODY body) \
{ \
int n; \
struct vsb *vsb; \
+ VCL_STRANDS s; \
+ VCL_BLOB b; \
\
+ CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); \
+ AN(body); \
CAST_OBJ_NOTNULL(vsb, ctx->specific, VSB_MAGIC); \
- assert(type == LBODY_SET || type == LBODY_ADD); \
- if (type == LBODY_SET) \
+ if (type == LBODY_SET_STRING || type == LBODY_SET_BLOB) \
VSB_clear(vsb); \
+ if (type == LBODY_SET_BLOB || type == LBODY_ADD_BLOB) { \
+ AZ(str); \
+ b = body; \
+ VSB_bcat(vsb, b->blob, b->len); \
+ return; \
+ } \
if (str != NULL) \
VSB_cat(vsb, str); \
+ assert(type == LBODY_SET_STRING || \
+ type == LBODY_ADD_STRING); \
+ s = body; \
for (n = 0; s != NULL && n < s->n; n++) \
if (s->p[n] != NULL) \
VSB_cat(vsb, s->p[n]); \
diff --git a/bin/varnishtest/tests/r03079.vtc b/bin/varnishtest/tests/r03079.vtc
index 3b2f57204..22da633ac 100644
--- a/bin/varnishtest/tests/r03079.vtc
+++ b/bin/varnishtest/tests/r03079.vtc
@@ -26,7 +26,7 @@ client c1 {
expect resp.http.x-powered-by == varnishtest1002
} -run
-# set BODY [+]= STRINGS;
+# set BODY [+]= STRINGS|BLOB;
varnish v1 -vcl {
import blob;
@@ -50,11 +50,20 @@ varnish v1 -vcl {
set resp.body += "world";
}
}
+ if (req.url ~ "blob") {
+ set resp.body = blob.decode(HEX, encoded="1100");
+ if (req.url ~ "reset") {
+ set resp.body = blob.decode(HEX, encoded="221100");
+ }
+ if (req.url ~ "add") {
+ set resp.body += blob.decode(HEX, encoded="221100");
+ }
+ }
return (deliver);
}
}
-client c1 {
+client c2 {
txreq -url "/synth"
rxresp
expect resp.body == hello
@@ -74,4 +83,16 @@ client c1 {
txreq -url "/string/add"
rxresp
expect resp.body == helloworld
+
+ txreq -url "/blob"
+ rxresp
+ expect resp.bodylen == 2
+
+ txreq -url "/blob/reset"
+ rxresp
+ expect resp.bodylen == 3
+
+ txreq -url "/blob/add"
+ rxresp
+ expect resp.bodylen == 5
} -run
diff --git a/doc/sphinx/reference/vmod.rst b/doc/sphinx/reference/vmod.rst
index 84283745f..10460cd7b 100644
--- a/doc/sphinx/reference/vmod.rst
+++ b/doc/sphinx/reference/vmod.rst
@@ -302,6 +302,13 @@ BLOB
An opaque type to pass random bits of memory between VMOD
functions.
+BODY
+ C-type: ``const void *``
+
+ A type only used on the LHS of an assignment that can take
+ either a blob or an expression that can be converted to a
+ string.
+
BOOL
C-type: ``unsigned``
diff --git a/include/vrt.h b/include/vrt.h
index a47250255..f7a1d31e1 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -56,6 +56,14 @@
* Next (2021-03-15)
* VRT_Assign_Backend added
* VRT_StaticDirector added
+ * enum lbody_e changed
+ * - previous enum lbody_e values are defined as macros
+ * The following functions changed to take `const char *, BODY`:
+ * - VRT_l_beresp_body()
+ * - VRT_l_resp_body()
+ * BODY can either be a BLOB or a STRANDS, but only a STRANDS
+ * can take a non-NULL const char * prefix. The changes to BODY
+ * assignments doesn't break the ABI or the API.
*
* 14.0 (2021-09-15)
* VIN_n_Arg() no directly returns the directory name.
@@ -328,7 +336,7 @@ extern const struct vrt_blob *vrt_null_blob;
typedef const struct vrt_acl * VCL_ACL;
typedef const struct director * VCL_BACKEND;
typedef const struct vrt_blob * VCL_BLOB;
-typedef const char * VCL_BODY;
+typedef const void * VCL_BODY;
typedef unsigned VCL_BOOL;
typedef int64_t VCL_BYTES;
typedef vtim_dur VCL_DURATION;
@@ -615,10 +623,15 @@ VCL_STRING VRT_GetHdr(VRT_CTX, VCL_HEADER);
*/
enum lbody_e {
- LBODY_SET,
- LBODY_ADD,
+ LBODY_SET_STRING,
+ LBODY_ADD_STRING,
+ LBODY_SET_BLOB,
+ LBODY_ADD_BLOB,
};
+#define LBODY_SET LBODY_SET_STRING
+#define LBODY_ADD LBODY_ADD_STRING
+
VCL_BYTES VRT_CacheReqBody(VRT_CTX, VCL_BYTES maxsize);
VCL_STRING VRT_ban_string(VRT_CTX, VCL_STRING);
diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py
index a2b318ba8..c50194348 100755
--- a/lib/libvcc/generate.py
+++ b/lib/libvcc/generate.py
@@ -219,7 +219,7 @@ class vardef(object):
if self.typ == "STRING":
s += ctyp.c + ", VCL_STRANDS)"
elif self.typ == "BODY":
- s += "enum lbody_e, " + ctyp.c + ", VCL_STRANDS)"
+ s += "enum lbody_e, const char *, " + ctyp.c + ")"
else:
s += "VCL_" + self.typ + ")"
varproto(s)
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
index 0ed675da6..f7c2ce29f 100644
--- a/lib/libvcc/vcc_action.c
+++ b/lib/libvcc/vcc_action.c
@@ -121,8 +121,8 @@ static const struct assign {
{ STRING, '=', STRANDS, "0,\n" },
{ HEADER, T_INCR, STRANDS, "VRT_GetHdr(ctx, \v),\n" },
{ HEADER, '=', STRANDS, "0,\n" },
- { BODY, '=', STRANDS, "LBODY_SET, 0,\n" },
- { BODY, T_INCR, STRANDS, "LBODY_ADD, 0,\n" },
+ { BODY, '=', BODY, "LBODY_SET_" },
+ { BODY, T_INCR, BODY, "LBODY_ADD_" },
{ VOID, '=', VOID }
};
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index 6ce150c4c..76b2cab73 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -119,6 +119,8 @@ struct type {
const char *tostring;
vcc_type_t multype;
int stringform;
+ int bodyform;
+ int noindent;
};
#define VCC_TYPE(UC, lc) extern const struct type UC[1];
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index bc9864d29..0805f9340 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -237,8 +237,10 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
char *p;
int i;
- for (i = 0; i < ind; i++)
- VSB_cat(d, " ");
+ if (!e1->fmt->noindent) {
+ for (i = 0; i < ind; i++)
+ VSB_putc(d, ' ');
+ }
p = VSB_data(e1->vsb);
while (*p != '\0') {
if (*p == '\n') {
@@ -246,7 +248,7 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
if (*++p == '\0')
break;
for (i = 0; i < ind; i++)
- VSB_cat(d, " ");
+ VSB_putc(d, ' ');
} else if (*p != '\v') {
VSB_putc(d, *p++);
} else {
@@ -1417,6 +1419,8 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
vcc_expr_cor(tl, e, fmt);
ERRCHK(tl);
+ assert((*e)->fmt != BODY);
+
if ((*e)->fmt == fmt)
return;
@@ -1431,6 +1435,18 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
return;
}
+ if (fmt == BODY && !(*e)->fmt->bodyform)
+ vcc_expr_tostring(tl, e, STRINGS);
+
+ if (fmt == BODY && (*e)->fmt->bodyform) {
+ if ((*e)->fmt == STRINGS)
+ *e = vcc_expr_edit(tl, BODY, "STRING, 0, \vT", *e, NULL);
+ else if ((*e)->fmt == BLOB)
+ *e = vcc_expr_edit(tl, BODY, "BLOB, 0, \v1", *e, NULL);
+ else
+ WRONG("Unhandled bodyform");
+ }
+
if ((*e)->fmt == STRINGS && fmt->stringform) {
if (fmt == STRING)
*e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c
index 829bb2c2e..cfa6714b3 100644
--- a/lib/libvcc/vcc_types.c
+++ b/lib/libvcc/vcc_types.c
@@ -78,12 +78,14 @@ const struct type BACKEND[1] = {{
const struct type BLOB[1] = {{
.magic = TYPE_MAGIC,
.name = "BLOB",
+ .bodyform = 1,
.tostring = "VRT_BLOB_string(ctx, \v1)",
}};
const struct type BODY[1] = {{
.magic = TYPE_MAGIC,
.name = "BODY",
+ .noindent = 1,
}};
const struct type BOOL[1] = {{
@@ -199,6 +201,7 @@ const struct type STRINGS[1] = {{
.magic = TYPE_MAGIC,
.name = "STRINGS",
.methods = strings_methods,
+ .bodyform = 1,
.tostring = "",
}};
More information about the varnish-commit
mailing list