From 809553d40b9e5c7a2e08410cbb3412aa80ccb798 Mon Sep 17 00:00:00 2001 From: phk Date: Sun, 18 Jan 2009 16:25:54 +0000 Subject: [PATCH] Add the ability to purge on random request or object headers. For instance: purge req.http.host ~ www.foo.com && req.url ~ "\.png$" purge obj.http.set-cookie ~ USER=383839 Now, why would you want purge on request headers and not object headers ? Simple, some information the object does not have, the Host: header is a good example. Assuming that the Host: header is part of the hash we use to lookup an object (as is the default), we can avoid copying that field into the object (saving memory: O(nObjects)) by using the request value to purge against. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3519 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/cache_ban.c | 59 +++++++++- .../bin/varnishtest/tests/c00021.vtc | 101 +++++++++++++++--- 2 files changed, 143 insertions(+), 17 deletions(-) diff --git a/varnish-cache/bin/varnishd/cache_ban.c b/varnish-cache/bin/varnishd/cache_ban.c index 72ae21bc..42c59d5f 100644 --- a/varnish-cache/bin/varnishd/cache_ban.c +++ b/varnish-cache/bin/varnishd/cache_ban.c @@ -75,6 +75,7 @@ struct ban_test { #define BAN_T_NOT (1 << 1) regex_t re; char *dst; + char *src; }; struct ban { @@ -191,7 +192,7 @@ ban_compare(const struct ban *b1, const struct ban *b2) } /*-------------------------------------------------------------------- - * Test functions -- return 0 if the test does not match + * Test functions -- return 0 if the test matches */ static int @@ -199,13 +200,15 @@ ban_cond_str(const struct ban_test *bt, const char *p) { int i; + if (p == NULL) + return(!(bt->flags & BAN_T_NOT)); if (bt->flags & BAN_T_REGEXP) i = regexec(&bt->re, p, 0, NULL, 0); else i = strcmp(bt->dst, p); if (bt->flags & BAN_T_NOT) - return (i); - return (!i); + return (!i); + return (i); } static int @@ -229,6 +232,30 @@ ban_cond_hash(const struct ban_test *bt, const struct object *o, return(ban_cond_str(bt, o->objhead->hash)); } +static int +ban_cond_req_http(const struct ban_test *bt, const struct object *o, + const struct sess *sp) +{ + char *s; + + (void)o; + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + http_GetHdr(sp->http, bt->src, &s); + return (ban_cond_str(bt, s)); +} + +static int +ban_cond_obj_http(const struct ban_test *bt, const struct object *o, + const struct sess *sp) +{ + char *s; + + (void)sp; + CHECK_OBJ_NOTNULL(o, OBJECT_MAGIC); + http_GetHdr(o->http, bt->src, &s); + return (ban_cond_str(bt, s)); +} + /*-------------------------------------------------------------------- * Parse and add a ban test specification */ @@ -252,6 +279,20 @@ ban_parse_regexp(struct cli *cli, struct ban_test *bt, const char *a3) return (0); } +static void +ban_parse_http(struct ban_test *bt, const char *a1) +{ + int l; + + l = strlen(a1); + bt->src = malloc(l + 3); + XXXAN(bt->src); + bt->src[0] = l + 1; + memcpy(bt->src + 1, a1, l); + bt->src[l + 1] = ':'; + bt->src[l + 2] = '\0'; +} + static int ban_parse_test(struct cli *cli, struct ban *b, const char *a1, const char *a2, const char *a3) { @@ -289,11 +330,19 @@ ban_parse_test(struct cli *cli, struct ban *b, const char *a1, const char *a2, c cli_result(cli, CLIS_PARAM); return (-1); } + + if (!strcmp(a1, "req.url")) bt->func = ban_cond_url; else if (!strcmp(a1, "obj.hash")) bt->func = ban_cond_hash; - else { + else if (!strncmp(a1, "req.http.", 9)) { + bt->func = ban_cond_req_http; + ban_parse_http(bt, a1 + 9); + } else if (!strncmp(a1, "obj.http.", 9)) { + bt->func = ban_cond_obj_http; + ban_parse_http(bt, a1 + 9); + } else { cli_out(cli, "unknown or unsupported field \"%s\"", a1); cli_result(cli, CLIS_PARAM); return (-1); @@ -439,7 +488,7 @@ BAN_CheckObject(struct object *o, const struct sess *sp) if (bt->func(bt, o, sp)) break; } - if (bt != NULL) + if (bt == NULL) break; } diff --git a/varnish-cache/bin/varnishtest/tests/c00021.vtc b/varnish-cache/bin/varnishtest/tests/c00021.vtc index 680755e7..44ae4671 100644 --- a/varnish-cache/bin/varnishtest/tests/c00021.vtc +++ b/varnish-cache/bin/varnishtest/tests/c00021.vtc @@ -5,10 +5,19 @@ test "Test banning a url with cli:purge" server s1 { rxreq expect req.url == "/foo" - txresp -body "1111\n" + 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 -body "11111\n" + txresp -hdr "foo: bar8" -body "1111111\n" } -start varnish v1 -vcl+backend { } -start @@ -17,33 +26,101 @@ client c1 { txreq -url "/foo" rxresp expect resp.status == 200 - expect resp.http.content-length == 5 -} - -client c1 -run + expect resp.http.foo == bar5 + expect resp.bodylen == 5 +} -run +# syntax checks varnish v1 -clierr 104 "purge" varnish v1 -clierr 104 "purge foo" varnish v1 -clierr 104 "purge foo bar" varnish v1 -clierr 106 "purge a b c && a" varnish v1 -clierr 106 "purge a b c && a b" varnish v1 -clierr 106 "purge a b c || a b c" +varnish v1 -cliok "purge.list" + +# exact match, not matching varnish v1 -cliok "purge req.url == foo" +varnish v1 -cliok "purge.list" + client c1 { txreq -url "/foo" rxresp expect resp.status == 200 - expect resp.http.content-length == 5 -} + expect resp.http.foo == bar5 + expect resp.bodylen == 5 +} -run -varnish v1 -cliok "purge req.url ~ foo && req.url ~ \"[ o]\"" +# exact match, matching +varnish v1 -cliok "purge req.url == /foo" +varnish v1 -cliok "purge.list" +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar6 + expect resp.bodylen == 6 +} -run + +# regexp nonmatch +varnish v1 -cliok "purge req.url ~ bar" varnish v1 -cliok "purge.list" client c1 { txreq -url "/foo" rxresp expect resp.status == 200 - expect resp.http.content-length == 6 -} + expect resp.http.foo == bar6 + expect resp.bodylen == 6 +} -run + + +# regexp match +varnish v1 -cliok "purge req.url ~ foo" +varnish v1 -cliok "purge.list" + +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar7 + expect resp.bodylen == 7 +} -run + +# header check, nonmatch +varnish v1 -cliok "purge obj.http.foo != bar7" +varnish v1 -cliok "purge.list" + +client c1 { + txreq -url "/foo" + rxresp + expect resp.status == 200 + expect resp.http.foo == bar7 + expect resp.bodylen == 7 +} -run + +# header check, match +varnish v1 -cliok "purge req.http.foo == barcheck" +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 check, no header +varnish v1 -cliok "purge obj.http.bar == barcheck" +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 + -client c1 -run -- 2.39.5