diff --git a/cmd/cooked-mcp/main.go b/cmd/cooked-mcp/main.go index ed0e8e298edd78122c9605dcbc1656b3448f2579..3d6af10899acc0263ba6fe465a39a1c543608fe8 100644 --- a/cmd/cooked-mcp/main.go +++ b/cmd/cooked-mcp/main.go @@ -74,7 +74,7 @@ func run() error { return err } - client, err := cooked.NewClient(config.BaseURL, config.Username, config.Password) + client, err := cooked.NewClient(config.BaseURL, config.Username, config.Password, "cooked-mcp/"+version) if err != nil { return err } diff --git a/internal/cooked/client.go b/internal/cooked/client.go index c3f93458d1a50c0f79aa1217b55da1bd750f2f9d..c59a0e9bb680f0215483df03d80059a022b3f9b7 100644 --- a/internal/cooked/client.go +++ b/internal/cooked/client.go @@ -30,6 +30,7 @@ type Client struct { username string password string http *http.Client + userAgent string requestMu sync.Mutex authenticatedUsername string @@ -105,16 +106,17 @@ type RecipeURLImport struct { } // NewClient returns a Cooked client with an in-memory cookie jar. -func NewClient(baseURL *url.URL, username, password string) (*Client, error) { +func NewClient(baseURL *url.URL, username, password, userAgent string) (*Client, error) { jar, err := newCookieJar() if err != nil { return nil, fmt.Errorf("create cookie jar: %w", err) } return &Client{ - baseURL: baseURL, - username: username, - password: password, + baseURL: baseURL, + username: username, + password: password, + userAgent: userAgent, http: &http.Client{ Jar: jar, Timeout: 30 * time.Second, @@ -585,6 +587,7 @@ func (c *Client) newRequest(ctx context.Context, method, path string, body []byt if body != nil { request.Header.Set("Content-Type", "application/json") } + request.Header.Set("User-Agent", c.userAgent) return request, nil } diff --git a/internal/cooked/client_test.go b/internal/cooked/client_test.go index 7628decb6e6f6fe0a26b351deda6717cb428441c..d5b1f3c8b6714f8ec4a4cfa9dcc96728a6864c86 100644 --- a/internal/cooked/client_test.go +++ b/internal/cooked/client_test.go @@ -389,6 +389,28 @@ func TestNewRequestPreservesEscapedUserPathWithQuery(t *testing.T) { } } +func TestNewRequestSetsUserAgent(t *testing.T) { + baseURL, err := url.Parse("https://example.invalid") + if err != nil { + t.Fatalf("parse base URL: %v", err) + } + client := &Client{baseURL: baseURL, userAgent: "cooked-mcp/test"} + + request, err := client.newRequest( + context.Background(), + http.MethodGet, + "/api/public/login", + nil, + ) + if err != nil { + t.Fatalf("newRequest() error = %v", err) + } + + if got := request.Header.Get("User-Agent"); got != "cooked-mcp/test" { + t.Fatalf("User-Agent = %q, want %q", got, "cooked-mcp/test") + } +} + func newTestClient(t *testing.T, handler http.HandlerFunc) (*Client, func()) { t.Helper() @@ -398,7 +420,7 @@ func newTestClient(t *testing.T, handler http.HandlerFunc) (*Client, func()) { server.Close() t.Fatalf("parse server URL: %v", err) } - client, err := NewClient(baseURL, "configured-user", "configured-password") + client, err := NewClient(baseURL, "configured-user", "configured-password", "cooked-mcp/test") if err != nil { server.Close() t.Fatalf("NewClient() error = %v", err)