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. If you are using NGINX Plus, please see the documentation for our NGINX Plus module here. > **Note:** Unlike NGINX Plus, you will still need to compile and link the NGINX module. 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](https://docs.scientiamobile.com/documentation/infuze/infuze-c-api-user-guide). Release notes for each API can be found [here](https://docs.scientiamobile.com/documentation/changelog/infuze-api-change-log). > WARNING > ------- > > SINCE MODULE VERSION 1.8.4.1 YOU NEED TO ADD A `wurfl_enable on;` COMMAND TO THE `http section` OF YOUR CONFIGURATION FILE,
OTHERWISE THE WURFL MODULE WILL NOT BE LOADED. THIS CHANGE IS PART OF A FEATURE ALIGNMENT, NECESSARY FOR ENTERPRISE USERS OF NGINX. >
Build WURFL Module -------------------------- We provide an installation script (`wurfl_nginx_mod_setup.sh`) which automatically installs the NGINX server and the WURFL NGINX module.
We strongly advise use of this script to quickly build NGINX with the WURFL module. Execute `wurfl_nginx_mod_setup.sh`, specifying the NGINX version as the first script parameter (`A.B.C`), and WURFL version as the second parameter (W.X.Y.Z): ```shell $ chmod +x ./wurfl_nginx_mod_setup.sh $ ./wurfl_nginx_mod_setup.sh A.B.C W.X.Y.Z ``` > **Tip**: Since NGINX 1.9.11, `dynamic modules` are supported. For WURFL NGINX module versions 1.8.1.0 and greater, you can choose to build it as a `dynamic module` or `embedded in NGINX`. If you want to build WURFL module as an NGINX `Dynamic module`, edit the **wurfl_nginx_mod_setup.sh** file, > uncomment the line `##./configure --with-debug --with-threads --with-cc-opt=-Wno-error --add-dynamic-module=../src` > and comment the line `./configure --with-debug --with-threads --with-cc-opt=-Wno-error --add-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](http://wiki.nginx.org/NginxInstallOptions) page of the NGINX wiki for full details.
> **Tip**: For significant performance enhancement, you might want to consider reinstalling PCRE with "just-in-time compilation", and then edit the **wurfl_nginx_mod_setup.sh** file adding `--with-pcre-jit` option to your `./configure` call : `./configure --with-pcre-jit --with-debug --with-threads . . . . . . .`
> **Tip**: If you choosed to build mod_wurfl as an NGINX Dynamic module, you should find the `ngx_http_wurfl_module.so` file in **/usr/local/nginx/sbin/nginx/modules**. ### Configuration Guide ------------------- Below is a sample `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. ```nginx # ... # -- Uncomment this if you are using NGINX Plus # -- or you compiled WURFL module with --add-dynamic-module (WURFL API version 1.8.1.0 or above / NGINX OSS 1.9.11 or above). #load_module modules/ngx_http_wurfl_module.so; # ... http { # ... # -- Command to enable WURFL module. Since WURFL module version 1.8.4.1, WURFL module is DISABLED BY DEFAULT. # -- Used to switch on/off WURFL module; if set 'off', NGINX will ignore all wurfl_* configuration. # -- If WURFL module is disabled, NGINX variables used to handle WURFL detection results (i.e: $wurfl_id , $wurfl_cap_is_smarttv...) are still valid but their values will be "empty string". # -- Valid values are on/off. Default value is off. wurfl_enable on; # -- 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 for seamless update of the 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 the wurfl_root file type. # -- Apply the wurfl_updater by setting your personal updater URL from the ScientiaMobile Customer Vault. If your license is expired, NGINX won't start with the Updater configured. # -- Valid values for Updater's checking frequency (how often the updater checks for any new WURFL data file # -- to be downloaded and used by the engine) are DAILY or WEEKLY. # -- Updater log file (wurfl-updater.log) will be located in the "wurfl_root" folder. The folder and wurfl.zip file should be writable, and a wurfl.zip file must already be present in order for the Updater to determine whether or not it has to pull an update. # -- by an 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 cache: one of the following wurfl_cache_lru 100000; #wurfl_cache_null; # -- 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_info; #wurfl_request_property wurfl_api_version; #wurfl_request_property wurfl_last_load_time; #wurfl_request_property wurfl_normalized_useragent; # -- WURFL user requested static capabilities (as an example, this is not a complete list) #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 # # 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 # # 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 - Whitelist hit - resource: - regex: (rule name:) # -- WURFL: Server - Blacklist hit - resource: - regex: (rule 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_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 static capabilities needed in webapp (as an example, this is not a complete list) #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; } # ... } } ``` Important Note -------------- If you are using NGINX with the builtin wurfl updater make sure that the folder that contains the wurfl.zip file is writable to all. Even if nginx starts as root, worker child processes might run as unpriviliged user ("nobody" by default) and this prevents workers engine updater to correctly update the wurfl.zip file during normal operations. WURFL NGINX Module command table -------------------------------------- The following table shows directives which can be applied to configure and use the WURFL NGINX Module.
Section Syntax Description Availability
**http** **wurfl_enable** Enable/Disable the WURFL module. Since version 1.8.4.1, the WURFL module is disabled by default and will need to be enabled: `wurfl_enable on;`
Otherwise all WURFL commands will be ignored and the WURFL module will not be loaded.
Possible values: on/off. Default value: off.
1.9
**http** **wurfl_root** Defines the location (path) of the WURFL data file. 1.4
**wurfl_updater** Allows seamless updates of the 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.
Please note that in the case your license is expired, NGINX won't start with Updater configured.
• the `updater checking frequency` (how often the updater checks for any new WURFL data file to be downloaded and used by the engine) 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_default**
or
**wurfl_target_fast_desktop_browser_match**
or
**wurfl_target_performance**
or
**wurfl_target_accuracy**
`These configuration options are deprecated and will be removed in a future release.` 1.4
**wurfl_cache_lru**
or
**wurfl_cache_null**
In order to increase performance while processing real HTTP traffic, we suggest setting up a `LRU` cache. The `LRU` caching strategy will speed up lookup operations on processed User Agents by keeping them in an LRU map. By default the cache will be set to 30000 entries which accounts for 7 to 10 MB of additional memory usage. Specific concerns regarding memory usage apart, users are advised to size their cache generously (100,000 or more) to increase performance. For more information, please see [LRU Cache Mechanism](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)). 1.4
**wurfl_request_capability** Enables injection of WURFL Static Capabilities/Virtual Capabilities in the HTTP request headers with your specified parameter(s).
Syntax: **wurfl_request_capability <static capability/virtual capability name>**
You can find the complete list of WURFL Static Capabilities and WURFL Virtual Capabilities [here](https://www.scientiamobile.com/capabilities).
If a Static Capability/Virtual Capability is specified in a `wurfl_request_capability` command, WURFL NGINX module set a NGINX variable whose name is
**wurfl_cap_**
1.4
**wurfl_useragent_priority_override_sideloaded_browser_useragent**
or
**wurfl_useragent_priority_use_plain_useragent**
`These configuration options are deprecated and will be removed in a future release.` 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 `This property is deprecated and will be removed in a future release.` 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 `This property is deprecated and will be removed in a future release.` 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: ```shell 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](http://www.rackspace.com/knowledge_center/article/ubuntu-and-debian-adding-an-nginx-init-script). 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: ```shell sudo ps aux | grep nginx ``` To stop the NGINX service manually, you can take advantage of the `pid file` to identify process ID. ```shell 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.](https://docs.scientiamobile.com/img/nginx_phpinfo.jpg "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 // 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 that 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: ```shell sudo apt-get install php5-fpm ``` Then run `PHP5-FPM` in the background, using the following `init.d` script to start the process: ```shell 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 //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. ------- **© 2024 ScientiaMobile Inc.
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.