Commit f64a54e3 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

Import vmod_cookie from varnish/varnish-modules

This is in essence the same VMOD so migrating from one to the other
should result in no VCL change, except for the removal of DEPRECATED
cookie.filter_except().

The test suite was refreshed to take advantage of recent features and
mostly operates in vcl_synth as a result, not wasting cycles bringing
needless backends up.

The C code and VCC descriptor were also improved for better code style
compliance and documentation consistency, without changing the VMOD's
behavior. On the C side actual changes mostly consisted in adding missing
assertions but there were notable changes:

- usage of VRE_Free instead of free (with test case)
- WS_VSB_* facility usage for the one use case

There are other opportunities for improvement, like usage of more modern
facilities like VRT_fail, or a named Lck instead of a plain mutex.

Closes #3184
parent 746384b2
......@@ -853,6 +853,7 @@ AC_CONFIG_FILES([
lib/libvarnishapi/Makefile
lib/libvcc/Makefile
lib/libvgz/Makefile
lib/libvmod_cookie/Makefile
lib/libvmod_debug/Makefile
lib/libvmod_std/Makefile
lib/libvmod_directors/Makefile
......
......@@ -5,6 +5,7 @@ SUBDIRS = \
libvarnishapi \
libvcc \
libvgz \
libvmod_cookie \
libvmod_debug \
libvmod_std \
libvmod_directors \
......
libvmod_cookie_la_SOURCES = \
vmod_cookie.c
# Use vmodtool.py generated automake boilerplate
include $(srcdir)/automake_boilerplate.am
# Generated by vmodtool.py --boilerplate.
AM_LDFLAGS = $(AM_LT_LDFLAGS)
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/bin/varnishd \
-I$(top_builddir)/include
vmoddir = $(pkglibdir)/vmods
vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
vmodtoolargs ?= --strict --boilerplate
vmod_LTLIBRARIES = libvmod_cookie.la
libvmod_cookie_la_CFLAGS = \
@SAN_CFLAGS@
libvmod_cookie_la_LDFLAGS = \
-export-symbols-regex 'Vmod_cookie_Data' \
$(AM_LDFLAGS) \
$(VMOD_LDFLAGS) \
@SAN_LDFLAGS@
nodist_libvmod_cookie_la_SOURCES = vcc_if.c vcc_if.h
$(libvmod_cookie_la_OBJECTS): vcc_if.h
vcc_if.h vmod_cookie.rst vmod_cookie.man.rst: vcc_if.c
vcc_if.c: $(vmodtool) $(srcdir)/vmod.vcc
@PYTHON@ $(vmodtool) $(vmodtoolargs) $(srcdir)/vmod.vcc
EXTRA_DIST = vmod.vcc automake_boilerplate.am
CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h \
$(builddir)/vmod_cookie.rst \
$(builddir)/vmod_cookie.man.rst
TESTS = \
tests/cookie_b00000.vtc \
tests/cookie_b00001.vtc \
tests/cookie_b00002.vtc \
tests/cookie_b00003.vtc \
tests/cookie_b00004.vtc \
tests/cookie_b00005.vtc \
tests/cookie_b00006.vtc \
tests/cookie_b00007.vtc \
tests/cookie_b00008.vtc \
tests/cookie_b00009.vtc \
tests/cookie_b00010.vtc \
tests/cookie_b00011.vtc \
tests/cookie_b00012.vtc \
tests/cookie_b00013.vtc \
tests/cookie_r00028.vtc \
tests/cookie_v00000.vtc
EXTRA_DIST += $(TESTS)
vtc-refresh-tests:
@PYTHON@ $(vmodtool) $(vmodtoolargs) $(srcdir)/vmod.vcc
@cd $(top_builddir) && ./config.status --file=$(subdir)/Makefile
include $(top_srcdir)/vtc.am
varnishtest "Test vmod_cookie"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("cookie1", "cookie1BAD");
cookie.set("cookie2", "cookie2value");
cookie.set("cookie3", "cookie3value");
cookie.set("cookie4", "cookie4value");
cookie.set("cookie1", "cookie1value"); # overrides cookie1
cookie.delete("cookie2");
set resp.http.X-foo = cookie.get_string();
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-foo == "cookie1=cookie1value; cookie3=cookie3value; cookie4=cookie4value;"
} -run
varnishtest "Test cookie.clean()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.clean();
cookie.set("cookie1", "cookie1BAD");
set resp.http.X-foo = cookie.get_string();
cookie.clean();
set resp.http.X-bar = cookie.get_string();
}
} -start
client c1 {
txreq
rxresp
expect resp.http.X-foo == "cookie1=cookie1BAD;"
expect resp.http.X-bar == ""
} -run
varnishtest "NULL/empty value checks"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
# nothing in here at this point.
set req.http.x-foo = cookie.get_string();
# XXX: We might want to revisit these assumptions since "="
# (empty name and empty value) is as correct as "name=value"
# for a cookie. See rfc6265 section 5.2 for reference.
# empty name
cookie.set("", "foo");
# empty value
cookie.set("cookie1", "");
# proper NULL
cookie.set(req.http.null, "foo");
# double delete
cookie.delete("cookie2");
cookie.delete("cookie2");
cookie.delete(req.http.null);
set resp.http.x-foo = cookie.get_string();
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.x-foo == ""
} -run
varnishtest "Test cookie.keep()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("biscuit", "standard");
cookie.set("bredela", "eggwhites");
cookie.set("chocolatechip", "verychippy");
cookie.set("empire", "jellytots");
cookie.keep("bredela,empire,baz");
set resp.http.X-foo = cookie.get_string();
# Test exotic admin-supplied filter strings.
cookie.parse("bredela=eggwhites; empire=jellytots;");
cookie.keep(",,,,bredela, ,empire,baz,");
set resp.http.X-bar = cookie.get_string();
cookie.keep(req.http.none);
set resp.http.X-baz = cookie.get_string();
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-foo == "bredela=eggwhites; empire=jellytots;"
expect resp.http.X-bar == "bredela=eggwhites; empire=jellytots;"
expect resp.http.X-baz == ""
} -run
varnishtest "Test cookie.filter()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("biscuit", "standard");
cookie.set("bredela", "eggwhites");
cookie.set("chocolatechip", "verychippy");
cookie.set("empire", "jellytots");
cookie.filter("bredela,empire,baz");
set resp.http.X-foo = cookie.get_string();
# Test exotic admin-supplied filter strings.
cookie.parse("bredela=eggwhites; empire=jellytots;");
cookie.filter(",,,,bredela, ,baz,");
set resp.http.X-bar = cookie.get_string();
cookie.parse("foo=bar; bar=baz;");
cookie.filter(req.http.none);
set resp.http.X-baz = cookie.get_string();
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-foo == "biscuit=standard; chocolatechip=verychippy;"
expect resp.http.X-bar == "empire=jellytots;"
expect resp.http.X-baz == "foo=bar; bar=baz;"
} -run
varnishtest "Test missing cookie"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("cookie1", "cookie1value");
cookie.set("cookie2", "cookie2value");
set resp.http.X-foo = cookie.get("cookie2");
# Make sure we handle this gracefully.
set resp.http.X-bar = "" + cookie.get("non-existing");
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-foo == "cookie2value"
expect resp.http.X-bar == ""
} -run
varnishtest "Test vmod_cookie concurrency"
barrier b1 cond 2
server s1 {
rxreq
barrier b1 sync
expect req.url == "/s1"
txresp
} -start
server s2 {
rxreq
expect req.url == "/s2"
txresp
} -start
varnish v1 -vcl+backend {
import cookie;
sub vcl_recv {
cookie.parse(req.http.cookie);
if (req.url == "/s1") {
set req.backend_hint = s1;
}
else {
set req.backend_hint = s2;
}
}
sub vcl_deliver {
set resp.http.x-val = cookie.get("a");
}
} -start
client c1 {
txreq -url "/s1" -hdr "Cookie: a=bar"
rxresp
expect resp.http.x-val == "bar"
} -start
client c2 {
barrier b1 sync
txreq -url "/s2" -hdr "Cookie: a=foo"
rxresp
expect resp.http.x-val == "foo"
} -run
client c1 -wait
varnishtest "Test cookie.isset()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("cookie1", "cookie1value");
set resp.http.does = cookie.isset("cookie1");
set resp.http.does-not = cookie.isset("non-existent");
set resp.http.null = cookie.isset("");
set resp.http.null2 = cookie.isset(req.http.probably-null);
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.does == "true"
expect resp.http.does-not == "false"
expect resp.http.null == "false"
expect resp.http.null2 == "false"
} -run
varnishtest "Test large cookies"
varnish v1 -cliok "param.set workspace_client 64k" -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.parse(req.http.cookie);
set resp.http.cookiestring = cookie.get_string();
set resp.http.cookie1 = cookie.isset("cookie1");
}
} -start
client c1 {
# Insanely long cookie name.
txreq -url "/" -hdr "Cookie: phohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1j=cookievalue"
rxresp
expect resp.http.cookiestring == "phohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1j=cookievalue;"
# Insane 6KB cookie value.
txreq -url "/" -hdr "Cookie: cookie1=foobarbazfoobarbazphohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1jphohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1jphohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1jphohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1jphohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1jphohx8aingie6Ide7peephie5paip6ang4thooh4ooquai8ohvah7eiqueeki8ooth7viequ0Tha5thewiSheih5jaimaiTahr1wi8WooQuoe7loothieThahweeneichoo8cufeelu3tie5cei1iShiemiezoofox6ahcaevaihocheungai2aeghaichaingee0EiGie3Ees5ujaem5uquahpieFeelei7Ohngei1afaTooph4aiquum1aewaidatheshuh1fohhoor0hoo6aeTeiy9xougahf3jeapooshuhoob5deiwareingahth7ahf2fafeer8Oobiewai3rei8ofejohjeiye4die8Na7ze6eixajauCairoth0lek8vioyuom6eih0egho2aingoo7coh1at3niochu6osahthi0ue1Luchae1eifeupiuwaa0raidiewaijese4oozee4eihie5shaBaoreacooNg8uW9eru9kigh3Feesi8iex2pu7ohfaiBiezael6ifaujiek4nutae1aalohchoteiPuaM2chiefaicaopheKohsh6Ho1wiephieseef1daj3Pahfie2ooch8shaing5baXeiLiep9lahfe9uDaxeehielais2eix3iekiew8aiter9Foo8noo2hae7ohdie1iB7hoop3podeengooSothoojui4AhXu5Nain8ohqu8if1ue5iTheimei5oghie9sheiv4Hejah1veixahcaixie8ahyieT8Phay4daeTei1aRiemae6oicheef2miiNuoxeil1kae2nea1roh9Rei1keiwaT2eoJaiNgie0den6aideif3uechaishaec4cai2eozieb9aeN9sai9ahnielohdaeGh2kaeleiteitai0ietoo7eiCha0baiW7dai0im1jul5OWijaLo2ohh3kooxu2oFah3loob6feiw7pie9eighu8ik4chae0Athou2fah5ieQuuic0Mu1j;"
rxresp
# We support long cookie values, should be fine.
expect resp.http.cookie1 == "true"
} -run
varnishtest "Test cookie parser"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.parse(req.http.cookie);
set resp.http.X-foo = cookie.get_string();
}
} -start
client c1 {
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
} -run
client c2 {
txreq -hdr "Cookie: __utmc=253898641; __utma=253898641.654622101.1372224466.1372224466.1372224466.1; __utmb=253898641.44.10.1372224466; __utmz=253898641.1372224466.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=index%2Bof%2Bccnp%2Bpdf"
rxresp
expect resp.http.X-foo == "__utmc=253898641; __utma=253898641.654622101.1372224466.1372224466.1372224466.1; __utmb=253898641.44.10.1372224466; __utmz=253898641.1372224466.1.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=index%2Bof%2Bccnp%2Bpdf;"
} -run
client c3 {
txreq -hdr "Cookie: "
rxresp
expect resp.http.X-foo == ""
} -run
# An empty cookie is a non-existing cookie for us.
client c4 {
txreq -hdr "Cookie: emptycookie="
rxresp
expect resp.http.X-foo == ""
} -run
# A single cookie should also work.
client c5 {
txreq -hdr "Cookie: cookie1=foobarbaz"
rxresp
expect resp.http.X-foo == "cookie1=foobarbaz;"
} -run
# Don't overflow the buffer with an edge case
client c6 {
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128a;=" -hdr "X-Not-Cookie: sessionid=a707505310ddf259bb290d3ca63fc561"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128a;"
} -run
varnishtest "Test rfc1123 string formatting function"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
set resp.http.x-date = cookie.format_rfc1123(now, 1d);
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.date != <undef>
} -run
varnishtest "Test cookie.get_re()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("biscuit", "standard");
cookie.set("chocolatechip", "verychippy");
cookie.set("empire", "jellytots");
set resp.http.X-first = cookie.get_re("DOES_NOT_EXIST");
set resp.http.X-second = cookie.get_re("biscuit");
set resp.http.X-third = cookie.get_re("DOES_NOT_EXIST_EITHER");
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-first == ""
expect resp.http.X-second == "standard"
expect resp.http.X-third == ""
} -run
varnishtest "Test cookie.filter_re()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.set("biscuit", "standard");
cookie.set("bredela", "eggwhites");
cookie.set("empire", "jellytots");
set resp.http.X-foo = cookie.get_string();
cookie.filter_re("^NOT-MATCHING-ANYTHING$");
set resp.http.X-bar = cookie.get_string();
cookie.filter_re("^bredela");
set resp.http.X-baz = cookie.get_string();
cookie.filter_re(".*");
set resp.http.X-qux = cookie.get_string();
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-foo == resp.http.X-bar
expect resp.http.X-baz != resp.http.X-foo
expect resp.http.X-baz == "biscuit=standard; empire=jellytots;"
expect resp.http.X-qux == ""
} -run
varnishtest "Test cookie.keep_re()"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.parse("foo=bar; baz=qux;");
cookie.keep_re("NOTHING_MATCHES_SO_NOTHING_KEPT$");
set resp.http.X-empty = cookie.get_string();
cookie.parse("biscuit=standard; bredela=eggwhites; empire=jellytots;");
cookie.keep_re("^b");
set resp.http.X-bees = cookie.get_string();
}
} -start
client c1 {
txreq -url "/"
rxresp
expect resp.http.X-empty == ""
expect resp.http.X-bees == "biscuit=standard; bredela=eggwhites;"
} -run
varnishtest "Test issue https://github.com/varnish/varnish-modules/issues/28"
varnish v1 -vcl {
import cookie;
backend be none;
sub vcl_recv { return (synth(200)); }
sub vcl_synth {
cookie.parse(req.http.cookie);
set resp.http.X-foo = cookie.get_string();
}
} -start
client c1 {
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
}
client c2 {
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
txreq -hdr "Cookie: csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560"
rxresp
expect resp.http.X-foo == "csrftoken=0e0c3616e41a6bd561b72b7f5fc1128f; sessionid=a707505310ddf259bb290d3ca63fc560;"
}
client c1 -repeat 2 -run
client c2 -repeat 2 -run
$Module cookie 3 "Varnish Cookie Module"
DESCRIPTION
===========
Handle HTTP cookies easier in Varnish VCL.
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. A filter() method removes a comma-
separated list of cookies.
Regular expressions can be used for either selecting cookies, deleting matching
cookies and deleting non-matching cookie names.
A convenience function for formatting the Set-Cookie Expires date field
is also included.
The state loaded with cookie.parse() has a lifetime of the current request
or backend request context. To pass variables to the backend request, store
the contents as fake bereq headers.
Filtering example::
import cookie;
sub vcl_recv {
if (req.http.cookie) {
cookie.parse(req.http.cookie);
# Either delete the ones you want to get rid of:
cookie.delete("cookie2");
# or delete all but a few:
cookie.keep("SESSIONID,PHPSESSID");
# Store it back into req so it will be passed to the backend.
set req.http.cookie = cookie.get_string();
# If empty, unset so the builtin VCL can consider it for caching.
if (req.http.cookie == "") {
unset req.http.cookie;
}
}
}
$ABI strict
$Function VOID clean(PRIV_TASK)
Clean up previously parsed cookies. It is not necessary to run clean()
in normal operations.
Example::
sub vcl_recv {
cookie.clean();
}
$Function VOID delete(PRIV_TASK, STRING cookiename)
Delete ``cookiename`` from internal vmod storage if it exists.
Example::
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2;");
cookie.delete("cookie2");
# get_string() will now yield "cookie1: value1";
}
$Function VOID filter(PRIV_TASK, STRING filterstring)
Delete all cookies from internal vmod storage that are 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";
}
$Function VOID filter_re(PRIV_TASK, PRIV_CALL, STRING expression)
Delete all cookies from internal vmod storage that matches the
regular expression ``expression``.
Example::
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2; cookie3: value3");
cookie.filter_re("^cookie[12]$");
# get_string() will now yield
# "cookie3: value3";
}
$Function VOID keep(PRIV_TASK, STRING filterstring)
Delete all cookies from internal vmod storage that is not in the
comma-separated argument cookienames.
Example::
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2; cookie3: value3");
cookie.keep("cookie1,cookie2");
# get_string() will now yield
# "cookie1: value1; cookie2: value2;";
}
$Function VOID keep_re(PRIV_TASK, PRIV_CALL, STRING expression)
Delete all cookies from internal vmod storage that does not match
expression ``expression``.
Example::
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2; cookie3: value3");
cookie.keep_re("^cookie1,cookie2");
# get_string() will now yield
# "cookie1: value1; cookie2: value2;";
}
$Function STRING format_rfc1123(TIME now, DURATION timedelta)
Get a RFC1123 formatted date string suitable for inclusion in a
Set-Cookie response header.
Care should be taken if the response has multiple Set-Cookie headers.
In that case the header vmod should be used.
Example::
sub vcl_deliver {
# Set a userid cookie on the client that lives for 5 minutes.
set resp.http.Set-Cookie = "userid=" + req.http.userid +
"; Expires=" + cookie.format_rfc1123(now, 5m) + "; httpOnly";
}
$Function STRING get(PRIV_TASK, STRING cookiename)
Get the value of ``cookiename``, as stored in internal vmod storage. If
``cookiename`` does not exist an empty string is returned.
Example::
import std;
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2;");
std.log("cookie1 value is: " + cookie.get("cookie1"));
}
$Function STRING get_re(PRIV_TASK, PRIV_CALL, STRING expression)
Get the value of the first cookie in internal vmod storage that matches
regular expression ``expression``. If nothing matches, an empty string
is returned.
Example::
import std;
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2;");
std.log("cookie1 value is: " + cookie.get_re("^cookie1$"));
}
$Function STRING get_string(PRIV_TASK)
Get a Cookie string value with all cookies in internal vmod storage. Does
not modify internal storage.
Example::
sub vcl_recv {
cookie.parse(req.http.cookie);
cookie.filter_except("SESSIONID,PHPSESSID");
set req.http.cookie = cookie.get_string();
}
$Function BOOL isset(PRIV_TASK, STRING cookiename)
Check if ``cookiename`` is set in the internal vmod storage.
Example::
import std;
sub vcl_recv {
cookie.parse("cookie1: value1; cookie2: value2;");
if (cookie.isset("cookie2")) {
std.log("cookie2 is set.");
}
}
$Function VOID parse(PRIV_TASK, STRING cookieheader)
Parse the cookie string in ``cookieheader``. If state already exists,
``clean()`` will be run first.
Example::
sub vcl_recv {
cookie.parse(req.http.Cookie);
}
$Function VOID set(PRIV_TASK, STRING cookiename, STRING value)
Set the internal vmod storage for ``cookiename`` to ``value``.
Example::
sub vcl_recv {
cookie.set("cookie1", "value1");
std.log("cookie1 value is: " + cookie.get("cookie1"));
}
This diff is collapsed.
......@@ -15,6 +15,7 @@ dist_man_MANS = \
varnishtest.1 \
vtc.7 \
varnishtop.1 \
vmod_cookie.3 \
vmod_directors.3 \
vmod_purge.3 \
vmod_std.3 \
......@@ -91,6 +92,9 @@ varnishhist.1: \
$(top_builddir)/doc/sphinx/include/varnishhist_synopsis.rst
$(BUILD_MAN) $(top_srcdir)/doc/sphinx/reference/varnishhist.rst $@
vmod_cookie.3: $(top_builddir)/lib/libvmod_cookie/vmod_cookie.man.rst
$(BUILD_MAN) $? $@
vmod_directors.3: $(top_builddir)/lib/libvmod_directors/vmod_directors.man.rst
$(BUILD_MAN) $? $@
......
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