From 0b1202374424f03441d9bc2599a55b11fd3b85f1 Mon Sep 17 00:00:00 2001 From: phk Date: Sat, 24 Jan 2009 10:36:46 +0000 Subject: [PATCH] Implement the new-purge case where the entire expression comes from VCL. It is possible to instigate purges two ways from VCL now: sub vcl_recv { # Purge the req.url if (req.request == "PURGE") { purge (req.url == req.url); error 410; } # Take entire purge instruction from "Purge:" header if (req.request == "PURGESTR") { purge ("" req.http.purge); error 410; } Testcase for this. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3542 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache_vrt.c | 50 ++++++ .../bin/varnishtest/tests/c00022.vtc | 162 ++++++++++++++++++ varnish-cache/include/vrt.h | 1 + varnish-cache/lib/libvcl/vcc_action.c | 2 +- varnish-cache/lib/libvcl/vcc_fixed_token.c | 9 +- 5 files changed, 219 insertions(+), 5 deletions(-) create mode 100644 varnish-cache/bin/varnishtest/tests/c00022.vtc diff --git a/varnish-cache/bin/varnishd/cache_vrt.c b/varnish-cache/bin/varnishd/cache_vrt.c index 120c9c2a..e2fd9eef 100644 --- a/varnish-cache/bin/varnishd/cache_vrt.c +++ b/varnish-cache/bin/varnishd/cache_vrt.c @@ -788,11 +788,61 @@ VRT_purge(struct sess *sp, char *cmds, ...) good = 1; } if (!good) + /* XXX: report error how ? */ BAN_Free(b); else BAN_Insert(b); } +/*--------------------------------------------------------------------*/ + +void +VRT_purge_string(struct sess *sp, char *str, ...) +{ + char *p, *a1, *a2, *a3; + char **av; + va_list ap; + struct ban *b; + int good; + int i; + + va_start(ap, str); + p = vrt_assemble_string(sp->http, NULL, str, ap); + if (p == NULL) + /* XXX: report error how ? */ + return; + + av = ParseArgv(p, 0); + if (av[0] != NULL) { + /* XXX: report error how ? */ + FreeArgv(av); + return; + } + b = BAN_New(); + good = 0; + for (i = 1; ; i += 3) { + a1 = av[i]; + if (a1 == NULL) + break; + good = 0; + a2 = av[i + 1]; + if (a2 == NULL) + break; + a3 = av[i + 2]; + if (a3 == NULL) + break; + if (BAN_AddTest(NULL, b, a1, a2, a3)) + break; + good = 1; + } + if (!good) + /* XXX: report error how ? */ + BAN_Free(b); + else + BAN_Insert(b); + FreeArgv(av); +} + /*-------------------------------------------------------------------- * Simple stuff */ diff --git a/varnish-cache/bin/varnishtest/tests/c00022.vtc b/varnish-cache/bin/varnishtest/tests/c00022.vtc new file mode 100644 index 00000000..d8f0b8a7 --- /dev/null +++ b/varnish-cache/bin/varnishtest/tests/c00022.vtc @@ -0,0 +1,162 @@ +# $Id$ + +test "Test banning a url with VCL purge" + +server s1 { + rxreq + expect req.url == "/foo" + txresp -hdr "foo: bar5" -body "1111\n" + + rxreq + expect req.url == "/foo" + txresp -hdr "foo: bar6" -body "11111\n" + + rxreq + expect req.url == "/foo" + txresp -hdr "foo: bar7" -body "111111\n" + + rxreq + expect req.url == "/foo" + txresp -hdr "foo: bar8" -body "1111111\n" +} -start + +varnish v1 -vcl+backend { + sub vcl_recv { + if (req.request == "PURGE") { + purge (req.url == req.url); + error 410; + } + if (req.request == "PURGESTR") { + purge ("" req.http.purge); + error 410; + } + } +} -start + +# Fetch into cache +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar5 + expect resp.bodylen == 5 +} -run + +# Purge something else +client c1 { + txreq -req PURGE -url /foox + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +# Still in cache +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar5 + expect resp.bodylen == 5 +} -run + +# Purge it +client c1 { + txreq -req PURGE -url /foo + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +# New obj +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar6 + expect resp.bodylen == 6 +} -run + +# Purge everything else +client c1 { + txreq -req PURGESTR -hdr "purge=req.url != /foo" + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +# still there +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar6 + expect resp.bodylen == 6 +} -run + +# Purge it +client c1 { + txreq -req PURGESTR -hdr "Purge: obj.http.foo == \"bar6\"" + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +# New one +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar7 + expect resp.bodylen == 7 +} -run + +# Purge something else +client c1 { + txreq -req PURGESTR -hdr "Purge: obj.http.foo == \"bar6\"" + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +# Still there +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar7 + expect resp.bodylen == 7 +} -run + +# Header match +client c1 { + txreq -req PURGESTR -hdr "Purge: req.http.foo == \"barcheck\"" + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +client c1 { + txreq -url "/foo" -hdr "foo: barcheck" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar8 + expect resp.bodylen == 8 +} -run + +# Header match +client c1 { + txreq -req PURGESTR -hdr "Purge: obj.http.foo == \"barcheck\"" + rxresp + expect resp.status == 410 +} -run +varnish v1 -cliok "purge.list" + +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar8 + expect resp.bodylen == 8 +} -run + + diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h index 4569c479..5a0f60dc 100644 --- a/varnish-cache/include/vrt.h +++ b/varnish-cache/include/vrt.h @@ -143,6 +143,7 @@ const char *VRT_regsub(const struct sess *sp, int all, const char *, void VRT_panic(struct sess *sp, const char *, ...); void VRT_purge(struct sess *sp, char *, ...); +void VRT_purge_string(struct sess *sp, char *, ...); void VRT_count(const struct sess *, unsigned); int VRT_rewrite(const char *, const char *); diff --git a/varnish-cache/lib/libvcl/vcc_action.c b/varnish-cache/lib/libvcl/vcc_action.c index 586f4eda..d6dd0c9e 100644 --- a/varnish-cache/lib/libvcl/vcc_action.c +++ b/varnish-cache/lib/libvcl/vcc_action.c @@ -401,7 +401,7 @@ parse_purge(struct tokenlist *tl) do Fb(tl, 0, ", "); while (vcc_StringVal(tl)); - Fb(tl, 0, ", 0);\n"); + Fb(tl, 0, "vrt_magic_string_end);\n"); } Expect(tl, ')'); diff --git a/varnish-cache/lib/libvcl/vcc_fixed_token.c b/varnish-cache/lib/libvcl/vcc_fixed_token.c index 83c6482d..bb6df1d8 100644 --- a/varnish-cache/lib/libvcl/vcc_fixed_token.c +++ b/varnish-cache/lib/libvcl/vcc_fixed_token.c @@ -235,10 +235,10 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, " * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWI"); vsb_cat(sb, "SE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFT"); vsb_cat(sb, "WARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n"); - vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 3406 2008-11-19 14:"); - vsb_cat(sb, "13:57Z petter $\n *\n * Runtime support for compiled V"); - vsb_cat(sb, "CL programs.\n *\n * XXX: When this file is changed, l"); - vsb_cat(sb, "ib/libvcl/vcc_gen_fixed_token.tcl\n"); + vsb_cat(sb, " * SUCH DAMAGE.\n *\n * $Id: vrt.h 3541 2009-01-23 21:"); + vsb_cat(sb, "17:02Z phk $\n *\n * Runtime support for compiled VCL "); + vsb_cat(sb, "programs.\n *\n * XXX: When this file is changed, lib/"); + vsb_cat(sb, "libvcl/vcc_gen_fixed_token.tcl\n"); vsb_cat(sb, " * XXX: *MUST* be rerun.\n */\n"); vsb_cat(sb, "\nstruct sess;\nstruct vsb;\nstruct cli;\n"); vsb_cat(sb, "struct director;\nstruct VCL_conf;\n"); @@ -289,6 +289,7 @@ vcl_output_lang_h(struct vsb *sb) vsb_cat(sb, " const char *,\n void *, const char *);\n"); vsb_cat(sb, "\nvoid VRT_panic(struct sess *sp, const char *, ...);\n"); vsb_cat(sb, "void VRT_purge(struct sess *sp, char *, ...);\n"); + vsb_cat(sb, "void VRT_purge_string(struct sess *sp, char *, ...);\n"); vsb_cat(sb, "\nvoid VRT_count(const struct sess *, unsigned);\n"); vsb_cat(sb, "int VRT_rewrite(const char *, const char *);\n"); vsb_cat(sb, "void VRT_error(struct sess *, unsigned, const char *);"); -- 2.39.5