]> err.no Git - varnish/commitdiff
Add the ability to purge on random request or object headers.
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Sun, 18 Jan 2009 16:25:54 +0000 (16:25 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Sun, 18 Jan 2009 16:25:54 +0000 (16:25 +0000)
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
varnish-cache/bin/varnishtest/tests/c00021.vtc

index 72ae21bc730aa2d2b7e1a1285c5d7973c75b1874..42c59d5f4dc38595ce2948070e769a08dddaf373 100644 (file)
@@ -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;
        }
 
index 680755e77fcbe1d86ad76dce6e85bc8402b0cd15..44ae4671994c1a999db0dd3067fd411384864a5d 100644 (file)
@@ -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