infuze nginx module user guide

WURFL InFuze Module for NGINX: User Guide

This document is aimed at developers and system administrators who intend to install and configure the WURFL InFuze Module for Nginx on Unix, Linux, and other Unix-based systems.

Installing libwurfl

IMPORTANT: Installing libwurfl

In order for the Module to work it is ESSENTIAL that the libwurfl library is installed on your system. libwurfl is provided in your Customer Vault/FileX.

If you have not already installed libwurfl, instructions can be found here. Release notes for each API can be found here.

Installing NGINX

Unlike other web server applications (e.g. Apache), NGINX web server does not support dynamically linked or third-party modules. You are required to download and compile the entire source code, including the WURFL Module extension for NGINX.

Install Prerequisites on Ubuntu/Debian

Run the following commands to ensure that your system's package database and installed programs are up to date, and then install the dependent packages:

sudo apt-get update
sudo apt-get upgrade --show-upgraded
sudo apt-get install libpcre3-dev build-essential libssl-dev
sudo apt-get install libpcap-dev libnet1-dev libyaml-0-2 libyaml-dev
sudo apt-get install zlib1g zlib1g-dev libcap-ng-dev libcap-ng0

Install Prerequisites on RedHat/Fedora/CentOS

Before you compile NGINX, you will need to install the following dependent packages:

yum groupinstall "Development Tools"
yum install libpcap pcre-devel zlib-devel openssl-devel

Download and Compile NGINX

You may already have an instance of NGINX running, in which case we recommend that you stop. You will need to recompile NGINX to include nginx-mod_wurfl, a WURFL module extension for NGINX.

Tip: We also provide an installation script named "wurfl_nginx_mod_setup.sh" which automatically installs the NGINX server and the WURFL NGINX Module. We strongly advise use of this script to easily build NGINX with the WURFL Module.

Build WURFL module embedded in NGINX or as a NGINX Dynamic Module

Since NGINX 1.9.11, dynamic modules are supported. Starting from WURFL NGINX module version 1.8.1.0 you can choose to build it as a shared object.
Edit the wurfl_nginx_mod_setup.sh file, uncomment the line

##./configure --with-debug --with-threads --add-dynamic-module=../src

and comment the line

./configure --with-debug --with-threads --add-module=../src

Specify NGINX version as a first script parameter, and WURFL version as the second script parameter. For example:

chmod +x ./wurfl_nginx_mod_setup.sh
./wurfl_nginx_mod_setup.sh 1.10.3 1.8.3.0

Alternatively, you may install the module yourself following the steps below:

For this example, the source files will be downloaded to the /opt/nginx/ directory (you must manually create the 'nginx' directory inside /opt/ - mkdir nginx). Download and Extract the nginx-mod_wurfl (nginx-mod_wurfl-1.8.0.0.tar) file to the /opt/nginx/ folder, which consists of the source code of module extension, by running the following commands:

cd /opt/nginx
tar xvf nginx-mod_wurfl-1.8.3.0.tar

Check out the NGINX download page for the URL of the latest stable release, and then issue the following commands to obtain it (substituting a newer link if necessary):

wget http://nginx.org/download/nginx-1.10.3.tar.gz
tar zxvf nginx-1.10.3.tar.gz
cd nginx*

Before compiling the NGINX server, be sure to append --add-module option if you want to build mod_wurfl embedded in NGINX

./configure --with-debug --with-threads --add-module=../src

or --add-dynamic-module option if you want to build mod_wurfl as a NGINX Dynamic Module (NGINX version >= 1.9.11, WURFL NGINX module version >= 1.8.1.0)

./configure --with-debug --with-threads --add-dynamic-module=../src

Tip: By default, NGINX will be installed in /usr/local/nginx, which, although a good place, means that the main NGINX binary will be found in /usr/local/nginx/sbin/nginx. Have a look at the Install Options page of the NGINX wiki for full details.

To build and install NGINX with the above configuration, use the following command sequence:

make
sudo make install

Tip: For significant performance enhancement, you might want to consider reinstalling PCRE with "just-in-time compilation", and then adding --with-pcre-jit option to NGINX builds.

Tip: If you choosed to build mod_wurfl as a NGINX Dynamic Module, you should find the ngx_http_wurfl_module.so file in /usr/local/nginx/sbin/nginx/modules .

Configuration Guide

