Device Detection in C Varnish module
The project contains source code for the Varnish integration of 51Degrees' on-premise Device Detection engine.
The module is supported for Varnish 6.0.6 (LTS).
- gcc
- autoconf
- automake
- libvarnishapi-dev
- Varnish source
- libatomic
For Ubuntu based distributions gcc can be found on apt, use
$ sudo apt-get install gcc autoconf automake libvarnishapi-dev varnish
To install the module into an existing Varnish deployment,
first clone 51Degrees/device-detection-varnish repository with
$ git clone --recursive https://github.com/51Degrees/device-detection-varnish.git
This will also clone the dependent sub-module device-detection-cxx
and any of its' recursive sub-modules.
Move to the Varnish directory with
$ cd device-detection-varnish
and install the module with (NOTE: if Varnish source was installed using the package manager, its' files will be located under /usr/include/varnish
directory rather than /usr/local/include/varnish
. The environment variable VARNISHSRC
will need to be set to point to this location for the installation to succeed).
$ ./autogen.sh
$ ./configure --with-config=release|test --with-datafile=(optional)
$ make
$ sudo make install
Where --with-config
[optional] sets the version that will be built. release
and test
versions are identical, except that the test
version expose some additional functions to support the testing process. Only release
version is recommended for production. By default release
version is built.
--with-datafile
[optional] sets the data file used by the unit tests. This data file will also be copied on installation.
When varnish is installed in a non standard directory, please set the value of environment variable VARNISHSRC
to point to where the varnish source resides before running the configure
(e.g. export VARNISHSRC=/usr/include/varnish
).
The location of where the module will be installed can also be customised by setting the environment variable VMOD_DIR
before running the configure
.
Then run the included tests with the following command. A test
version is required for this to succeed:
$ make check
This will all pass if the local installation was successful.
Before start matching user agents, you may wish to configure the solution to use a different database for example.
These settings should be set before calling fiftyonedegrees.start
.
set_performance_profile
(defaults toDEFAULT
). Set the performance profile.set_drift
(defaults to0
). Set the drift value.set_difference
(defaults to0
). Set the difference value.set_max_concurrency
(defaults is determined by the performance profile). Set the expected concurrent detection requests.set_allow_unmatched
(defaults isNO
). Set whether unmatched node should be allowed.set_use_performance_graph
(defaults is determined by the performance profile). Set whether the performance optimized graph should be used.set_use_predictive_graph
(defaults is determined by the performance profile). Set whether the predictive optimized graph should be used.set_delimiter
(defaults to','
). Sets the delimiter to separate values with.set_properties
(defaults to all properties). Sets the properties to initialise.
The easiest way to view full usage information is to run the command:
man vmod_fiftyonedegrees
to display all the functions with examples.
An example configuration file is included in this repository. It shows how to add device information to HTTP headers.
In the init block is where you should set any settings and initialise the resource manager.
import fiftyonedegrees;
sub vcl_init {
# Initialise the resource manager with the data file.
fiftyonedegrees.start("/home/51Degrees/data/51Degrees.dat");
}
Matching can be done is two ways.
To get properties using the device's User-Agent use:
sub vcl_deliver {
# This sets resp.http.X-IsMobile to "True"/"False".
set resp.http.X-IsMobile = fiftyonedegrees.match_single(req.http.user-agent, "IsMobile");
}
To get properties from all the relevant HTTP headers from the device use:
sub vcl_deliver {
# This sets resp.http.X-IsMobile to "True"/"False".
set resp.http.X-IsMobile = fiftyonedegrees.match_all("IsMobile");
}
To enable client-hint matching, add the set_resp_headers
to the vcl_deliver
block. This adds the Accept-CH
header to the response if
it is supported by the browser. The client-hint headers sent by the browser
are then automatically used by the match_all
method.
sub vcl_deliver {
# Enable client-hints
fiftyonedegrees.set_resp_headers();
# Use the match_all as above.
set resp.http.X-IsMobile = fiftyonedegrees.match_all("IsMobile");
}
The value of the header is set to a comma separated list of values (comma delimited is the default behaviour, but the delimiter can be set explicitly with set_delimiter
), these are in the same order the properties are listed in the config file. So setting a header with the line:
set resp.http.X-Device = fiftyonedegrees.match_all("HardwareName,BrowserName,PlatformName");
will give a header named X-Device
with a value like Desktop,Firefox,Ubuntu
. Alternatively, headers can be set individually like:
set resp.http.X-HardwareName = fiftyonedegrees.match_all("HardwareName");
set resp.http.X-BrowserName = fiftyonedegrees.match_all("BrowserName");
set resp.http.X-PlatformName = fiftyonedegrees.match_all("PlatformName");
giving three separate headers.
Start Varnish using the example VCLs within the device-detection-varnish/examples/hash
directory with (NOTE: The data file path used by the start
API in the vcl_init
block will need to be updated before proceed):
$ varnishd -f /path/to/examples/hash/gettingStarted.vcl -a localhost:8080 -d
Then, type start
to launch the worker process.
In a Linux environment, the headers can be viewed with the command:
$ curl localhost:8080 -I -A "Mozilla/5.0 (iPhone; CPU iPhone OS 11_2 like Mac OS X) AppleWebKit/604.4.7 (KHTML, like Gecko) Mobile/15C114"
which will give the following response:
HTTP/1.1 200 OK
...
X-IsMobile: True
...