diff --git a/internal/client/eightsleep.go b/internal/client/eightsleep.go index 55fad67..284af85 100644 --- a/internal/client/eightsleep.go +++ b/internal/client/eightsleep.go @@ -2,6 +2,7 @@ package client import ( "bytes" + "compress/gzip" "context" "crypto/tls" "encoding/json" @@ -120,8 +121,8 @@ func (c *Client) authTokenEndpoint(ctx context.Context) error { "grant_type": "password", "username": c.Email, "password": c.Password, - "client_id": "sleep-client", - "client_secret": "", + "client_id": c.ClientID, + "client_secret": c.ClientSecret, } body, _ := json.Marshal(payload) req, err := http.NewRequestWithContext(ctx, http.MethodPost, authURL, bytes.NewReader(body)) @@ -288,6 +289,15 @@ func (c *Client) do(ctx context.Context, method, path string, query url.Values, return err } defer resp.Body.Close() + var bodyReader io.Reader = resp.Body + if resp.Header.Get("Content-Encoding") == "gzip" { + gr, err := gzip.NewReader(resp.Body) + if err != nil { + return err + } + defer gr.Close() + bodyReader = gr + } if resp.StatusCode == http.StatusTooManyRequests { time.Sleep(2 * time.Second) return c.do(ctx, method, path, query, body, out) @@ -301,11 +311,11 @@ func (c *Client) do(ctx context.Context, method, path string, query url.Values, return c.do(ctx, method, path, query, body, out) } if resp.StatusCode >= 300 { - b, _ := io.ReadAll(resp.Body) + b, _ := io.ReadAll(bodyReader) return fmt.Errorf("api %s %s: %s", method, path, string(b)) } if out != nil { - return json.NewDecoder(resp.Body).Decode(out) + return json.NewDecoder(bodyReader).Decode(out) } return nil } diff --git a/internal/client/eightsleep_test.go b/internal/client/eightsleep_test.go index a6204ac..610b44f 100644 --- a/internal/client/eightsleep_test.go +++ b/internal/client/eightsleep_test.go @@ -1,7 +1,9 @@ package client import ( + "compress/gzip" "context" + "encoding/json" "net/http" "net/http/httptest" "testing" @@ -101,3 +103,31 @@ func Test429Retry(t *testing.T) { t.Fatalf("expected backoff, got %v", elapsed) } } + +func TestDoHandlesGzipResponse(t *testing.T) { + mux := http.NewServeMux() + mux.HandleFunc("/gzipped", func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Content-Encoding", "gzip") + gz := gzip.NewWriter(w) + json.NewEncoder(gz).Encode(map[string]string{"hello": "world"}) + gz.Close() + }) + srv := httptest.NewServer(mux) + defer srv.Close() + + c := New("email", "pass", "uid", "", "") + c.BaseURL = srv.URL + c.token = "t" + c.tokenExp = time.Now().Add(time.Hour) + c.HTTP = srv.Client() + + var out map[string]string + if err := c.do(context.Background(), http.MethodGet, "/gzipped", nil, nil, &out); err != nil { + t.Fatalf("do gzip: %v", err) + } + if out["hello"] != "world" { + t.Fatalf("expected {hello: world}, got %v", out) + } +} +