infuze node.js user guide

WURFL InFuze Module for Node.js: User Guide

This document is about the Node.js platform and how you, a developer or a sysadmin, would install and configure the WURFL Module for Node.js on Unix/Linux and Windows systems.

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 the Node.js Package

Starting from WURFL 1.6.0.0, the Node.js module is dependent on the nan Native Abstractions for Node.js and supports Node.js from v0.12. Starting with WURFL 1.6.2.2, this dependency is declared in the package.json and will not need to be installed separately. You can install nan using the official Node Package Manager by typing:

npm install -g --save nan

We provide a nodejs-mod_wurfl-XYZ.tgz archive containing all the required files to install our module for Node.js and a README, where XYZ stands for the currently used WURFL API version. Please note that Node.js modules support only three digits version numbers.

In this archive you will also find some JavaScript examples on how to configure and test WURFL through Node.js.

Before installing the WURFL Node.js module make sure that both Node.js version 0.10.26 (or greater) and NPM (the Node.js tool to manage Node modules) are installed on your system.

Installing WURFL Node.js Module on Linux/Unix/MacOSX/Windows systems

As you can see from the official documentation, NPM works in two modes. Local mode is the default and, in this mode, you can choose where to install the node modules by simply switching directories prior to launching an NPM installation. When NPM is instead set in global mode (using the -g option), NPM installs the packages and the binaries into the directories specified by the install prefix used at the time when NPM was installed.

Once you have downloaded the Node.js module from your ScientiaMobile account, you can install the WURFL Node.js module in global mode:

npm install -g nodejs-mod_wurfl-1.8.0.tgz

During the installation process NPM may show warnings regarding unmet dependencies. This is unrelated to WURFL and depends on which version of NPM you are using and how those dependencies are handled by NPM itself.

Usage

The usage of WURFL from Node.js module is very easy. All the initialization phase is encapsulated in WurflInFuze.js (more on this later on), so it is enough to specify some parameters and let the module initialize() function build the engine. Here is a very basic sample configuration:

var config = {
    root: "./wurfl.zip",
    engine_target: "HIGH_PERFORMANCE",
    useragent_priority: "OVERRIDE_SIDELOADED_BROWSER_USERAGENT",
    cache: { type: "double-lru",max_useragents: 10000, max_devices: 3000  },
}

This will build a working engine in the wurfl global variable, so you will be able to obtain a device from a lookup and ask for its various properties and capabilities:

console.log("WURFL Info: " + wurfl.getInfo());
console.log("WURFL API Version: " + wurfl_nodejs_module.WurflAPIVersion());
console.log("WURFL Last Load Time: " + wurfl.getLastLoadTime());

console.log("Testing lookup function using a user agent string: ");
var device =  wurfl.lookupUseragent("SonyEricssonK700i/R2AC SEMC-Browser/4.0.2 Profile/MIDP-2.0 Configuration/CLDC-1.1");

console.log("----Device info----");
console.log("Device ID is: " + device.getDeviceId());
console.log("Is this an iOS? " + device.getVirtualCapability("is_ios"));
console.log("Is this an Android? " + device.getVirtualCapability("is_android"));

Please note that all cleanup/destroy actions are automatically handled by the NodeJS garbage collection mechanism.

You can find more complex examples, like executing a lookup with full HTTP request headers to increase accuracy and/or using WURFL as a server in the test/test_wurfl.js and test/test_cli.js examples.

WURFL Node.js Module's function list

Our module exposes a set of functions to be used to setup WURFL, query WURFL for specific capabilities, get general purpose information, and so on.

WURFL methods (class Wurfl, maps to InFuze wurfl_handle)

Function Description Availability (WURFL version)
setRoot(path_to_root_xml) This function sets the root WURFL data file to be used by WURFL to a specific path in your file system. Please note that if you plan to use the updater feature, you MUST use a compressed (i.e, ZIP or XML.GZ) wurfl data file. 1.5.1.2
addPatch(path_to_patch_xml) This function adds a patch to WURFL by taking the path to the patch xml file. 1.5.1.2
addRequestedCapability(capability_name) Adds a new capability to the capabilities filter. If not used, all capabilities are loaded 1.5.1.2
setEngineTarget(wurfl_engine_target) Sets the WURFL Engine Target to either HIGH_ACCURACY or HIGH_PERFORMANCE. 1.5.1.2
getEngineTarget() This function returns the selected engine target. 1.5.1.2
setUserAgentPriority(useragent_priority) sets the useragent priority to either OVERRIDE_SIDELOADED_BROWSER_USERAGENT or USE_PLAIN_USERAGENT 1.5.2
getUserAgentPriority() return the user agent priority (either OVERRIDE_SIDELOADED_BROWSER_USERAGENT or USE_PLAIN_USERAGENT) 1.5.2
setCacheProvider(cache_mode, max_useragents, max_devices) This function sets the WURFL Cache provider to be used. Choose "cache_mode" between 0 (no cache), 1 (single LRU cache) or 2 (double LRU cache). If you choose the single LRU cache you also need to pass a "max_useragents" integer which tells how many user agents WURFL can cache. If you choose the double LRU cache instead then you also need to pass a "max_devices" integer which tells how many devices WURFL can cache. 1.5.1.2
load() Loads the WURFL Instance with the previously selected modes (engine target, cache, root data file..). 1.5.1.2
lookupUseragent(useragent) This function is responsible to query WURFL for a device matching the passed "useragent" as a string. It returns a wurfl_device_handle structure. 1.5.1.2
lookupWithHeaderResolverFunction(header_resolver) This function is responsible to query WURFL for a specific device. The header_resolver function passed as a parameter must tell WURFL how to retrieve the header values. Please note that the header-retrieval functions should be case-insensitive. It returns a wurfl_device_handle structure. 1.5.1.2
getDevice(device_id) This function is responsible to query WURFL for a specific device matching a specific wurfl device identifier as a string. It returns a wurfl_device_handle structure. 1.5.1.2
getLastLoadTime() This function returns a string describing the timestamp of the latest successful WURFL load. 1.5.1.2
getInfo() This function returns a string describing some information regarding the loaded WURFL database and optional patch files. 1.5.1.2
setUpdaterLogPath(file_path) Instructs the internal WURFL InFuze updater to log to file any operation/error. If not used, the updater will not log anything. 1.8.3.0
setUpdaterDataURL(url) Sets remote data file URL to be downloaded via internal WURFL InFuze updater. This is the only MANDATORY call if you want to use the InFuze Updater 1.8.3.0
setUpdaterDataFrequency(check_frequency) Sets how often the updater checks for any new/updated WURFL data file to be downloaded and used by the engine (DAILY (default) or WEEKLY). 1.8.3.0
setUpdaterDataURLTimeouts(connection_timeout, data_transfer_timeout) Sets internal WURFL InFuze Updater timeouts, in milliseconds. The values are mapped to `curl` `--connect-timeout` and `--max-time` parameters (after millisecs-to-secs conversion). Connection timeout has a WURFL InFuze default value of 10 seconds (10000 ms) and refers only to connection phase. Passing 0 will use `curl` value "no timeout used". Data transfer timeout has a InFuze default value of 600 seconds (600000 ms). Passing 0 will use `curl` default value "no timeout used". So, pass 0 to either parameter to invoke `curl` "no timeout used" behaviour. Pass -1 to either parameter to use WURFL InFuze default values (10 secs, 600 secs). The specified timeouts (if any) are only used in the synchronous (i.e., `updaterRunonce()`) API call. The asynchronous background updater invoked by `updaterStart()`/`updaterStop()` always runs with `curl` behaviour and timeouts (i.e., it will wait "as long as needed" for a new data file to be downloaded) 1.8.3.0
updaterStart() Starts the asynchronous WURFL InFuze background update thread. 1.8.3.0
updaterStop() Stops the asynchronous WURFL InFuze background update thread. 1.8.3.0
updaterRunonce() Call a WURFL InFuze synchronous update. 1.8.3.0

WURFL Device methods (class WurflDevice, maps to wurfl_device_handle)

Function Description Availability (WURFL version)
getDeviceId() This function retrieves the deviceId of a specific wurfl_device_handle as a string. 1.5.1.2
getRootId() This function retrieves the root device identifier of a specific wurfl_device_handle as a string. 1.5.1.2
getOriginalUseragent() Returns the original useragent of this device (as of WURFL database). 1.5.1.2
getNormalizedUseragent() Returns the normalized useragent of this device. 1.5.1.3
isActualDeviceRoot() Tells if this device is a root device in the device hierarchy. 1.5.1.2
hasCapability(cap) Tells if this device has a capability named "cap". 1.5.1.2
hasVirtualCapability(vcap) Tells if this device has a virtual capability named "vcap". 1.5.1.2
getCapability(cap) Gets the capability value of the capability named "cap" as a string. 1.5.1.2
getVirtualCapability(vcap) Gets the virtual capability value of the virtual capability named "vcap" as a string. 1.5.1.2
getCapabilityAsInt(cap) Gets the capability value of the capability named "cap" as an integer. 1.5.1.2
getVirtualCapabilityAsInt(vcap) Gets the virtual capability value of the virtual capability named "vcap" as an integer. 1.5.1.2
getCapabilityAsBool(cap) Gets the capability value of the capability named "cap" as a boolean. 1.5.1.2
getVirtualCapabilityAsBool(vcap) Gets the virtual capability value of the virtual capability named "vcap" as a boolean. 1.5.1.2

IMPORTANT NOTE: For examples on how to use these functions, please take a look at the JavaScript examples provided within the archive.

The Internal WURFL InFuze Updater

Since InFuze 1.8.3.0, a native internal Updater Module is available.

All updater functions are accessed via

