@@ -18,6 +18,7 @@ import (
1818 "os"
1919 "strings"
2020
21+ "github.com/jaxxstorm/tscli/pkg/version"
2122 "github.com/spf13/viper"
2223 tsapi "tailscale.com/client/tailscale/v2"
2324)
@@ -27,6 +28,11 @@ const (
2728 defaultContentType = "application/json"
2829)
2930
31+ // getUserAgent returns the properly formatted user agent string
32+ func getUserAgent () string {
33+ return fmt .Sprintf ("tscli/%s (Go client)" , version .GetVersion ())
34+ }
35+
3036func New () (* tsapi.Client , error ) {
3137 tailnet := viper .GetString ("tailnet" )
3238 apiKey := viper .GetString ("api-key" )
@@ -37,15 +43,27 @@ func New() (*tsapi.Client, error) {
3743 return nil , fmt .Errorf ("api-key is required" )
3844 }
3945
40- httpClient := & http.Client {}
46+ userAgent := getUserAgent ()
47+
48+ // Create a custom transport that ensures UserAgent is always set
49+ transport := & userAgentTransport {
50+ rt : http .DefaultTransport ,
51+ userAgent : userAgent ,
52+ }
53+
54+ // Wrap with debug logging if enabled
4155 if viper .GetBool ("debug" ) {
42- httpClient .Transport = & logTransport {rt : http .DefaultTransport }
56+ transport .rt = & logTransport {rt : transport .rt }
57+ }
58+
59+ httpClient := & http.Client {
60+ Transport : transport ,
4361 }
4462
4563 return & tsapi.Client {
4664 Tailnet : tailnet ,
4765 APIKey : apiKey ,
48- UserAgent : "tscli" ,
66+ UserAgent : userAgent ,
4967 HTTP : httpClient ,
5068 }, nil
5169}
@@ -173,3 +191,15 @@ func (t *logTransport) RoundTrip(req *http.Request) (*http.Response, error) {
173191 }
174192 return resp , nil
175193}
194+
195+ // userAgentTransport wraps an http.RoundTripper to ensure UserAgent is always set
196+ type userAgentTransport struct {
197+ rt http.RoundTripper
198+ userAgent string
199+ }
200+
201+ func (t * userAgentTransport ) RoundTrip (req * http.Request ) (* http.Response , error ) {
202+ // Always set our custom user agent
203+ req .Header .Set ("User-Agent" , t .userAgent )
204+ return t .rt .RoundTrip (req )
205+ }
0 commit comments