Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
varnish-devicedetect
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
varnishcache
varnish-devicedetect
Commits
d54c3149
Commit
d54c3149
authored
Dec 19, 2014
by
Lasse Karstensen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Big rework of example VCL testing.
parent
a33cf2a4
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
130 additions
and
234 deletions
+130
-234
.gitignore
.gitignore
+1
-0
INSTALL.rst
INSTALL.rst
+32
-14
insert-vcl-examples
insert-vcl-examples
+0
-27
65-redir-mobile.vtc
tests/65-redir-mobile.vtc
+0
-40
71-example1.vtc
tests/71-example1.vtc
+0
-50
72-example2.vtc
tests/72-example2.vtc
+0
-42
73-example3.vtc
tests/73-example3.vtc
+0
-58
Makefile
tests/Makefile
+6
-2
vtc-from-controlset.py
tests/vtc-from-controlset.py
+4
-1
vtc-from-snippets.py
tests/vtc-from-snippets.py
+87
-0
No files found.
.gitignore
View file @
d54c3149
tests/99*
tests/snippet-*.vtc
INSTALL.rst
View file @
d54c3149
...
...
@@ -26,12 +26,14 @@ content is dependant on this header.
Everything works out of the box from Varnish' perspective.
..
71-example1-start
..
startsnippet-example1
VCL::
include "devicedetect.vcl";
sub vcl_recv { call devicedetect; }
sub vcl_recv {
call devicedetect;
}
# req.http.X-UA-Device is copied by Varnish into bereq.http.X-UA-Device
# so, this is a bit conterintuitive. The backend creates content based on the normalized User-Agent,
...
...
@@ -60,7 +62,7 @@ VCL::
}
}
..
71-example1-end
..
endsnippet-example1
Example 2: Normalize the User-Agent string
...
...
@@ -83,12 +85,19 @@ This works if you don't need the original header for anything on the backend. A
possible use for this is for CGI scripts where only a small set of predefined
headers are (by default) available for the script.
.. 72-example2-start
.. req: txreq -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
.. req: rxresp
.. req: expect resp.http.X-UA-Device == "mobile-android"
.. req: expect resp.http.Vary == "User-Agent"
.. startsnippet-example2
VCL::
include "devicedetect.vcl";
sub vcl_recv { call devicedetect; }
sub vcl_recv {
call devicedetect;
}
# override the header before it is sent to the backend
sub vcl_backend_fetch { if (bereq.http.X-UA-Device) { set bereq.http.User-Agent = bereq.http.X-UA-Device; } }
...
...
@@ -110,7 +119,7 @@ VCL::
}
}
..
72-example2-end
..
endsnippet-example2
Example 3: Add the device class as a GET query parameter
''''''''''''''''''''''''''''''''''''''''''''''''''''''''
...
...
@@ -121,12 +130,14 @@ If everything else fails, you can add the device type as a GET argument.
The client itself does not see this classification, only the backend request is changed.
..
73-example3-start
..
startsnippet-example3
VCL::
include "devicedetect.vcl";
sub vcl_recv { call devicedetect; }
sub vcl_recv {
call devicedetect;
}
# do this after vcl_hash, so all Vary-ants can be purged in one go. (avoid ban()ing)
sub vcl_backend_fetch {
...
...
@@ -166,18 +177,21 @@ VCL::
}
}
..
73-example3-end
..
endsnippet-example3
Different backend for mobile clients
------------------------------------
If you have a different backend that serves pages for mobile clients, or any
special needs in VCL, you can use the X-UA-Device header like this::
special needs in VCL, you can use the X-UA-Device header like the following.
VCL::
vcl 4.0;
include "devicedetect.vcl";
backend mobile {
.host = "1
0.0.0.1
";
.host = "1
92.0.2.10
";
.port = "80";
}
...
...
@@ -185,7 +199,7 @@ special needs in VCL, you can use the X-UA-Device header like this::
call devicedetect;
if (req.http.X-UA-Device ~ "^mobile" || req.http.X-UA-device ~ "^tablet") {
set req.backend = mobile;
set req.backend
_hint
= mobile;
}
}
...
...
@@ -194,7 +208,11 @@ Redirecting mobile clients
If you want to redirect mobile clients you can use the following snippet.
.. 65-redir-mobile-start
.. req: txreq -req GET -url /foo -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" -hdr "Host: example.com"
.. req: rxresp
.. req: expect resp.status == 302
.. req: expect resp.http.Location == "http://m.example.com/foo"
.. startsnippet-redir2
VCL::
...
...
@@ -215,7 +233,7 @@ VCL::
}
}
..
65-redir-mobile-end
..
endsnippet-redir2
Testing tools
...
...
insert-vcl-examples
deleted
100755 → 0
View file @
a33cf2a4
#!/bin/bash -x
#
# To make sure the example VCL code is valid and runnable, actually store the auth copy in
# the varnishtest files. Use the magic of sed to put it into the documentation.
#
tmpfile
=
/tmp/foo
$RANDOM
DOCUMENT
=
INSTALL.rst
transform
()
{
f
=
$1
# stuff to put into the section
sed
-n
'/varnish v1 -vcl+backend/,/start/p'
tests/
$f
.vtc
>
$tmpfile
sed
-i
's/${projectdir}\/..\///'
$tmpfile
# remove first and last line of file. todo: learn more sed to do this more smoothly.
tail
-n
+2
$tmpfile
|
head
-n-1
>
$tmpfile
.2
;
mv
$tmpfile
.2
$tmpfile
sed
-e
"/..
$f
-start/ q"
$DOCUMENT
>
$tmpfile
.orig.top
echo
-e
"
\n
VCL::
\n
"
>>
$tmpfile
.orig.top
sed
-n
"/..
$f
-end/,
\$
p"
$DOCUMENT
>
$tmpfile
.orig.below
cat
$tmpfile
.orig.top
$tmpfile
$tmpfile
.orig.below
>
$DOCUMENT
rm
$tmpfile
$tmpfile
.orig.top
$tmpfile
.orig.below
}
transform 65-redir-mobile
transform 71-example1
transform 72-example2
transform 73-example3
tests/65-redir-mobile.vtc
deleted
100644 → 0
View file @
a33cf2a4
varnishtest "Show example of per-device-class redirects."
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
include "${projectdir}/../devicedetect.vcl";
sub vcl_recv {
call devicedetect;
if (req.http.X-UA-Device ~ "^mobile" || req.http.X-UA-device ~ "^tablet") {
return(synth(750, "Moved Temporarily"));
}
}
sub vcl_synth {
if (resp.status == 750) {
set resp.http.Location = "http://m.example.com" + req.url;
set resp.status = 302;
return(deliver);
}
}
} -start
client c1 {
txreq -req GET -url /foo -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" -hdr "Host: example.com"
rxresp
expect resp.status == 302
expect resp.http.Location == "http://m.example.com/foo"
} -run
client c2 {
txreq -req GET -url /foo -hdr "Host: example.com"
rxresp
expect resp.status == 200
expect resp.http.Location == <undef>
} -run
tests/71-example1.vtc
deleted
100644 → 0
View file @
a33cf2a4
varnishtest "Test varnish-devicedetect"
server s1 {
rxreq
expect req.http.X-UA-Device == "mobile-android"
txresp
} -start
# this example shows how to normalize the user agent string seen by the backend.
varnish v1 -vcl+backend {
include "${projectdir}/../devicedetect.vcl";
sub vcl_recv {
call devicedetect;
}
# req.http.X-UA-Device is copied by Varnish into bereq.http.X-UA-Device
# so, this is a bit conterintuitive. The backend creates content based on the normalized User-Agent,
# but we use Vary on X-UA-Device so Varnish will use the same cached object for all U-As that map to
# the same X-UA-Device.
# If the backend does not mention in Vary that it has crafted special
# content based on the User-Agent (==X-UA-Device), add it.
# If your backend does set Vary: User-Agent, you may have to remove that here.
sub vcl_backend_response {
if (bereq.http.X-UA-Device) {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "X-UA-Device";
} elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
}
}
# comment this out if you don't want the client to know your classification
set beresp.http.X-UA-Device = bereq.http.X-UA-Device;
}
# to keep any caches in the wild from serving wrong content to client #2 behind them, we need to
# transform the Vary on the way out.
sub vcl_deliver {
if ((req.http.X-UA-Device) && (resp.http.Vary)) {
set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
}
}
} -start
client c1 {
txreq -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
rxresp
expect resp.http.X-UA-Device == "mobile-android"
expect resp.http.Vary == "User-Agent"
} -run
tests/72-example2.vtc
deleted
100644 → 0
View file @
a33cf2a4
varnishtest "Test varnish-devicedetect"
server s1 {
rxreq
txresp
} -start
# this example shows how to normalize the user agent string seen by the backend.
varnish v1 -vcl+backend {
include "${projectdir}/../devicedetect.vcl";
sub vcl_recv {
call devicedetect;
}
# override the header before it is sent to the backend
sub vcl_backend_fetch { if (bereq.http.X-UA-Device) { set bereq.http.User-Agent = bereq.http.X-UA-Device; } }
# standard Vary handling code from previous examples.
sub vcl_backend_response {
if (bereq.http.X-UA-Device) {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "X-UA-Device";
} elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
}
}
set beresp.http.X-UA-Device = bereq.http.X-UA-Device;
}
sub vcl_deliver {
if ((req.http.X-UA-Device) && (resp.http.Vary)) {
set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
}
}
} -start
client c1 {
txreq -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
rxresp
expect resp.http.X-UA-Device == "mobile-android"
expect resp.http.Vary == "User-Agent"
} -run
tests/73-example3.vtc
deleted
100644 → 0
View file @
a33cf2a4
varnishtest "Test varnish-devicedetect"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
include "${projectdir}/../devicedetect.vcl";
sub vcl_recv {
call devicedetect;
}
# do this after vcl_hash, so all Vary-ants can be purged in one go. (avoid ban()ing)
sub vcl_backend_fetch {
if ((bereq.http.X-UA-Device) && (bereq.method == "GET")) {
# if there are existing GET arguments;
if (bereq.url ~ "\?") {
set bereq.http.X-get-devicetype = "&devicetype=" + bereq.http.X-UA-Device;
} else {
set bereq.http.X-get-devicetype = "?devicetype=" + bereq.http.X-UA-Device;
}
set bereq.url = bereq.url + bereq.http.X-get-devicetype;
unset bereq.http.X-get-devicetype;
}
}
# Handle redirects, otherwise standard Vary handling code from previous examples.
sub vcl_backend_response {
if (bereq.http.X-UA-Device) {
if (!beresp.http.Vary) { # no Vary at all
set beresp.http.Vary = "X-UA-Device";
} elseif (beresp.http.Vary !~ "X-UA-Device") { # add to existing Vary
set beresp.http.Vary = beresp.http.Vary + ", X-UA-Device";
}
# if the backend returns a redirect (think missing trailing slash), we
# will potentially show the extra address to the client. we don't want that.
# if the backend reorders the get parameters, you may need to be smarter here. (? and & ordering)
if (beresp.status == 301 || beresp.status == 302 || beresp.status == 303) {
set beresp.http.Location = regsub(beresp.http.location, "[?&]devicetype=.*$", "");
}
}
set beresp.http.X-UA-Device = bereq.http.X-UA-Device;
}
sub vcl_deliver {
if ((req.http.X-UA-Device) && (resp.http.Vary)) {
set resp.http.Vary = regsub(resp.http.Vary, "X-UA-Device", "User-Agent");
}
}
} -start
client c1 {
txreq -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
rxresp
expect resp.http.X-UA-Device == "mobile-android"
} -run
tests/Makefile
View file @
d54c3149
...
...
@@ -8,10 +8,14 @@ TESTS=*.vtc
all
:
controlset $(TESTS)
.PHONY
:
all controlset $(TESTS)
.PHONY
:
all controlset
snippets
$(TESTS)
controlset
:
../controlset.txt vtc-from-controlset.py
./vtc-from-controlset.py
>
99-controlset.vtc
$(TESTS)
:
controlset
snippets
:
../INSTALL.rst vtc-from-snippets.py
rm
snippet
*
vtc
./vtc-from-snippets.py ../INSTALL.rst
$(TESTS)
:
controlset snippets
${
VARNISHTEST
}
-Dvarnishd
=
${
VARNISHD
}
-Dprojectdir
=
$(PWD)
$@
tests/vtc-from-controlset.py
View file @
d54c3149
...
...
@@ -13,7 +13,10 @@ server s1 {
} -start
varnish v1 -vcl+backend {
include "${projectdir}/../devicedetect.vcl";
sub vcl_deliver { class devicedetect; set resp.http.X-UA-Device = req.http.X-UA-Device; }
sub vcl_deliver {
call devicedetect;
set resp.http.X-UA-Device = req.http.X-UA-Device;
}
} -start
client c1 {"""
...
...
tests/vtc-from-snippets.py
0 → 100755
View file @
d54c3149
#!/usr/bin/env python
"""
Pick out the examples from the installation documentation and
build a VTC test case around it.
This is to make sure that our documented examples are always runnable.
Format from the input file:
.. foo-start
vcl code here
.. foo-end
foo is a name that describes the vcl snippet.
"""
from
sys
import
argv
,
stdout
from
pprint
import
pprint
def
header
(
description
):
return
"""varnishtest "
%
s"
server s1 {
rxreq
txresp
} -start
varnish v1 -vcl+backend {
include "${projectdir}/../devicedetect.vcl";"""
%
description
def
tailer
(
optional_req
):
s
=
"""} -start
client c1 {
"""
if
req
:
s
+=
" # from rst
\n
"
s
+=
req
else
:
s
+=
"""
txreq -req GET -url /foo -hdr "User-Agent: Mozilla/5.0 (Linux; U; Android 2.2; nb-no; HTC Desire Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1" -hdr "Host: example.com"
rxresp
expect resp.status == 200"""
s
+=
"""
} -run"""
return
s
def
parse
(
inputfile
):
section
=
None
buf
=
[]
req
=
[]
for
line
in
open
(
inputfile
):
if
line
.
startswith
(
".. req:"
):
req
.
append
(
line
[
len
(
".. req:"
):])
continue
if
line
.
startswith
(
".. startsnippet-"
):
section
=
line
.
replace
(
".. startsnippet-"
,
""
)[:
-
1
]
continue
if
line
.
startswith
(
".. endsnippet-"
):
try
:
assert
section
is
not
None
assert
line
.
startswith
(
".. endsnippet-
%
s"
%
section
)
except
AssertionError
:
print
section
,
line
print
buf
print
req
raise
yield
section
,
""
.
join
(
buf
),
" "
.
join
(
req
)
section
=
None
buf
=
[]
req
=
[]
if
section
:
# No allowed to have comments/"startsnippet" inside block sections.
if
line
.
startswith
(
"VCL::"
):
continue
if
"include"
in
line
and
"devicedetect.vcl"
in
line
:
continue
buf
+=
[
line
]
if
__name__
==
"__main__"
:
rstfile
=
argv
[
1
]
for
name
,
testsnippet
,
req
in
parse
(
rstfile
):
with
open
(
"snippet-
%
s.vtc"
%
name
,
"w+"
)
as
fp
:
print
>>
fp
,
header
(
name
)
print
>>
fp
,
testsnippet
print
>>
fp
,
tailer
(
req
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment