httpheaders.go

 1// Package httpheaders provides shared User-Agent resolution for all HTTP-based providers.
 2package httpheaders
 3
 4import (
 5	"fmt"
 6	"strings"
 7)
 8
 9// DefaultUserAgent returns the default User-Agent string for the SDK.
10// The result is "Charm Fantasy/<version>".
11func DefaultUserAgent(version string) string {
12	return fmt.Sprintf("Charm-Fantasy/%s (https://charm.land/fantasy)", version)
13}
14
15// ResolveHeaders returns a new header map, with a User-Agent field.
16//
17// Setting the value via WithUserAgent() takes precedence, however the user
18// agent can also be set via HTTP headers (i.e. WithHeaders()). Otherwise, the
19// default user agent will be used, i.e. Charm Fantasy/0.11.0.
20//
21// Also note that the input map is never mutated.
22func ResolveHeaders(headers map[string]string, explicitUA, defaultUA string) map[string]string {
23	out := make(map[string]string, len(headers)+1)
24	var uaKeys []string
25
26	for k, v := range headers {
27		out[k] = v
28		if strings.EqualFold(k, "User-Agent") {
29			uaKeys = append(uaKeys, k)
30		}
31	}
32
33	switch {
34	case explicitUA != "":
35		for _, k := range uaKeys {
36			delete(out, k)
37		}
38		out["User-Agent"] = explicitUA
39	case len(uaKeys) > 0:
40		val := out[uaKeys[0]]
41		for _, k := range uaKeys {
42			delete(out, k)
43		}
44		out["User-Agent"] = val
45	default:
46		out["User-Agent"] = defaultUA
47	}
48
49	return out
50}
51
52// CallUserAgent resolves the User-Agent for a single API call. It returns the
53// resolved UA string and true if a per-call override should be applied, or
54// empty string and false if the client-level UA should be used as-is.
55func CallUserAgent(callUA string) (string, bool) {
56	if callUA != "" {
57		return callUA, true
58	}
59	return "", false
60}