Below is an example nginx.conf configuration file for WURFL setup. Please refer to the Module Command Table below which explains each element in detail (Table 1), their parameters, constraints, and default recommended settings.

...

# -- Since WURFL API version 1.8.1.0 / NGINX 1.9.11, it is possible to build WURFL module as dynamic module.
# -- Uncomment this if WURFL module is compiled with --add-dynamic-module
#load_module modules/ngx_http_wurfl_module.so;

...

http {
    ...

    # -- WURFL root definition, one per config. User MUST specify this path in order to make WURFL engine correctly start.
    wurfl_root      /usr/share/wurfl/wurfl.zip;

    # -- WURFL Updater allows seamless update of WURFL engine with new data downloaded from Scientiamobile.
    # -- Updater configuration must be done after wurfl_root
    # -- WURFL file should be either .zip or .xml.gz and match wurfl_root file type
    # -- Put your personal updater url taken from Scientiamobile customer Vault.
    # -- Valid values for the update frequency are DAILY,WEEKLY
    # -- Updater log file (wurfl-updater.log) may be found in "wurfl_root" folder. The folder and wurfl.zip file must be writable
    # -- by NGINX process
    #wurfl_updater   https://data.scientiamobile.com/xxxxx/wurfl.zip DAILY;

    # -- WURFL patches definition (as much as needed, patches will be applied in the same order as specified in this conf file)
    #wurfl_patch     /path/to/patch1.xml;
    #wurfl_patch     /path/to/patch2.xml;
    #wurfl_patch     /path/to/patch3.xml;

    # Increase the variable hash size
    variables_hash_max_size 1024;
    variables_hash_bucket_size 1024;

    # -- WURFL engine target: one of the following (default is performance)
    wurfl_target_performance;
    #wurfl_target_accuracy;

    # -- WURFL UA priority: one of the following (default is wurfl_useragent_priority_override_sideloaded_browser_useragent)
    wurfl_useragent_priority_override_sideloaded_browser_useragent;
    #wurfl_useragent_priority_use_plain_useragent;

    # -- WURFL cache: one of the following
    #wurfl_cache_null;
    wurfl_cache_double_lru 10000,3000;

    # -- WURFL properties (formerly "WURFL default variables")
    # -- Since WURFL API version 1.8.0.0, WURFL default variables except "wurfl_id" are no longer injected by default
    # -- and have to be explicitly specified.
    #wurfl_request_property  wurfl_root_id;
    #wurfl_request_property  wurfl_isdevroot;
    #wurfl_request_property  wurfl_useragent;
    #wurfl_request_property  wurfl_engine_target;
    #wurfl_request_property  wurfl_useragent_priority;
    #wurfl_request_property  wurfl_info;
    #wurfl_request_property  wurfl_api_version;
    #wurfl_request_property  wurfl_last_load_time;
    #wurfl_request_property  wurfl_normalized_useragent;

    # -- WURFL user requested capabilities (as an example, this is not a complete list)
    #wurfl_request_capability is_console;
    #wurfl_request_capability is_tablet;
    #wurfl_request_capability is_wireless_device;

    # -- WURFL user requested virtual capabilities (as an example, this is not a complete list).
    # -- Since WURFL API version 1.7.1.0, virtual capabilities are no longer injected by default
    # -- and have to be explicitly specified.
    #wurfl_request_capability advertised_device_os;
    #wurfl_request_capability is_android;

    ...

    server {

        ...

        # -- WURFL injection rules
        #
        # -- The following rule lists define which urls hasn't/has to be injected with wurfl data.
        #
        # -- The urls will be processed in this manner:
        #
        # -- Check if a wurfl_do_not_process_url regex matches the url. If yes, the url
        # -- itself will not be injected and no further checks will be made
        # -- If no wurfl_do_not_process_url match, check if a wurfl_process_url regex
        # -- matches the url. If yes, the url itself will be injected
        #
        # -- The fallback behaviour in case the url doesn't match any
        # -- wurfl_do_not_process_url/wurfl_process_url rule is:
        # -- INJECTION if the list of wurfl_process_url is empty
        # -- NO INJECTION if the list of wurfl_process_url is not empty
        #
        #
        # ---- Black list: defines which urls hasn't to be injected with wurfl data
        # ---- syntax: wurfl_do_not_process_url <url regex> <rule name>
        #
        # wurfl_do_not_process_url .*\.(gif|jpeg|png|css) "Static contents";
        # wurfl_do_not_process_url .*\/img\/.* "All in img folder;
        #
        #
        # ---- White list: defines which urls has to be injected with wurfl data
        # ---- syntax: wurfl_process_url <url regex> <rule name>
        #
        # wurfl_process_url .*\.(php|php4|php5) "Php scripts";
        # wurfl_process_url .*\.(jsp|asp) "Jsp/Asp scripts";

        # -- Trace wurfl injections (default value = off)
        # -- The log format is:
        # -- WURFL: Server <server name> - Whitelist hit - resource: <url> - regex: <url regex> (rule name:<rule name>)
        # -- WURFL: Server <server name> - Blacklist hit - resource: <url> - regex: <url regex> (rule name:<rule name>)
        # -- <server name> is the value of server_name property, or, if empty, a number indicating
        # -- which server section the log is relative to
        #
        # wurfl_log_header_injection on;

        ...

        # Example of uses with PHP FastCGI (Note: PHP is not a requirement!)
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
            include        fastcgi_params;

            ############ WURFL data passed to fastcgi PHP scripts
            #
            ######## WURFL properties (formerly "WURFL default variables"): add here to make them available to fastcgi PHP scripts.
            ######## Property "wurfl_id" is injected by default (see http section) and could be specified here
            fastcgi_param  WURFL_ID                         $wurfl_id;
            #fastcgi_param  WURFL_ROOT_ID                    $wurfl_root_id;
            #fastcgi_param  WURFL_ISDEVROOT                  $wurfl_isdevroot;
            #fastcgi_param  WURFL_ORIGINAL_USERAGENT         $wurfl_useragent;
            #fastcgi_param  WURFL_ENGINE_TARGET              $wurfl_engine_target;
            #fastcgi_param  WURFL_USERAGENT_PRIORITY         $wurfl_useragent_priority;
            #fastcgi_param  WURFL_INFO                       $wurfl_info;
            #fastcgi_param  WURFL_API_VERSION                $wurfl_api_version;
            #fastcgi_param  WURFL_LAST_LOAD_TIME             $wurfl_last_load_time;
            #fastcgi_param  WURFL_NORMALIZED_USERAGENT       $wurfl_normalized_useragent;
            #
            #
            ######## WURFL capabilities: headers injected by into Request by wurfl engine.
            ######## Add here to make them available to fastcgi PHP scripts.
            #
            #### specify the capabilities needed in webapp (as an example, this is not a complete list)
            #fastcgi_param  WURFL_IS_CONSOLE                 $wurfl_cap_is_console;
            #fastcgi_param  WURFL_IS_TABLET                  $wurfl_cap_is_tablet;
            #fastcgi_param  WURFL_IS_WIRELESS_DEVICE         $wurfl_cap_is_wireless_device;
            #
            #### specify the virtual capabilities needed in webapp (as an example, this is not a complete list)
            #fastcgi_param  WURFL_ADVERTISED_DEVICE_OS       $wurfl_cap_advertised_device_os;
            #fastcgi_param  WURFL_IS_ANDROID                 $wurfl_cap_is_android;
        }
        ...
    }
}

