Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/tap/tap.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ var licenseText string

func main() {
cli.LicenseText = licenseText
// Hubs list signed-in clients by user agent; name tap rather than Go.
cli.InstallUserAgent()

ctx := context.Background()
// Signal handling is intentionally not registered at the entrypoint.
Expand Down
31 changes: 31 additions & 0 deletions pkg/cli/user_agent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cli

import (
"net/http"
"runtime"
)

// UserAgent identifies tap to the hubs it talks to, so a hub's list of
// signed-in clients can say which tap, and on what platform, holds a login.
func UserAgent() string {
return "tap/" + Version + " (" + runtime.GOOS + "/" + runtime.GOARCH + ")"
}

// userAgentTransport sets UserAgent on requests that do not set their own.
type userAgentTransport struct{ base http.RoundTripper }

func (t userAgentTransport) RoundTrip(r *http.Request) (*http.Response, error) {
if r.Header.Get("User-Agent") == "" {
r = r.Clone(r.Context())
r.Header.Set("User-Agent", UserAgent())
}
return t.base.RoundTrip(r)
}

// InstallUserAgent makes every request sent through http.DefaultTransport,
// which tap's hub clients use, carry UserAgent. Call it once from main.
func InstallUserAgent() {
if _, done := http.DefaultTransport.(userAgentTransport); !done {
http.DefaultTransport = userAgentTransport{base: http.DefaultTransport}
}
}
31 changes: 31 additions & 0 deletions pkg/cli/user_agent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package cli

import (
"net/http"
"net/http/httptest"
"runtime"
"testing"

"github.com/stretchr/testify/require"
)

func TestUserAgentTransport(t *testing.T) {
t.Parallel()
var got []string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
got = append(got, r.Header.Get("User-Agent"))
}))
defer srv.Close()
client := &http.Client{Transport: userAgentTransport{base: http.DefaultTransport}}

_, err := client.Get(srv.URL)
require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, srv.URL, nil)
require.NoError(t, err)
req.Header.Set("User-Agent", "custom/1")
_, err = client.Do(req)
require.NoError(t, err)

require.Equal(t, []string{"tap/" + Version + " (" + runtime.GOOS + "/" + runtime.GOARCH + ")", "custom/1"}, got,
"tap's agent is the default; a request's own agent wins")
}
Loading