userstack

package module
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2019 License: MIT Imports: 9 Imported by: 0

README

userstack

userstack is a Go client library for the apilayer userstack service; returning instant user-agent string lookups.

To use this client you will need an API access key. The free tier supports 10,000 monthly lookups, but over http-only. To get HTTPS Encryption you need a Basic plan or higher 🤷‍♂️.

The official documentation is found here.

If you are on a free account, initialize the client with secure false. Otherwise you'll get a 105 error:

Access Restricted - Your current Subscription Plan does not support HTTPS Encryption.


Technical bits:

Well-defined types are available: entity, device, category and api error.

Users can supply their own HTTP Client implementation through options, otherwise a default client is used.

Users can propogate a context, otherwise context.Background() is used by default.

This package may return a custom error, *ApiErr, which callers can assert to get at the raw code, type and info. If using go1.13 use errors.As for assertions, otherwise a regular type switch will do. Especially useful for 104 or ErrUsageLimitReached errors: monthly usage limit has been exceeded.

Crawler information is only available for Basic Plan or higher. So if you don't see this in the response, check your plan.

Example usage - single lookup (HTTP GET)

client, err := userstack.NewClient(key, false)
if err != nil {
    // handler err
}

ua := "Mozilla/5.0 (Linux; Android 9; Pixel 2 Build/PQ3A.190801.002; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.132 Mobile Safari/537.36 Instagram 109.0.0.18.124 Android (28/9; 420dpi; 1080x1794; Google/google; Pixel 2; walleye; walleye; en_US; 170693979)"

// context.Background() used internally if nil ctx is supplied.
stack, err := client.Detect(nil, ua) 
if err != nil {
    var e *userstack.ApiErr
    if errors.As(err, &e) { 
        // handler error of type ApiErr
    }
    // handler err
}

fmt.Printf("device: %s\nentity: %s\ncrawler: %s", stack.Device.Type, stack.Type, stack.Crawler.Category)
// device: smartphone
// entity: mobile-browser
// crawler: unknown

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func OptionDebug

func OptionDebug(b bool) func(*Client)

OptionDebug enable debugging for the client.

func OptionDisableStrictMode added in v0.3.0

func OptionDisableStrictMode() func(*Client)

OptionDisableStrictMode stops custom UnmarshalText on well-known types. Will not cause client to error if userstack API returns a type that cannot be expressed as a typed string constant.

func OptionHTTPClient

func OptionHTTPClient(client HTTPClient) func(*Client)

OptionHTTPClient - provide a custom http client to the client.

Types

type ApiErr

type ApiErr struct {
	// Most unfortunate this "success" is also not returned in the successful state.
	Success *bool `json:"success"`

	Err struct {
		Code int       `json:"code,omitempty"`
		Type ErrorType `json:"type,omitempty"`
		Info string    `json:"info,omitempty"`
	} `json:"error,omitempty"`
}

ApiErr is a well formatted error returned by the userstack API.

func (*ApiErr) Error

func (e *ApiErr) Error() string

type CategoryType

type CategoryType string
const (
	CategoryUnknown           CategoryType = "unknown"
	CategorySearchEngine      CategoryType = "search-engine"
	CategoryMonitoring        CategoryType = "monitoring"
	CategoryScreenshotService CategoryType = "screenshot-service"
	CategoryScraper           CategoryType = "scraper"
	CategorySecurityScanner   CategoryType = "security-scanner"
)

func (CategoryType) String

func (c CategoryType) String() string

func (*CategoryType) UnmarshalText

func (c *CategoryType) UnmarshalText(text []byte) error

UnmarshalText satisfies TextUnmarshaler

type Client

type Client struct {
	// contains filtered or unexported fields
}

func NewClient

func NewClient(apiKey string, secure bool, options ...Option) (*Client, error)

NewClient returns a userstack client. Users can modify clients with functional options.

Note: if you have a non-paying account, you must specify secure: false. Only paid accounts get access to `https`.

func (*Client) Detect

func (c *Client) Detect(ctx context.Context, userAgent string, params ...RequestParam) (*Stack, error)

Detect looks a single User-Agent string. Context may be nil, in which case context.Background() is used.

Only first param struct is used, do not pass more than one.

type DeviceType

type DeviceType string
const (
	DeviceUnknown    DeviceType = "unknown"
	DeviceDesktop    DeviceType = "desktop"
	DeviceTablet     DeviceType = "tablet"
	DeviceSmartPhone DeviceType = "smartphone"
	DeviceConsole    DeviceType = "console"
	DeviceSmartTV    DeviceType = "smarttv"
	DeviceWearable   DeviceType = "wearable"
)

