Golang and WURFL: an Overdue Marriage

Golang and WURFL: an Overdue Marriage

It does not matter how slowly you GO as LANG as you do not stop” – Confucius, slightly adapted

The Golang WURFL Opportunity

By Luca Passani, CTO @ScientiaMobile
infuze-golang-button

Here at ScientiaMobile, we have heard requests over the last several years for a WURFL API that supported the Go programming language (AKA golang). Technically speaking, the idea of supporting golang has been attractive. But then again, a lot of other languages and technologies were worthy of WURFL support. We had to prioritize. Compared to other opportunities in the industry, golang consistently fell a little short.

Nevertheless, we would see many (mostly lame) attempts to bridge the gap between WURFL and golang pop up around the Internet. To us, this was a clear indication that something had to be done.

Be the First to Use WURFL InFuze for Golang!

Last summer we got one of our engineers on the case. He came up with a functioning Go module. The golang WURFL module is still unreleased. Here at ScientiaMobile, we would love to work with someone who already uses golang and can deploy the module in a real-world environment.

We will assist that person or company in the installation/deployment of the module in order to ensure that it functions as advertised. You can contact us through our Inquiry Form.

Looking forward to hearing from you,

 

Luca Passani – CTO

Integrating WURFL Capabilities with Golang

The WURFL package comes with 2 golang types, Wurfl and Device,  that make the use of our WURFL InFuze C API more friendly to the Go programmer

The following example should be pretty straightforward for anyone with a smattering of Go:

package main
import (
  "Fmt"
  "wurfl"
)

func main() {

 wengine, err = wurfl.Create("./wurfl.zip", nil, wurfl.WurflEngineTargetHighAccuray, wurfl.WurflCacheProviderDoubleLru, "100000,30000")

 ua := "ArtDeviant/3.0.2 CFNetwork/711.3.18 Darwin/14.0.0"

 device, err := wengine.Lookup(ua)

 deviceid, err := device.GetDeviceId()
 fmt.Println(deviceid)
 fmt.Println(device.GetCapability("device_os"))
 fmt.Println(device.GetVirtualCapability("is_android"))

 device.Destroy()
 wengine.Destroy()
}

Since we are using Golang callbacks from C, you will need to set GODEBUG=cgocheck=0 for the package to run when passing references. This is similar to what is needed with other packages, such as go-curl.

The WURFL Go module is currently available for Linux/Mac-OS platforms.

Usage

Here are snippets from our internal documentation for “WURFL Go”

Engine Target Possible Values

const (
    WurflEngineTargetHighAccuray     = C.WURFL_ENGINE_TARGET_HIGH_ACCURACY
    WurflEngineTargetHighPerformance = C.WURFL_ENGINE_TARGET_HIGH_PERFORMANCE
)

Cache Provider Possible Values

const (
    WurflCacheProviderNone      = C.WURFL_CACHE_PROVIDER_NONE
    WurflCacheProviderLru       = C.WURFL_CACHE_PROVIDER_LRU
    WurflCacheProviderDoubleLru = C.WURFL_CACHE_PROVIDER_DOUBLE_LRU
)

Match Type

const (
    WurflMatchTypeExact           = C.WURFL_MATCH_TYPE_EXACT
    WurflMatchTypeConclusive      = C.WURFL_MATCH_TYPE_CONCLUSIVE
    WurflMatchTypeRecovery        = C.WURFL_MATCH_TYPE_RECOVERY
    WurflMatchTypeCatchall        = C.WURFL_MATCH_TYPE_CATCHALL
    WurflMatchTypeHighPerformance = C.WURFL_MATCH_TYPE_HIGHPERFORMANCE
    WurflMatchTypeNone            = C.WURFL_MATCH_TYPE_NONE
    WurflMatchTypeCached          = C.WURFL_MATCH_TYPE_CACHED
)

Type Device

type Device struct {
    Device C.wurfl_device_handle
    Wurfl  C.wurfl_handle
}

Func (*Device) Destroy

func (d *Device) Destroy()

func (*Device) GetCapabilities

func (d *Device) GetCapabilities(caps []string) []string

func (*Device) GetCapability

Get a single Capability

func (d *Device) GetCapability(cap string) string

func (*Device) GetDeviceId

Get wurfl_id string from device handle

func (d *Device) GetDeviceId() (string, error)

 

func (*Device) GetMatchType

Get type of Match occurred in lookup

func (d *Device) GetMatchType() int

 

func (*Device) GetVirtualCapability

Get Virtual Capability

func (d *Device) GetVirtualCapability(vcap string) string

 

type Wurfl

type Wurfl struct {
    Wurfl C.wurfl_handle
}

func Create

func Create(Wurflxml string, Patches []string, CapFilter []string, EngineTarget int, CacheProvider int, CacheExtraConfig string) (*Wurfl, error)

Create the wurfl engine.Parameters : Wurflxml : path to the wurfl.xml/zip file Patches : slice of paths of patches files to load CapFilter : list of capabilities used; allow to init engine without loading all 500+ caps EngineTarget : either WurflEngineTargetHighPerformance or WurflEngineTargetHighAccuray CacheProvider : WurflCacheProviderLru or WurflCacheProviderDoubleLru CacheExtraConfig : size of single or double lru caches in the form “100000” or “100000,30000”

func (*Wurfl) Destroy

Destroy the wurfl engine

func (w *Wurfl) Destroy()

func (*Wurfl) GetApiVersion

get api version

func (w *Wurfl) GetApiVersion() string

func (*Wurfl) LookupRequest

Lookup Request and return Device handle

func (w *Wurfl) LookupRequest(r *http.Request) (*Device, error)

func (*Wurfl) LookupUserAgent

Lookup useragent and return Device handle

func (w *Wurfl) LookupUserAgent(ua string) (*Device, error)