44 "bytes"
55 "context"
66 "encoding/json"
7- "errors"
87 "fmt"
98 "io"
109 "io/ioutil"
@@ -16,8 +15,16 @@ const DefaultEndpoint = "https://api.habitify.me"
1615
1716const (
1817 urlHabits = "/habits"
18+ urlNotes = "/notes"
1919)
2020
21+ type apiResponse struct {
22+ Message string `json:"message"`
23+ Version string `json:"version"`
24+ Status bool `json:"status"`
25+ Data json.RawMessage `json:"data"`
26+ }
27+
2128// Client is a client for Habitify API.
2229type Client struct {
2330 httpClient * http.Client
@@ -75,53 +82,48 @@ func (resp *httpResponse) Close() {
7582 _ = resp .Body .Close ()
7683}
7784
78- func (c * Client ) do (ctx context.Context , method , path string , body io.Reader ) ( * httpResponse , error ) {
85+ func (c * Client ) do (ctx context.Context , method , path string , body io.Reader , data interface {}) error {
7986 req , err := http .NewRequestWithContext (ctx , method , c .endpoint + path , body )
8087
8188 if err != nil {
82- return nil , err
89+ return err
8390 }
8491
8592 req .Header .Add ("Authorization" , c .apiKey )
8693 req .Header .Add ("Content-Type" , "application/json; charset=utf8" )
8794
8895 resp , err := c .httpClient .Do (req )
8996 if err != nil {
90- return nil , err
97+ return err
9198 }
99+ defer resp .Body .Close ()
92100
93- switch resp .StatusCode {
94- case http .StatusBadRequest :
95- return nil , errors .New ("client has issues an invalid request" )
96- case http .StatusUnauthorized :
97- return nil , errors .New ("authorization for the API is required but the request has not been authenticated" )
98- case http .StatusForbidden :
99- return nil , errors .New ("the request has been authenticated but does not have permission or the resource is not found" )
100- case http .StatusNotAcceptable :
101- return nil , errors .New ("the client has requestd a MIM typ via the Accept header for a value not supported by the server" )
102- case http .StatusUnsupportedMediaType :
103- return nil , errors .New ("the client has defined a Content-Type header that is not supported by the server" )
104- case http .StatusUnprocessableEntity :
105- return nil , errors .New ("the client has made a valid request but the server cannot process it" )
106- case http .StatusTooManyRequests :
107- return nil , errors .New ("the client has exceeded the number of requests allowed for a givn time window" )
108- case http .StatusInternalServerError :
109- return nil , errors .New ("an unexpected error on the server has occurred" )
101+ httpResp := & httpResponse {Response : resp }
102+ var apiResp apiResponse
103+ if err := httpResp .DecodeJSON (& apiResp ); err != nil {
104+ return err
105+ }
106+ if ! apiResp .Status {
107+ return newError (resp .StatusCode , apiResp .Message )
110108 }
111109
112- return & httpResponse {Response : resp }, nil
110+ if err := json .Unmarshal (apiResp .Data , data ); err != nil {
111+ return fmt .Errorf ("decoding JSON data: %w" , err )
112+ }
113+
114+ return nil
113115}
114116
115- func (c * Client ) get (ctx context.Context , path string ) ( * httpResponse , error ) {
116- return c .do (ctx , http .MethodGet , path , nil )
117+ func (c * Client ) get (ctx context.Context , path string , data interface {}) error {
118+ return c .do (ctx , http .MethodGet , path , nil , data )
117119}
118120
119- func (c * Client ) post (ctx context.Context , path string , body interface {}) ( * httpResponse , error ) {
121+ func (c * Client ) post (ctx context.Context , path string , body interface {}) error {
120122 var buf bytes.Buffer
121123
122124 if err := json .NewEncoder (& buf ).Encode (body ); err != nil {
123- return nil , err
125+ return err
124126 }
125127
126- return c .do (ctx , http .MethodPost , path , & buf )
128+ return c .do (ctx , http .MethodPost , path , & buf , nil )
127129}
0 commit comments