...
 
Commits (2)
......@@ -323,6 +323,24 @@ Example::
synth_body.synth();
}
.. _xreader.blob():
BLOB xreader.blob()
-------------------
Return the file's contents as a BLOB. Invokes VCL failure if the most
recent update check encountered an error.
Example::
import blob;
# Set the backend response body to the hex-encoded contents of
# the file. Also works for resp.body in vcl_synth.
sub vcl_backend_error {
set beresp.body = blob.encode(HEX, blob=synth_body.blob());
}
.. _reader.error():
.. _xreader.error():
......
# looks like -*- vcl -*-
varnishtest "reader.blob()"
shell {echo -n "foo bar baz quux" > ${tmpdir}/blob}
varnish v1 -vcl {
import ${vmod_file};
import blob;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
new rdr = file.reader("${tmpdir}/blob", ttl=0.1s);
}
sub vcl_recv {
set req.http.Blob = blob.encode(blob=rdr.blob());
return (synth(200));
}
sub vcl_synth {
set resp.http.Blob = req.http.Blob;
return (deliver);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Blob == "foo bar baz quux"
} -run
shell {echo -n "quux baz bar foo" > ${tmpdir}/blob}
delay .1
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.Blob == "quux baz bar foo"
} -run
shell {chmod a-r ${tmpdir}/blob}
delay .1
client c1 {
txreq
rxresp
expect resp.status == 503
expect resp.reason == "VCL failed"
} -run
logexpect l1 -v v1 -d 1 -g vxid -q "VCL_Error" {
expect 0 * Begin req
expect * = VCL_Error {^rdr\.blob\(\): vmod file failure: vcl1\.rdr: cannot open}
expect * = End
} -run
......@@ -55,6 +55,9 @@
snprintf((rdr)->errbuf, (rdr)->errlen, "vmod file failure: " fmt, \
__VA_ARGS__)
/* Other VMODs may check the result of .blob() for this value, see vrt.h */
#define VMOD_FILE_BLOB_MAGIC 0x069392c4
#define INIT_SLEEP_INTERVAL 0.001
#define ERRMSG_LEN 128
#define NO_ERR ("No error")
......@@ -546,6 +549,40 @@ vmod_reader_synth(VRT_CTX, struct VPFX(file_reader) *rdr)
return;
}
VCL_BLOB
vmod_reader_blob(VRT_CTX, struct VPFX(file_reader) *rdr)
{
struct vrt_blob *blob;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(rdr, FILE_READER_MAGIC);
CHECK_OBJ_NOTNULL(rdr->info, FILE_INFO_MAGIC);
if (WS_ReserveSize(ctx->ws, sizeof(*blob)) == 0) {
VRT_fail(ctx, "%s.blob(): cannot reserve workspace",
rdr->obj_name);
return (NULL);
}
blob = (struct vrt_blob *)WS_Front(ctx->ws);
blob->type = VMOD_FILE_BLOB_MAGIC;
AZ(pthread_rwlock_rdlock(&rdr->lock));
if (rdr->flags & RDR_ERROR) {
VRT_fail(ctx, "%s.blob(): %s", rdr->obj_name, rdr->errbuf);
AZ(pthread_rwlock_unlock(&rdr->lock));
AN(strcmp(rdr->errbuf, NO_ERR));
WS_Release(ctx->ws, 0);
return (NULL);
}
blob->blob = rdr->addr;
blob->len = rdr->info->len - 1;
AZ(pthread_rwlock_unlock(&rdr->lock));
WS_Release(ctx->ws, sizeof(*blob));
return (blob);
}
VCL_BOOL
vmod_reader_error(VRT_CTX, struct VPFX(file_reader) *rdr)
{
......@@ -659,6 +696,7 @@ VPFX(event)(VRT_CTX, struct vmod_priv *priv, enum vcl_event_e e)
VSLIST_REMOVE_HEAD(th, list);
FREE_OBJ(ent);
}
free(th);
return (0);
case VCL_EVENT_WARM:
VSLIST_FOREACH(ent, th, list) {
......
......@@ -303,6 +303,21 @@ Example::
synth_body.synth();
}
$Method BLOB .blob()
Return the file's contents as a BLOB. Invokes VCL failure if the most
recent update check encountered an error.
Example::
import blob;
# Set the backend response body to the hex-encoded contents of
# the file. Also works for resp.body in vcl_synth.
sub vcl_backend_error {
set beresp.body = blob.encode(HEX, blob=synth_body.blob());
}
.. _reader.error():
$Method BOOL .error()
......