Skip to content

Commit

Permalink
Switch to go-rest (#21)
Browse files Browse the repository at this point in the history
* switched to go-rest

* added interceptors.SetReqContentType

* disabled codecov comments
  • Loading branch information
vtopc authored Dec 12, 2021
1 parent ffcb8a9 commit fdfdf91
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 81 deletions.
75 changes: 14 additions & 61 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@ package monobank
// TODO: add HTTP retry

import (
"context"
"encoding/json"
"io"
"net/http"
"net/url"
"time"

"github.com/pkg/errors"
"github.com/vtopc/go-rest"
"github.com/vtopc/go-rest/defaults"
"github.com/vtopc/go-rest/interceptors"
)

const (
baseURL = "https://api.monobank.ua"
defaultTimeout = 30 * time.Second
baseURL = "https://api.monobank.ua"
)

type Client struct {
httpClient *http.Client
restClient *rest.Client
auth Authorizer
baseURL string // TODO: switch to url.URL
}
Expand All @@ -29,14 +27,14 @@ type Client struct {
// NewClient - returns public monobank Client
func NewClient(client *http.Client) Client {
if client == nil {
// defaults
client = &http.Client{
Timeout: defaultTimeout,
}
client = defaults.NewHTTPClient()
}

_ = interceptors.SetReqContentType(client, "application/json")
c := rest.NewClient(client)

return Client{
httpClient: client,
restClient: c,
auth: NewPublicAuthorizer(),
baseURL: baseURL,
}
Expand All @@ -54,9 +52,7 @@ func (c *Client) withAuth(auth Authorizer) {
// do does request.
// Stores JSON response in the value pointed to by v.
// TODO: make expectedStatusCode a slice:
func (c Client) do(ctx context.Context, req *http.Request, v interface{}, expectedStatusCode int) error {
// TODO: check that `v` is a pointer or nil

func (c Client) do(req *http.Request, v interface{}, expectedStatusCode int) error {
if req == nil {
return errors.New("empty request")
}
Expand All @@ -67,59 +63,16 @@ func (c Client) do(ctx context.Context, req *http.Request, v interface{}, expect
return errors.Wrap(err, "failed to build URL")
}

req = req.WithContext(ctx)

if c.auth != nil { // TODO: return an error if not
err = c.auth.SetAuth(req)
if err != nil {
return NewReqError(req, errors.Wrap(err, "SetAuth"))
return errors.Wrap(err, "SetAuth")
}
}

if req.Body != nil {
req.Header.Set("Content-Type", "application/json")
}

err = func() error {
resp, e := c.httpClient.Do(req)
if e != nil {
return e
}

defer resp.Body.Close()

var body []byte
if v != nil {
body, e = io.ReadAll(resp.Body)
if e != nil {
return errors.Wrap(e, "couldn't read the body")
}
}

// TODO: switch to "for" for multi-status:
if resp.StatusCode == expectedStatusCode {
if v == nil {
// nothing to unmarshal
return nil
}

e = json.Unmarshal(body, v)
if e == nil {
return nil
}

return errors.Wrap(e, "failed to unmarshal the response body")
}

// otherwise, non expected status code:
return &APIError{
ResponseStatusCode: resp.StatusCode,
ExpectedStatusCodes: []int{expectedStatusCode},
Err: errors.New(string(body)),
}
}()
err = c.restClient.Do(req, v, expectedStatusCode)
if err != nil {
return NewReqError(req, err)
return err
}

return nil
Expand Down
6 changes: 3 additions & 3 deletions client_test.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package monobank

import (
"context"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/vtopc/go-rest"
)

func TestClient_do(t *testing.T) {
Expand Down Expand Up @@ -45,14 +45,14 @@ func TestClient_do(t *testing.T) {

c := Client{
baseURL: server.URL,
httpClient: server.Client(),
restClient: rest.NewClient(server.Client()),
}

req, err := http.NewRequest(tc.method, tc.urlPostfix, http.NoBody)
require.NoError(t, err)

// test:
err = c.do(context.Background(), req, &tc.v, tc.expectedStatusCode)
err = c.do(req, &tc.v, tc.expectedStatusCode)
require.NoError(t, err)
assert.Equal(t, tc.want, tc.v)
})
Expand Down
1 change: 1 addition & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
comment: false
12 changes: 6 additions & 6 deletions common.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ func newCommonClient(client *http.Client) commonClient {
func (c commonClient) ClientInfo(ctx context.Context) (*ClientInfo, error) {
const urlPath = "/personal/client-info"

req, err := http.NewRequest(http.MethodGet, urlPath, http.NoBody)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, urlPath, http.NoBody)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}

var v ClientInfo
err = c.do(ctx, req, &v, http.StatusOK)
err = c.do(req, &v, http.StatusOK)

return &v, err
}
Expand All @@ -50,13 +50,13 @@ func (c commonClient) Transactions(ctx context.Context, accountID string, from,
const urlPath = "/personal/statement"
uri := fmt.Sprintf("%s/%s/%d/%d", urlPath, accountID, from.Unix(), to.Unix())

req, err := http.NewRequest(http.MethodGet, uri, http.NoBody)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, uri, http.NoBody)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}

var v Transactions
err = c.do(ctx, req, &v, http.StatusOK)
err = c.do(req, &v, http.StatusOK)

return v, err
}
Expand All @@ -68,10 +68,10 @@ func (c commonClient) setWebHook(ctx context.Context, uri, urlPath string) error
return errors.Wrap(err, "failed to marshal")
}

req, err := http.NewRequest(http.MethodPost, urlPath, &buf)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, urlPath, &buf)
if err != nil {
return errors.Wrap(err, "failed to create request")
}

return c.do(ctx, req, nil, http.StatusOK)
return c.do(req, nil, http.StatusOK)
}
8 changes: 4 additions & 4 deletions corporate.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func NewCorporateClient(client *http.Client, authMaker CorpAuthMakerAPI) (Corpor

// Auth initializes access.
func (c CorporateClient) Auth(ctx context.Context, callbackURL string, permissions ...string) (*TokenRequest, error) {
req, err := http.NewRequest(http.MethodPost, urlPathAuth, http.NoBody)
req, err := http.NewRequestWithContext(ctx, http.MethodPost, urlPathAuth, http.NoBody)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}
Expand All @@ -63,20 +63,20 @@ func (c CorporateClient) Auth(ctx context.Context, callbackURL string, permissio
authClient := c.withAuth(c.authMaker.NewPermissions(permissions...))

var v TokenRequest
err = authClient.commonClient.do(ctx, req, &v, http.StatusOK)
err = authClient.commonClient.do(req, &v, http.StatusOK)

return &v, err
}

func (c CorporateClient) CheckAuth(ctx context.Context, requestID string) error {
req, err := http.NewRequest(http.MethodGet, urlPathAuth, http.NoBody)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, urlPathAuth, http.NoBody)
if err != nil {
return errors.Wrap(err, "failed to create request")
}

authClient := c.withAuth(c.authMaker.New(requestID))

return authClient.do(ctx, req, nil, http.StatusOK)
return authClient.do(req, nil, http.StatusOK)
}

