Commit 26473198 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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: http://www.varnish-cache.org/svn/trunk/varnish-cache@3519 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent d5df426b
......@@ -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;
}
......
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment