From 8f6cd9fe1e14fda13b0a4fd6e85335416f10e66b Mon Sep 17 00:00:00 2001 From: Ryan Park Date: Sat, 28 Feb 2026 00:45:22 -0800 Subject: [PATCH] fix: add Authorization header to Histories, CreateHistory, and Delete These three methods were making authenticated API calls without setting the Authorization header, causing the server to return 404. The fix follows the existing pattern used in Verify() and the account management methods. Co-Authored-By: Claude Sonnet 4.6 --- histories.go | 3 +++ histories_test.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/histories.go b/histories.go index f282057..8b1c646 100644 --- a/histories.go +++ b/histories.go @@ -130,6 +130,7 @@ func (c *Client) Histories() ([]*History, error) { if err != nil { return nil, err } + req.Header.Set("Authorization", fmt.Sprintf("Password %s", c.password)) resp, err := c.do(req) if err != nil { return nil, err @@ -168,6 +169,7 @@ func (c *Client) CreateHistory() (*History, error) { if err != nil { return nil, err } + req.Header.Set("Authorization", fmt.Sprintf("Password %s", c.password)) resp, err := c.do(req) if err != nil { return nil, err @@ -199,6 +201,7 @@ func (h *History) Delete() error { if err != nil { return err } + req.Header.Set("Authorization", fmt.Sprintf("Password %s", h.Client.password)) resp, err := h.Client.do(req) if err != nil { return err diff --git a/histories_test.go b/histories_test.go index fa19f3c..d734091 100644 --- a/histories_test.go +++ b/histories_test.go @@ -2,9 +2,33 @@ package thingscloud import ( "fmt" + "io" + "net/http" + "net/http/httptest" + "os" "testing" ) +// authCapturingServer creates a test server that captures headers and serves a fixture file. +func authCapturingServer(t *testing.T, statusCode int, fixture string) (*httptest.Server, *http.Header) { + t.Helper() + var captured http.Header + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + captured = r.Header.Clone() + f, err := os.Open(fmt.Sprintf("tapes/%s", fixture)) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + defer f.Close() + content, _ := io.ReadAll(f) + w.WriteHeader(statusCode) + w.Header().Set("Content-Type", "application/json") + fmt.Fprintln(w, string(content)) + })) + return server, &captured +} + func TestClient_Histories(t *testing.T) { t.Run("Success", func(t *testing.T) { t.Parallel() @@ -21,6 +45,18 @@ func TestClient_Histories(t *testing.T) { } }) + t.Run("SetsAuthorizationHeader", func(t *testing.T) { + t.Parallel() + server, captured := authCapturingServer(t, 200, "histories-success.json") + defer server.Close() + + c := New(fmt.Sprintf("http://%s", server.Listener.Addr().String()), "martin@example.com", "secret") + c.Histories() //nolint:errcheck + if got := (*captured).Get("Authorization"); got != "Password secret" { + t.Errorf("Authorization = %q, want %q", got, "Password secret") + } + }) + t.Run("Error", func(t *testing.T) { t.Parallel() server := fakeServer(fakeResponse{401, "error.json"}) @@ -49,6 +85,18 @@ func TestClient_CreateHistory(t *testing.T) { t.Fatalf("Expected key %s but got %s", "33333abb-bfe4-4b03-a5c9-106d42220c72", h.ID) } }) + + t.Run("SetsAuthorizationHeader", func(t *testing.T) { + t.Parallel() + server, captured := authCapturingServer(t, 200, "create-history-success.json") + defer server.Close() + + c := New(fmt.Sprintf("http://%s", server.Listener.Addr().String()), "martin@example.com", "secret") + c.CreateHistory() //nolint:errcheck + if got := (*captured).Get("Authorization"); got != "Password secret" { + t.Errorf("Authorization = %q, want %q", got, "Password secret") + } + }) } func TestHistory_Delete(t *testing.T) { @@ -64,6 +112,19 @@ func TestHistory_Delete(t *testing.T) { t.Fatalf("Expected request to succeed, but didn't: %q", err.Error()) } }) + + t.Run("SetsAuthorizationHeader", func(t *testing.T) { + t.Parallel() + server, captured := authCapturingServer(t, 202, "create-history-success.json") + defer server.Close() + + c := New(fmt.Sprintf("http://%s", server.Listener.Addr().String()), "martin@example.com", "secret") + h := History{Client: c, ID: "33333abb-bfe4-4b03-a5c9-106d42220c72"} + h.Delete() //nolint:errcheck + if got := (*captured).Get("Authorization"); got != "Password secret" { + t.Errorf("Authorization = %q, want %q", got, "Password secret") + } + }) } func TestHistory_Sync(t *testing.T) {