base64 blob.decode() default error handling

pyunyh pyunyh at
Tue Nov 5 00:32:16 UTC 2019

On Mon, Nov 04, 2019 at 01:51:25PM +0100, Geoff Simmons wrote:


> @pyunyh, I'm moving this to varnish-misc, which is the more appropriate
> list for a user question like this.

Thanks for correcting me. Subscribed to varnish-misc@

> This is a general issue with VCL failure -- in vcl_synth, you can tell
> from resp.reason=="VCL failed" that it was VCL failure that you got you
> there, but there is little to no information about what caused the
> failure, so it can be difficult to impossible to implement specific
> error handling.
> I can see why you need this for the vmod blob use case. But I would
> suggest that the Varnish dev team consider a general solution for
> identifying the cause of a VCL failure, rather than special-casing a
> solution for the vmod.
> @pyunyh, as a workaround you might go to the old trick of using a
> request header as a variable:
> # assuming that req.http.X-Sec-WebSocket-Key-Validated is not set
> # at this point, or not set to "true"
> if (blob.length(blob.decode(BASE64, 0, req.http.Sec-WebSocket-Key)) != 16) {
>         return (synth(400, "Bad Request"));
> }
> set req.http.X-Sec-WebSocket-Key-Validated = "true";
> # now in vcl_synth:
> if (resp.reason == "VCL failed"
>     && req.http.X-Sec-WebSocket-Key-Validated != "true") {
> 	set resp.status = 400;
> 	set resp.reason = "Bad Request";
> }

That approach was the first one in my experiments and it didn't
work.  It seems there are two paths here. One is voluntary synth()
call in VCL and the other is indirect call via unconditional
'return (fail)'.  Header variable tricks works for the former case
only.  If there was an decoding or memory related error in blob it
appears to trigger internal 'return (fail)' which in turn have an
effect of resetting all header variables with std.rollback().  So
there are *NO* header variables available in this case.

The half-working and ugly code I have looks like the following.

sub vcl_synth {

        if (resp.status == 503 && resp.reason == "VCL failed") {
                if (req.method == "GET" &&
                    req.proto == "HTTP/1.1" &&
                    req.http.Upgrade &&
                    ... other conditions ...
                    req.http.Sec-WebSocket-Key &&
                    req.url ~ "^/path/to/WebSocket") {
                        set resp.status = 400;

Unfortunately this does not work as req.url points to original URL
such that it nullifies URL rewrting rules that were applied.


More information about the varnish-misc mailing list