// SetWebHook sets webhook for corporate API.
Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.16
require (
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.4.0
github.com/stretchr/testify v1.7.0
github.com/vtopc/epoch v1.0.0
github.com/vtopc/go-rest v0.2.0
)
10 changes: 6 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -8,18 +7,21 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0 h1:3GIJYXQDAKpLEFriGFN8SbSffak10UXHGdIcFaMPykY=
github.com/decred/dcrd/dcrec/secp256k1/v2 v2.0.0/go.mod h1:3s92l0paYkZoIHuj4X93Teg/HB7eGM9x/zokGw+u4mY=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/vtopc/epoch v1.0.0 h1:C9lSFt9DC/J0YlW3Eheq4vBBi0pk2hjC8XFb3indWlw=
github.com/vtopc/epoch v1.0.0/go.mod h1:/jzmj/iiCMyAiIk3T6RGPUpMpPSjUJDG2Yu7FzfEt8U=
github.com/vtopc/go-rest v0.2.0 h1:ZdNndlwzk1NjWbKf8yHGo8Bn1DRolWAtuPbIBvAVN5k=
github.com/vtopc/go-rest v0.2.0/go.mod h1:t7XPUz57Z+U66vsVIjEm89Uw/NZf486JVAFhq6+mZps=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
4 changes: 2 additions & 2 deletions public.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ type PublicAPI interface {
func (c Client) Currency(ctx context.Context) (Currencies, error) {
const urlPath = "/bank/currency"

req, err := http.NewRequest(http.MethodGet, urlPath, http.NoBody)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, urlPath, http.NoBody)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}

var v Currencies
err = c.do(ctx, req, &v, http.StatusOK)
err = c.do(req, &v, http.StatusOK)

return v, err
}

0 comments on commit fdfdf91

Please sign in to comment.