diff --git a/README.rst b/README.rst index 67d5f2b..9656f71 100644 --- a/README.rst +++ b/README.rst @@ -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 @@ -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 ---------- diff --git a/src/tests/04-filter.vtc b/src/tests/04-filter.vtc index 26c86ed..733d1f9 100644 --- a/src/tests/04-filter.vtc +++ b/src/tests/04-filter.vtc @@ -3,6 +3,8 @@ varnishtest "Test cookie vmod" server s1 { rxreq txresp + rxreq + txresp } -start varnish v1 -vcl+backend { @@ -13,7 +15,11 @@ 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(); @@ -21,9 +27,17 @@ varnish v1 -vcl+backend { } -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 diff --git a/src/vmod_cookie.c b/src/vmod_cookie.c index 74e98b1..c951298 100644 --- a/src/vmod_cookie.c +++ b/src/vmod_cookie.c @@ -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 { @@ -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) { diff --git a/src/vmod_cookie.vcc b/src/vmod_cookie.vcc index 2005ba7..6a9adde 100644 --- a/src/vmod_cookie.vcc +++ b/src/vmod_cookie.vcc @@ -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)