Documentation
¶
Overview ¶
Package ddgo parses user-agent strings into bot, client, operating system, and device metadata.
The parser is intentionally deterministic and returns Unknown for fields that cannot be derived from available inputs. For browser client-hint enrichment, ParseWithHeaders and ParseWithClientHints can be used alongside Parse.
Index ¶
Examples ¶
Constants ¶
const Unknown = "Unknown"
Unknown is a sentinel value used when parser data is not available. Callers can compare string fields to this value instead of empty string.
Variables ¶
var ErrNilDetector = errors.New("ddgo: nil detector")
ErrNilDetector is returned when Parse is called on a nil *Detector.
Functions ¶
This section is empty.
Types ¶
type ClientHintBrand ¶
ClientHintBrand represents one structured brand entry from Sec-CH-UA.
type ClientHints ¶
type ClientHints struct {
Brands []ClientHintBrand
Platform string
PlatformVersion string
Model string
Mobile *bool
}
ClientHints contains normalized Sec-CH-UA style client hints.
Mobile is nil when the client did not send Sec-CH-UA-Mobile.
func ParseClientHintsFromHeaders ¶
func ParseClientHintsFromHeaders(headers map[string]string) ClientHints
ParseClientHintsFromHeaders extracts known client hints from HTTP header values. Header name matching is case-insensitive.
Example ¶
package main
import (
"fmt"
"github.com/metalagman/ddgo"
)
func main() {
headers := map[string]string{
"Sec-CH-UA-Full-Version-List": "\"Not A;Brand\";v=\"24\", \"Chromium\";v=\"122.0.6261.128\", \"Google Chrome\";v=\"122.0.6261.128\"",
"Sec-CH-UA-Platform": "\"Android\"",
"Sec-CH-UA-Mobile": "?1",
}
hints := ddgo.ParseClientHintsFromHeaders(headers)
fmt.Printf("brands=%d platform=%s mobile=%t\n", len(hints.Brands), hints.Platform, *hints.Mobile)
}
Output: brands=3 platform=Android mobile=true
type Detector ¶
type Detector struct {
// contains filtered or unexported fields
}
Detector parses user-agent strings into structured detection results.
A Detector is safe for concurrent use by multiple goroutines.
func New ¶
New creates a detector with optional configuration overrides.
Example ¶
package main
import (
"fmt"
"log"
"github.com/metalagman/ddgo"
)
func main() {
detector, err := ddgo.New()
if err != nil {
log.Fatalf("ddgo.New() failed: %v", err)
}
result, err := detector.Parse("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0")
if err != nil {
log.Fatalf("Parse() failed: %v", err)
}
fmt.Printf("%s %s\n", result.Client.Name, result.Client.Version)
}
Output: Firefox 124.0
func (*Detector) Parse ¶
Parse analyzes a user-agent string and returns a detection result.
Parse can return cached results for identical normalized user-agent inputs.
Example ¶
package main
import (
"fmt"
"log"
"github.com/metalagman/ddgo"
)
func main() {
detector, err := ddgo.New()
if err != nil {
log.Fatalf("ddgo.New() failed: %v", err)
}
result, err := detector.Parse("Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
if err != nil {
log.Fatalf("Parse() failed: %v", err)
}
fmt.Printf("is_bot=%t name=%s device=%s\n", result.Bot.IsBot, result.Bot.Name, result.Device.Type)
}
Output: is_bot=true name=Googlebot device=Bot
func (*Detector) ParseWithClientHints ¶
func (d *Detector) ParseWithClientHints(userAgent string, hints ClientHints) (Result, error)
ParseWithClientHints analyzes a user-agent string with explicit client hints.
Hint-based parsing bypasses the internal Parse cache.
Example ¶
package main
import (
"fmt"
"log"
"github.com/metalagman/ddgo"
)
func main() {
detector, err := ddgo.New()
if err != nil {
log.Fatalf("ddgo.New() failed: %v", err)
}
mobile := true
hints := ddgo.ClientHints{
Brands: []ddgo.ClientHintBrand{{Name: "Google Chrome", Version: "122.0.6261.128"}},
Platform: "Android",
PlatformVersion: "14.0.0",
Model: "SM-G991B",
Mobile: &mobile,
}
result, err := detector.ParseWithClientHints("Mozilla/5.0", hints)
if err != nil {
log.Fatalf("ParseWithClientHints() failed: %v", err)
}
fmt.Printf("%s %s on %s (%s)\n", result.Client.Name, result.Client.Version, result.OS.Name, result.Device.Model)
}
Output: Chrome 122.0.6261.128 on Android (SM-G991B)
func (*Detector) ParseWithHeaders ¶
ParseWithHeaders analyzes a user-agent string and Sec-CH-UA style headers.
This helper normalizes headers via ParseClientHintsFromHeaders and then delegates to ParseWithClientHints.
Example ¶
package main
import (
"fmt"
"log"
"github.com/metalagman/ddgo"
)
func main() {
detector, err := ddgo.New()
if err != nil {
log.Fatalf("ddgo.New() failed: %v", err)
}
headers := map[string]string{
"Sec-CH-UA": "\"Not(A:Brand\";v=\"99\", \"Microsoft Edge\";v=\"123.0.0.0\", \"Chromium\";v=\"123.0.0.0\"",
"Sec-CH-UA-Platform": "\"Windows\"",
"Sec-CH-UA-Platform-Version": "\"15.0.0\"",
"Sec-CH-UA-Mobile": "?0",
}
result, err := detector.ParseWithHeaders("Mozilla/5.0", headers)
if err != nil {
log.Fatalf("ParseWithHeaders() failed: %v", err)
}
fmt.Printf("%s %s (%s)\n", result.Client.Name, result.Client.Version, result.Device.Type)
}
Output: Microsoft Edge 123.0.0.0 (Desktop)
type LRUResultCache ¶
type LRUResultCache struct {
// contains filtered or unexported fields
}
LRUResultCache is a bounded in-memory LRU cache implementation.
func NewLRUResultCache ¶
func NewLRUResultCache(capacity int) *LRUResultCache
NewLRUResultCache creates a bounded in-memory LRU parse result cache.
Returns nil when capacity is <= 0.
func (*LRUResultCache) Get ¶
func (c *LRUResultCache) Get(key string) (Result, bool)
Get returns a cached result for key and updates recency on hit.
func (*LRUResultCache) Set ¶
func (c *LRUResultCache) Set(key string, result Result)
Set stores a result for key and evicts the least-recently-used entry when full.
type MemoryResultCache ¶
type MemoryResultCache struct {
// contains filtered or unexported fields
}
MemoryResultCache is a simple unbounded in-memory cache implementation.
func NewMemoryResultCache ¶
func NewMemoryResultCache() *MemoryResultCache
NewMemoryResultCache creates an unbounded in-memory cache.
func (*MemoryResultCache) Get ¶
func (c *MemoryResultCache) Get(key string) (Result, bool)
Get returns a cached result for key.
func (*MemoryResultCache) Set ¶
func (c *MemoryResultCache) Set(key string, result Result)
Set stores a cached result for key.
type Option ¶
type Option func(*options)
Option configures Detector behavior.
func WithMaxUserAgentLen ¶
WithMaxUserAgentLen limits how many bytes of a user-agent string are parsed. Values below 1 are ignored.
Example ¶
package main
import (
"fmt"
"log"
"github.com/metalagman/ddgo"
)
func main() {
detector, err := ddgo.New(ddgo.WithMaxUserAgentLen(7))
if err != nil {
log.Fatalf("ddgo.New() failed: %v", err)
}
result, err := detector.Parse("Mozilla/5.0")
if err != nil {
log.Fatalf("Parse() failed: %v", err)
}
fmt.Println(result.UserAgent)
}
Output: Mozilla
func WithResultCache ¶
func WithResultCache(cache ResultCache) Option
WithResultCache configures a custom parse result cache implementation.
Passing nil explicitly disables caching.
func WithUserAgentTrimming ¶
WithUserAgentTrimming toggles normalization of user-agent whitespace.
When enabled, Parse collapses repeated whitespace and trims leading/trailing space before matching.
Example ¶
package main
import (
"fmt"
"log"
"github.com/metalagman/ddgo"
)
func main() {
detector, err := ddgo.New(ddgo.WithUserAgentTrimming(false))
if err != nil {
log.Fatalf("ddgo.New() failed: %v", err)
}
result, err := detector.Parse(" Mozilla/5.0 ")
if err != nil {
log.Fatalf("Parse() failed: %v", err)
}
fmt.Printf("%q\n", result.UserAgent)
}
Output: " Mozilla/5.0 "
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
ddsync
command
Command ddsync builds and verifies deterministic sync artifacts.
|
Command ddsync builds and verifies deterministic sync artifacts. |
|
ddsync/cmd
Package cmd provides the Cobra command tree for the ddsync CLI.
|
Package cmd provides the Cobra command tree for the ddsync CLI. |
|
internal
|
|
|
ddsync
Package ddsync implements deterministic snapshot compilation and verification.
|
Package ddsync implements deterministic snapshot compilation and verification. |