func (DeviceType) String

func (d DeviceType) String() string

func (*DeviceType) UnmarshalText

func (d *DeviceType) UnmarshalText(text []byte) error

UnmarshalText satisfies TextUnmarshaler

type EntityType

type EntityType string
const (
	EntityUnknown        EntityType = "unknown"
	EntityBrowser        EntityType = "browser"
	EntityMobileBrowser  EntityType = "mobile-browser"
	EntityEmailClient    EntityType = "email-client"
	EntityApp            EntityType = "app"
	EntityFeedReader     EntityType = "feed-reader"
	EntityCrawler        EntityType = "crawler"
	EntityOfflineBrowser EntityType = "offline-browser"
)

func (EntityType) String

func (e EntityType) String() string

func (*EntityType) UnmarshalText

func (e *EntityType) UnmarshalText(text []byte) error

UnmarshalText satisfies TextUnmarshaler

type ErrorType

type ErrorType string

ErrorType represents common userstack API errors.

const (
	ErrNotFound                 ErrorType = "404_not_found"
	ErrMissingAccessKey         ErrorType = "missing_access_key"
	ErrInvalidAccessKey         ErrorType = "invalid_access_key"
	ErrInactiveUser             ErrorType = "inactive_user"
	ErrInvalidAPIFunction       ErrorType = "invalid_api_function"
	ErrUsageLimitReached        ErrorType = "usage_limit_reached"
	ErrFunctionAccessRestricted ErrorType = "function_access_restricted"
	ErrHTTPSAccessRestricted    ErrorType = "https_access_restricted"
	ErrMissingUserAgent         ErrorType = "missing_user_agent"
	ErrInvalidFields            ErrorType = "invalid_fields"
	ErrTooManyUserAgents        ErrorType = "too_many_user_agents"
	ErrBatchNotSupportedOnPlan  ErrorType = "batch_not_supported_on_plan"
)

func (ErrorType) Error

func (e ErrorType) Error() string

func (*ErrorType) UnmarshalText

func (e *ErrorType) UnmarshalText(text []byte) error

UnmarshalText satisfies TextUnmarshaler

type HTTPClient

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
}

HTTPClient is the interface used to send HTTP requests. Users can provide their own implementation.

type Option

type Option func(*Client)

Option is a functional option to modify the underlying Client.

type RequestParam added in v0.3.1

type RequestParam struct {
	// Set to your preferred output field(s). Follow docs to compose this.
	Fields string
}

type Stack

type Stack struct {
	Ua    string     `json:"ua,omitempty"`
	Type  EntityType `json:"type,omitempty"`
	Brand string     `json:"brand,omitempty"` // Is this device.brand ?
	Name  string     `json:"name,omitempty"`  // Is this device.name ?
	URL   string     `json:"url,omitempty"`
	Os    struct {
		Name         string `json:"name,omitempty"`
		Code         string `json:"code,omitempty"`
		URL          string `json:"url,omitempty"`
		Family       string `json:"family,omitempty"`
		FamilyCode   string `json:"family_code,omitempty"`
		FamilyVendor string `json:"family_vendor,omitempty"`
		Icon         string `json:"icon,omitempty"`
		IconLarge    string `json:"icon_large,omitempty"`
	} `json:"os"`
	Device struct {
		IsMobileDevice bool       `json:"is_mobile_device,omitempty"`
		Type           DeviceType `json:"type,omitempty"`
		Brand          string     `json:"brand,omitempty"`
		BrandCode      string     `json:"brand_code,omitempty"`
		BrandURL       string     `json:"brand_url,omitempty"`
		Name           string     `json:"name,omitempty"`
	} `json:"device"`
	Browser struct {
		Name         string `json:"name,omitempty"`
		Version      string `json:"version,omitempty"`
		VersionMajor string `json:"version_major,omitempty"`
		Engine       string `json:"engine,omitempty"`
	} `json:"browser"`
	Crawler struct {
		IsCrawler bool         `json:"is_crawler,omitempty"`
		Category  CategoryType `json:"category,omitempty"`
		LastSeen  string       `json:"last_seen,omitempty"` // "2019-09-15 20:35:33"
	} `json:"crawler"`
}

type UnsupportedTypeError added in v0.3.0

type UnsupportedTypeError struct {
	// contains filtered or unexported fields
}

UnsupportedTypeError describes an unmarshal error when encountering an unknown type.

NOTE: only returned when running client in strict mode. See Options for more info.

func (*UnsupportedTypeError) Error added in v0.3.0

func (e *UnsupportedTypeError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL