Hello all, We're presently testing an upgrade from Varnish 3.0.3 to 3.0.6, and have encountered a change in the semantics of a header evaluated in boolean context after the header has been set to NULL by a VMOD.
The attached VTC test passes on 3.0.3 and fails on 3.0.6.
The VMOD in question is header, but I suspect the same thing will happen
with any VMOD that returns NULL for a STRING return type.
Ordinarily, if a header does not exist, then the bare header expression
evaluates to false in boolean context:
# This condition is false if there is no request header Foo
if (req.http.Foo) {
/* do stuff ... */
}
A VMOD may return NULL for a function whose return type is STRING;
header.get() does this if it does not find a header named in the first
arg that matches the expression in the second arg:
# header.get() returns NULL if there is no Cookie header that matches
# "bar"
import header;
set req.http.X-Bar-Cookie = header.get(req.http.Cookie, "bar");
If that happens in Varnish 3.0.3, then the header set on the LHS of the
assignment evaluates to false in boolean context, but it evaluates to
true in Varnish 3.0.6:
# if req.http.X-Bar-Cookie was set to NULL above,
# then this condition is false in 3.0.3, but true in 3.0.6
if (req.http.X-Bar-Cookie) {
/* do stuff ... */
}
A workaround is to match the header against the one-char/any-char regex:
# if req.http.X-Bar-Cookie was set to NULL above,
# then this condition is false in both 3.0.3 and 3.0.6
if (req.http.X-Bar-Cookie ~ ".") {
/* do stuff ... */
}
But it's wasteful to have to turn on the regex matcher just to check for
the existence of a header.
I don't see anything about this in the change logs between 3.0.3 and
3.0.6, and haven't had a chance to look through changes in source to
spot what causes the difference. Of course my guess may be wrong, and
this is just an issue with the header VMOD; but it seems more likely to
be an unintentional change in the meaning of NULL in VRT.
@devs: Should I file a trac ticket?
Sorry that I don't have an example with 4.x yet (because I'm having
trouble getting the header VMOD to build with 4.x; and in any case, it
would be a different implementation of the VMOD then).
Best,
Geoff
--
** * * UPLEX - Nils Goroll Systemoptimierung
Scheffelstraße 32
22301 Hamburg
Tel +49 40 2880 5731
Mob +49 176 636 90917
Fax +49 40 42949753
http://uplex.de
varnishtest "Non-existent header returned from header.get()"
server s1 {
rxreq
expect req.url == "/"
txresp -hdr "Bar: baz"
} -start
varnish v1 -vcl+backend {
import header;
sub vcl_deliver {
if (req.http.X-Foo ~ ".") {
set resp.http.X-Match-Foo = "true";
}
else {
set resp.http.X-Match-Foo = "false";
}
if (req.http.X-Foo) {
set resp.http.X-Boolean-Foo = "true";
}
else {
set resp.http.X-Boolean-Foo = "false";
}
set req.http.X-Quux = header.get(req.http.Bar, "quux");
if (req.http.X-Quux ~ ".") {
set resp.http.X-Match-Quux = "true";
}
else {
set resp.http.X-Match-Quux = "false";
}
if (req.http.X-Quux) {
set resp.http.X-Boolean-Quux = "true";
}
else {
set resp.http.X-Boolean-Quux = "false";
}
return(deliver);
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.status == 200
expect resp.http.X-Foo == <undef>
expect resp.http.X-Match-Foo == "false"
expect resp.http.X-Boolean-Foo == "false"
expect resp.http.Bar == "baz"
expect resp.http.X-Quux == <undef>
expect resp.http.X-Match-Quux == "false"
expect resp.http.X-Boolean-Quux == "false"
} -run
signature.asc
Description: OpenPGP digital signature
_______________________________________________ varnish-misc mailing list [email protected] https://www.varnish-cache.org/lists/mailman/listinfo/varnish-misc
