Skip to content
This repository was archived by the owner on Oct 24, 2020. It is now read-only.

Add filter function in orde to achieve the exact opposite of filter_except #33

Open
wants to merge 3 commits into
base: 4.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Handle HTTP cookies easier in Varnish VCL. (without regex)

Parses a cookie header into an internal data store, where per-cookie
get/set/delete functions are available. A filter_except() method removes all
but a set comma-separated list of cookies.
but a set comma-separated list of cookies. A filter() method removes a comma-
separated list of cookies.

A convenience function for formatting the Set-Cookie Expires date field
is also included. It might be needed to use libvmod-header if there might
Expand Down Expand Up @@ -190,6 +191,31 @@ Example



filter
------

Prototype
::

filter(STRING cookienames)
Return value
VOID
Description
Delete all cookies from internal vmod storage that is in the
comma-separated argument cookienames.

Example
::

sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2; cookie3: value3");
cookie.filter("cookie1,cookie2");
// get_string() will now yield
// "cookie3: value3;";
}



get_string
----------

Expand Down
18 changes: 16 additions & 2 deletions src/tests/04-filter.vtc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ varnishtest "Test cookie vmod"
server s1 {
rxreq
txresp
rxreq
txresp
} -start

varnish v1 -vcl+backend {
Expand All @@ -13,17 +15,29 @@ varnish v1 -vcl+backend {
cookie.set("cookie2", "cookie2value");
cookie.set("cookie3", "cookie3value");
cookie.set("cookie4", "cookie4value");
cookie.filter_except("cookie2,cookie4,baz");
if (req.url ~ "^/c1") {
cookie.filter_except("cookie2,cookie4,baz");
} else {
cookie.filter("cookie2,cookie4,baz");
}
}
sub vcl_deliver {
set resp.http.X-foo = cookie.get_string();
}
} -start

client c1 {
txreq -url "/"
txreq -url "/c1"
rxresp
expect resp.http.X-foo == "cookie2=cookie2value; cookie4=cookie4value;"
}

client c1 -run

client c2 {
txreq -url "/c2"
rxresp
expect resp.http.X-foo == "cookie1=cookie1value; cookie3=cookie3value;"
}

client c2 -run
55 changes: 32 additions & 23 deletions src/vmod_cookie.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ struct cookie {
VTAILQ_ENTRY(cookie) list;
};

struct whitelist {
struct list {
char name[MAX_COOKIE_NAME];
VTAILQ_ENTRY(whitelist) list;
VTAILQ_ENTRY(list) list;
};

struct vmod_cookie {
Expand Down Expand Up @@ -236,54 +236,63 @@ vmod_clean(const struct vrt_ctx *ctx) {
}

VCL_VOID
vmod_filter_except(const struct vrt_ctx *ctx, VCL_STRING whitelist_s) {
vmod_filter_function(const struct vrt_ctx *ctx, VCL_STRING list_s, VCL_INT white) {
char buf[MAX_COOKIE_STRING];
struct cookie *cookieptr;
char *tokptr, *saveptr;
int whitelisted = 0;
int listed = 0;
struct vmod_cookie *vcp = cobj_get(ctx);
struct whitelist *whentry;
struct list *entry;

VTAILQ_HEAD(, whitelist) whitelist_head;
VTAILQ_INIT(&whitelist_head);
VTAILQ_HEAD(, list) list_head;
VTAILQ_INIT(&list_head);
CHECK_OBJ_NOTNULL(vcp, VMOD_COOKIE_MAGIC);

strcpy(buf, whitelist_s);
strcpy(buf, list_s);
tokptr = strtok_r(buf, ",", &saveptr);
if (!tokptr) return;

/* Parse the supplied whitelist. */
/* Parse the supplied list. */
while (1) {
whentry = malloc(sizeof(struct whitelist));
AN(whentry);
strcpy(whentry->name, tokptr);
VTAILQ_INSERT_TAIL(&whitelist_head, whentry, list);
entry = malloc(sizeof(struct list));
AN(entry);
strcpy(entry->name, tokptr);
VTAILQ_INSERT_TAIL(&list_head, entry, list);
tokptr = strtok_r(NULL, ",", &saveptr);
if (!tokptr) break;
}

/* Filter existing cookies that isn't in the whitelist. */
/* Filter existing cookies that is or isn't (depends on the white flag) in the list. */
VTAILQ_FOREACH(cookieptr, &vcp->cookielist, list) {
CHECK_OBJ_NOTNULL(cookieptr, VMOD_COOKIE_ENTRY_MAGIC);
whitelisted = 0;
VTAILQ_FOREACH(whentry, &whitelist_head, list) {
if (strlen(cookieptr->name) == strlen(whentry->name) &&
strcmp(cookieptr->name, whentry->name) == 0) {
whitelisted = 1;
listed = 0;
VTAILQ_FOREACH(entry, &list_head, list) {
if (strlen(cookieptr->name) == strlen(entry->name) &&
strcmp(cookieptr->name, entry->name) == 0) {
listed = 1;
break;
}
}
if (!whitelisted) {
if ((white && !listed) || (!white && listed)) {
VTAILQ_REMOVE(&vcp->cookielist, cookieptr, list);
}
}

VTAILQ_FOREACH(whentry, &whitelist_head, list) {
VTAILQ_REMOVE(&whitelist_head, whentry, list);
free(whentry);
VTAILQ_FOREACH(entry, &list_head, list) {
VTAILQ_REMOVE(&list_head, entry, list);
free(entry);
}
}

VCL_VOID
vmod_filter_except(const struct vrt_ctx *ctx, VCL_STRING whitelist_s) {
vmod_filter_function(ctx, whitelist_s, 1);
}

VCL_VOID
vmod_filter(const struct vrt_ctx *ctx, VCL_STRING blacklist_s) {
vmod_filter_function(ctx, blacklist_s, 0);
}

VCL_STRING
vmod_get_string(const struct vrt_ctx *ctx) {
Expand Down
1 change: 1 addition & 0 deletions src/vmod_cookie.vcc
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ $Function STRING get(STRING)
$Function BOOL isset(STRING)
$Function VOID delete(STRING)
$Function VOID filter_except(STRING)
$Function VOID filter(STRING)
$Function STRING get_string()
$Function STRING format_rfc1123(TIME, DURATION)