WURFL NGINX Module command table

The following table shows directives which can be applied to configure and use our WURFL NGINX Module.

Section Syntax Description Availability
http wurfl_root Defines the location (path) of the WURFL data file. 1.4
wurfl_updater Allows seamless update of WURFL engine with new data downloaded from Scientiamobile. This directive must follow wurfl_root.
It takes two parameters:
• the data url (taken from your personal Scientiamobile Vault account, choosing between two data file types: .zip or .xml.gz)
Take care that wurfl_root file type and wurfl_updater data url file types match so you may need to change the wurfl_root file type accordingly.
• the update frequency which you can choose between DAILY and WEEKLY.
In order to let the Updater perform its activities both the wurfl_root folder and file must be writable by NGINX.
The wurfl-updater.log file in wurfl_root folder will contains details on Updater activity.
1.8.3
wurfl_patch Adds one or more custom patch files to the WURFL repository. 1.4
wurfl_target_performance
or
wurfl_target_accuracy
You can choose between high-accuracy (WURFL_ENGINE_TARGET_HIGH_ACCURACY) or high-performance (WURFL_ENGINE_TARGET_HIGH_PERFORMANCE) targets. In High-Performance mode, desktop web browser detection is done programmatically without referencing the WURFL data. As a result, most desktop web browsers are returned as generic_web_browser WURFL ID for performance. If neither High-Performance or High-Accuracy are defined, High-Performance mode is enabled by default. 1.4
wurfl_cache_null
or
wurfl_cache_lru
or
wurfl_cache_double_lru
The caching strategies are also configurable. You can choose between NULL, LRU, or Double LRU cache mechanisms. The default is Double LRU, which is a two-cache strategy (one going from User-Agent to Device-Id, the other from Device-Id to Device). The default parameters are 30,000, 10,000 (maximum 30,000 elements for the User-Agent to device-id cache and maximum 10,000 elements for the device-id to device cache) and the values are in elements. The LRU cache comes with User-Agent to Device mapping only, and the NULL parameter will disable the cache mode. These parameters refer to the max capacity size of the cache itself in Kilobytes. For more information, please see LRU Cache Mechanism. 1.4
wurfl_request_capability Enables injection of WURFL Capabilities/Virtual Capabilities in the HTTP request headers with your specified parameter(s).
Syntax: wurfl_request_capability <capability/virtual capability name>
You can find the complete list of WURFL Capabilities and WURFL Virtual Capabilities here.
If a Capability/Virtual Capability is specified in a wurfl_request_capability command, WURFL NGINX module set a NGINX variable whose name is
wurfl_cap_<Capability/Virtual Capability name>
1.4
wurfl_useragent_priority_override_sideloaded_browser_useragent
or
wurfl_useragent_priority_use_plain_useragent
You can choose between wurfl_useragent_priority_override_sideloaded_browser_useragent (WURFL_USERAGENT_PRIORITY_OVERRIDE_SIDELOADED_BROWSER_USERAGENT) or wurfl_useragent_priority_use_plain_useragent (WURFL_USERAGENT_PRIORITY_USE_PLAIN_USERAGENT) user agent priorities. In High-Performance mode, desktop web browser detection is done programmatically without referencing the WURFL data. As a result, most desktop web browsers are returned as generic_web_browser WURFL ID for performance. The default user agent priority is wurfl_useragent_priority_override_sideloaded_browser_useragent. 1.5.2
wurfl_request_property Enables injection of WURFL Properties (see section WURFL Properties below) in the HTTP request headers.
Syntax: wurfl_request_property <variable name>
Not mandatory.
1.8
server wurfl_do_not_process_url A regular expression defining which urls hasn't to be injected with wurfl data. Syntax: wurfl_do_not_process_url <url regex> <rule name>
Not mandatory.
You can specify more than one wurfl_do_not_process_url
The urls will be processed in this manner:
Check if a wurfl_do_not_process_url regex matches the url.
• If yes, the url itself will not be injected and no further checks will be made.
• If no, check if a wurfl_process_url regex matches the url.
• • If yes, the url itself will be injected
The fallback behaviour in case the url doesn't match any wurfl_do_not_process_url/wurfl_process_url rule is:
• INJECTION if the list of wurfl_process_url is empty
• NO INJECTION if the list of wurfl_process_url is not empty
1.8
wurfl_process_url A regular expression defining which urls has to be injected with wurfl data.
Syntax: wurfl_process_url <url regex> <rule name>
Not mandatory.
You can specify more than one wurfl_process_url.
The urls will be processed in this manner:
Check if a wurfl_do_not_process_url regex matches the url.
• If yes, the url itself will not be injected and no further checks will be made.
• If no, check if a wurfl_process_url regex matches the url.
• • If yes, the url itself will be injected
The fallback behaviour in case the url doesn't match any wurfl_do_not_process_url/wurfl_process_url rule is:
• INJECTION if the list of wurfl_process_url is empty
• NO INJECTION if the list of wurfl_process_url is not empty
1.8
wurfl_log_header_injection Enable/disable logging of occurred injections.
You can choose between on/off
Not mandatory. (default value is off)
1.8

