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}