httpheaders.go

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