WURFL Properties

The WURFL NGINX module sets some useful convenience NGINX variables to retrieve information regarding the currently active WURFL configuration.
These variables are automatically calculated and are injected in HTTP requests if specified in a wurfl_request_property command.
Please note that the wurfl_id variable is injected by default so you don't have to sepcify it in a wurfl_request_property command.

WURFL Properties Table

Variable Name Contents Availability
wurfl_id Contains the device ID of the matched device. It is injected by default so you don't have to specify it in a wurfl_request_property command 1.4
wurfl_root_id Contains the device root ID of the matched device. 1.4
wurfl_isdevroot Tells if the matched device is a root device. Possible values are "TRUE" or "FALSE" 1.4
wurfl_useragent The original useragent coming with this particular web request 1.5.1
wurfl_api_version Contains a string representing the currently used Libwurfl API version 1.5.1
wurfl_engine_target Contains a string representing the currently set WURFL Engine Target. Possible values are "HIGH_ACCURACY", "HIGH_PERFORMANCE" or "INVALID" 1.5.1
wurfl_info A string containing information on the parsed WURFL data file and its full path 1.5.1
wurfl_last_load_time Contains the UNIX timestamp of the last time WURFL has been loaded successfully. 1.5.1
wurfl_normalized_useragent The normalized useragent. 1.5.1.3
wurfl_useragent_priority The user agent priority used by WURFL. 1.5.2

