Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/openstatusHQ/cli. OpenStatus CLI www.openstatus.dev
cli cli-app synthetic-monitoring
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119package api
import ( "crypto/rand" "encoding/hex" "net/http" "net/url" "os" "runtime" "strconv" "strings" "sync/atomic"
"github.com/openstatusHQ/cli/internal/version")
// Headers sent on every request so the API can attribute usage to CLI// commands without the CLI making any extra call.const ( HeaderCLICommand = "x-openstatus-cli-command" HeaderCLIInvocation = "x-openstatus-cli-invocation")
// userAgent identifies the CLI, e.g. "openstatus-cli/v1.3.2 (darwin; arm64)".var userAgent = "openstatus-cli/" + version.Version + " (" + runtime.GOOS + "; " + runtime.GOARCH + ")"
var ( command atomic.Pointer[string] // invocationID is random per process: it lets the API count one command // run once even when it makes several requests. invocationID = newInvocationID())
// SetCommand records the command being run, e.g. "monitors apply". Call it// before the command makes any request.func SetCommand(name string) { command.Store(&name) }
// UsageOptOut reports whether the user asked not to share command usage, via// DO_NOT_TRACK or OPENSTATUS_NO_TELEMETRY.func UsageOptOut() bool { return isSet(os.Getenv("DO_NOT_TRACK")) || isSet(os.Getenv("OPENSTATUS_NO_TELEMETRY"))}
// isSet treats empty and falsy values (0, false, no, off, any case) as unset,// and anything else as an opt-out.func isSet(v string) bool { v = strings.TrimSpace(v) if v == "" || strings.EqualFold(v, "no") || strings.EqualFold(v, "off") { return false } if b, err := strconv.ParseBool(v); err == nil { return b } return true}
// sendsUsage reports whether a request to u may carry the command and// invocation ID: only requests to the configured API, plus the hosted speed// checker when the CLI targets openstatus Cloud. A self-hosted setup never// sends them to openstatus.dev.func sendsUsage(u *url.URL) bool { if UsageOptOut() { return false } if u.Host == hostOf(BaseURL) { return true } return BaseURL == DefaultBaseURL && u.Host == hostOf(PlayCheckerURL)}
func hostOf(rawURL string) string { u, err := url.Parse(rawURL) if err != nil { return "" } return u.Host}
func newInvocationID() string { b := make([]byte, 16) _, _ = rand.Read(b) return hex.EncodeToString(b)}
// cliTransport tags outgoing requests with the CLI headers.type cliTransport struct { base http.RoundTripper}
// NewTransport wraps base (http.DefaultTransport when nil) so every request// carries the CLI user agent and, when sendsUsage allows it, the command and// invocation ID.func NewTransport(base http.RoundTripper) http.RoundTripper { if base == nil { base = http.DefaultTransport } return cliTransport{base: base}}
func (t cliTransport) RoundTrip(req *http.Request) (*http.Response, error) { // A RoundTripper must not modify the caller's request. req = req.Clone(req.Context())
// Keep any existing agent (e.g. connect-go's) after ours. ua := userAgent if existing := req.Header.Get("User-Agent"); existing != "" { ua += " " + existing } req.Header.Set("User-Agent", ua)
if sendsUsage(req.URL) { req.Header.Set(HeaderCLIInvocation, invocationID) if name := command.Load(); name != nil && *name != "" { req.Header.Set(HeaderCLICommand, *name) } } return t.base.RoundTrip(req)}