• About Us
  • Blog
  • Basket
  • Account
  • Sign In
  •  

Golang API

What's Covered

This tutorial illustrates how to use the API in a Web project.

Code and Explanation

Full Source File
package main

import (
    "fmt"
    "net/http"
    "./src/pattern"
    "html/template"
    "os"
)

// Location of data file.
var dataFile = "../data/51Degrees-LiteV3.2.dat"

// Global Provider object.
var provider FiftyOneDegreesPatternV3.Provider
var properties []string

// Type definitions which represent the data  used to populate the web page
// templates.

// Object is populated when a match is performed after a request. Used to
// inject values into HTML template before serving to requesting device.
type exampleTemplate struct{
    DatasetPublishedDate string
    DatasetNextUpdate string
    DatasetVersion string
    DatasetName string
    DatasetDeviceCombinations int
    DeviceId string
    MatchMethod int
    Difference int
    Rank int
    DeviceData template.HTML
}

// Object is populated with  a dynamically generated html table containing a
// list of properties and their values retrieved from the match object.
type usingDetectionTemplate struct{
    DeviceData template.HTML
}

// Function sets up list of available properties in the data set, translating
// from SWIG Vector string to go array.
func getAvailableProperties() []string{
    // Get available properties from the data set.
    var _properties = provider.GetAvailableProperties()
    // Get the length of the VectorString and convert to an iterable type.
    var len = int(_properties.Size())
    // Variable to hold list of properties in a native type.
    var nativeProperties []string

    // Loop over VectorString of available properties and append them to  native
    // type array.
    for i := 0; i < len; i++{
        nativeProperties = append(nativeProperties, _properties.Get(i))
    }

    return nativeProperties
}

// Http response handlers.
// Index
func handler(w http.ResponseWriter, r *http.Request) {
    templ, err := template.ParseFiles("html/index.html")
    err = templ.Execute(w, nil)
    checkError(err)
}

// Using Detection
func usingDetection(w http.ResponseWriter, r *http.Request) {
    // Get using-detection page HTML tmeplate.
    templ, err := template.ParseFiles("html/using-detection.html")
    // Get a match with the request User-Agent.
    match := provider.GetMatch(r.Header.Get("User-Agent"))
    // Variable to hold dynamically generated list of properties and their
    // values.
    var deviceData string

    // Dynamically build an HTML list of all the available properties in the
    // data set and their values retrieved from the match object.
    for _,property := range properties{
        values := match.GetValue(property)
        if values != "" {
            deviceData += "<li>" + property + ": " + values + "</li>"
        }else{
            deviceData += "<li>" + property + ": " + "Switch Data Set" + "</li>"
        }
    }
    // Populate usingDetectionTemplate struct
    d := &usingDetectionTemplate{
        DeviceData: template.HTML(deviceData)}

    // Execute template processor which injects values from type
    // usingDetectionTemplate and sends response to requesting device.
    err = templ.Execute(w, d)
    checkError(err)

    // Close the match object.
    FiftyOneDegreesPatternV3.DeleteMatch(match)
}

// Example page
func example(w http.ResponseWriter, r *http.Request) {
    // Define which properties are displayed on the example page.
    _properties := []string{"BrowserName", "BrowserVendor",
        "BrowserVersion", "DeviceType", "HardwareVendor", "IsTablet", 
        "IsMobile", "IsCrawler", "ScreenInchesDiagonal","ScreenPixelsWidth"}

    // Get example page HTML template.
    templ, err := template.ParseFiles("html/example.html")
    // Get a Match with the request User-Agent.
    match := provider.GetMatch(r.Header.Get("User-Agent"))
    // Variable to hold dynamically generated table.
    var deviceData string

    // Build property table dynamically to inject into template. Get values for
    // each property and append a row to the HTML table.
    for _,property := range _properties{
        values := match.GetValue(property)
        if values != "" {
            deviceData += "<tr><td><a href=\"https://51degrees.com/resources/" +
                "property-dictionary#"+ property + "\">" + property + "</a>" +
                "</td><td>" + values + "</td></tr>"
        }else{
            deviceData += "<tr><td><a href=\"https://51degrees.com/resources/" +
                "property-dictionary#"+ property + "\">" + property + "</a>" +
                "</td><td>Switch Dataset</td></tr>"
        }
    }

    // Populate exampleTemplate struct
    d := &exampleTemplate{
    DatasetPublishedDate: provider.GetDataSetPublishedDate(),
    DatasetNextUpdate: provider.GetDataSetNextUpdateDate(),
    DatasetVersion: provider.GetDataSetFormat(),
    DatasetName: provider.GetDataSetName(),
    DatasetDeviceCombinations: provider.GetDataSetDeviceCombinations(),
    DeviceId: match.GetDeviceId(),
    MatchMethod: match.GetMethod(),
    Difference: match.GetDifference(),
    Rank: match.GetRank(),
    DeviceData: template.HTML(deviceData)}

    // Execute template processor which injects values from type exampleTemplate
    // and sends response to requesting device.
    err = templ.Execute(w, d)
    checkError(err)

    // Release the Match object back to the pool.
    FiftyOneDegreesPatternV3.DeleteMatch(match)
}

func main() {
    fmt.Println("Starting Server...")

    // Create a new Provider.
    provider =
        FiftyOneDegreesPatternV3.NewProvider(dataFile)

    // Get available properties and assign to to global type.
    properties = getAvailableProperties()

    // Set the HTTP handler function.
    http.HandleFunc("/", handler)
    http.HandleFunc("/example", example)
    http.HandleFunc("/using-detection", usingDetection)

    // Start the Server and bind to port 8080.
    fmt.Println("Server at port 8080")
    err := http.ListenAndServe(":8080", nil)
    checkError(err)
}

func checkError(err error){
    if err != nil {
        fmt.Println("Fatal error", err.Error())
        os.Exit(1)
    }
}

Full Source File

Summary

In this tutorial you have seen how to use the detector in the context of a simple server to retrieve various properties from both a single User-Agent header and multiple HTTP headers. For a full list of properties and the data files they exist in please see the Property Dictionary.