Running NGINX Web Server

Once you have configured NGINX and are ready to test the installion by launching the webserver, use the following command:

sudo /usr/local/nginx/sbin/nginx

Tip: This guide only instructs you on how to start and stop NGINX manually. There are many different online guides that shows how to build init scripts for NGINX, here is an example site.

To see if NGINX is running, go to your server's IP address. You should see a 'welcome to NGINX' message, indicating that NGINX is installed. Alternatively, check to see if the NGINX process is running by executing this command:

sudo ps aux | grep nginx

To stop the NGINX service manually, you can take advantage of the pid file to identify process ID.

sudo kill `cat /usr/local/nginx/logs/nginx.pid`

Verify WURFL Installation

At the end of the installation procedure, your NGINX web server will be enhanced with the new WURFL API capabilities to support a variety of use-cases that rely on your NGINX instance becoming aware of device information. Among other things, NGINX will augment HTTP requests with new headers such as: X-Wurfl-Is-Tablet, X-Is-Full-Desktop and the relative values as defined in WURFL. This will enable services deployed downstream to take advantage of device detection in the simplest way possible (getHeader() and similar).

Note: Pre-selected capabilities and header names are shown for this example (the actual choice of header names is configurable).

The WURFL Module for NGINX enables organizations to leverage device and browser information within the very tools, frameworks and programming languages that they have previously elected to use. For example, assuming that a RIM BlackBerry 8830 device requests a PHP phpinfo() page (assuming that PHP is installed), the following information would be returned by the system thanks to the WURFL NGINX Module:

Figure 1.

PHP variables now include HTTP headers that contain device information. This information can be leveraged by downstream applications to tailor the content to the capabilities of the requesting device. For example, assuming we choose the X-Wurfl-* notation for the environment variables or HTTP headers, the following PHP code can be used to determine if the requesting device is a tablet:

// PHP
if ($_SERVER['X-Wurfl-Is-Tablet'] == 'true') {
    //Do whatever makes sense for a tablet
}

Java, ASP.Net, Perl, Python and everything that can run in a CGI environment can take advantage of the functionality.

Running PHP Script on NGINX

In order to run the example script above, you will need to install PHP FastCGI. It is highly recommended you use PHP-FPM (FastCGI Process Manager) for its features and ease of installation. Use the following command to install the latest PHP-FPM package:

sudo apt-get install php5-fpm

Then run PHP5-FPM in the background, using the following init.d script to start the process:

sudo /etc/init.d/php-fpm start

At this point we are ready to create a simple test script. Test the capabilities filters with the following PHP script test.php to put in /usr/local/nginx/html:

//PHP - test.php
phpinfo(INFO_ENVIRONMENT);

The test.php script will return an extended result of what can be seen in Figure 1. You can use any kind of mobile device to load the site and see their unique device capabilities.

License

2017 ScientiaMobile Incorporated All Rights Reserved.

NOTICE: All information contained herein is, and remains the property of ScientiaMobile Incorporated and its suppliers, if any. The intellectual and technical concepts contained herein are proprietary to ScientiaMobile Incorporated and its suppliers and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret or copyright law. Dissemination of this information or reproduction of this material is strictly forbidden unless prior written permission is obtained from ScientiaMobile Incorporated.