XXXUpdaterXXX
Wurfl class methods (see above). The WurflInFuze.js helper contains, in its prototype.initialize() method, the code needed to read the engine configuration and to set up the updater. More in detail, here is a snippet of a configuration also creating an updater (the "updater URL" is something in the form "https://data.scientiamobile.com/xxxxx/wurfl.zip", with "xxxxx" replaced with your personal access token located in your license account page):

var config = {
    root: "./wurfl.zip", // the only really mandatory parameter for the engine
    updater_log: "./wurfl_updater.log",
    updater_data_url: <your updater URL here>, // the only really mandatory parameter for the updater
    updater_frequency: "DAILY",
}

Some example client code using the pre-configured updater and issuing some synchronous and asynchronous calls can be found in test/test_cli.js.

If you prefer to fully configure and control the updater from your code, you can find a commented usage example in test/test_updater.js. Basically, this is an outline of what you have to do:

// OPTIONAL but highly suggested: set a log file
wurfl.setUpdaterLogPath("updater.log");

// MANDATORY: set data URL.
wurfl.setUpdaterDataURL("https://data.scientiamobile.com/<your access token>/wurfl.zip");

// OPTIONAL: set frequency of checks for an updated data file
wurfl.setUpdaterDataFrequency(1); // WEEKLY

A correctly configured updater can then be used in two ways:

  • syncronously, via the updaterRunonce() call
  • asynchronously with updaterStart() and updaterStop().

Here "asynchronous" means that a low level (i.e. libwurfl C) thread is created and run in background, while "synchronous" means that the call is blocking at the libwurfl C level.

// start a libwurfl blocking update
wurfl.updaterRunonce();

or

// start and stop a non-blocking libwurfl background thread
wurfl.updaterStart();
....
wurfl.updaterStop();

It is up to the client to determine when to start asynchronous (updaterStart()/updaterStop()) or synchronous (updaterRunonce()) update operations.

Please note that the only mandatory call for the updater module to work is setUpdaterDataURL(), which depends from a successful setRoot() call:

  • The WURFL data file and the path where it resides, specified in the setRoot() call, MUST have write/rename access: the old data file will be replaced (i.e, a rename operation will be performed) with his updated version upon successful update operation completion, and the directory will be used for remote file download, etc.

  • ScientiaMobile does not distribute uncompressed XML data files via updater. This means that, if you plan to use this feature, you MUST use a compressed (i.e, a ZIP or a XML.GZ) file as data root in the setRoot() call.

Setting explicitly the update frequency and timeouts is optional and have the defaults specified in the above documentation, while enabling file logging is optional but highly recommended.

Please note that setUpdaterDataFrequency() sets how often the updater checks for any updated data file, not how often the engine data file is actually updated.

The WURFL InFuze Updater functionality relies on availability and features of the well-known and widely available curl command-line utility. Among others, also a check for curl avaliabilty is done in the setUpdaterDataURL() call

Testing WURFL Node.js Module on all operating systems

Together with the WURFL Node.js module files, we provide some javascript example files in the "test" directory to demonstrate some common uses of the WURFL InFuze module for Node.js.

Assuming that you've installed our WURFL module into /usr/lib/node_modules/nodejs-mod_wurfl open a terminal and type:

 node /usr/lib/node_modules/nodejs-mod_wurfl/test/test_wurfl.js

A node.js server will be spawned listening to any IP address on port 9997. To check out some of your web browser capabilities just open a browser and go to localhost:9997. The produced output should look like this:

Device ID is: google_chrome
Is this an iOS App? false
Is this an Android App? false
Is this a Windows Phone App? false
Is this request coming from a desktop environment? true
Advertised browser: Chrome
Advertised browser version: 35.0
Advertised device OS: Mac OS X
Advertised device OS version: 10.9.3

As previously mentioned, we also provide a WurflInFuze.js wrapper which contains some useful utility functions, namely:

WurflInFuze.js utility functions

Function Description Availability (WURFL version)
initialize(config, debug) This function is responsible to initialize WURFL with a series of functionalities like the cache mode and a custom capabilities filter. The first parameter "config" is a dictionary in which the keys are the functionalities names and the values are the correspondent specific values. Please refer to test_cli.js test file (included into "test" directory) for a complete example. The second parameter "debug" is a boolean which, if set to true, makes the loading process verbose. 1.5.1.2
addRequestedCapabilities(capabilities) Adds a specific set of capabilities to the capabilities filter. The "capabilities" parameter must be an array of capability names. 1.5.1.2
lookupRequest(headers) This function is useful to get a wurfl_device having passed a list of custom header names and values in the "headers" parameter. This function returns a wurfl_device_handle structure. 1.5.1.2
lookup(obj) This function is the main interface to get a wurfl_device. You can choose to pass three types of objects to this function. Specifically, you can pass a simple user-agent string, or a function which describes how to get the header values from the request object or ultimately a dictionary of header names and values (as for lookupRequest). This function returns a wurfl_device_handle structure. 1.5.1.2

IMPORTANT NOTE: If you decide to use the WurflInFuze.js wrapper you may need to edit the default_wurfl_root variable, which must point to the WURFL database you're using. See also the set_root() documentation.


License

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.