HTTP Client - Simplified - Mockable
- Create your client
- A Client is required to make any http calls - good thing it's dead easy to create:
- Simple Client example:
c := context.Background()
cl, err := github.NewClient(c)
- Advanced Client example:
c := context.Background()
cl, err := fetcher.NewClient(c,
fetcher.WithRequestOptions([]fetcher.RequestOption{
fetcher.WithAcceptJSONHeader(),
fetcher.WithHeader("API-Token", os.Getenv("API_TOKEN")),
}),
)
- This client can now be used as much as needed.
- Pass your client to the function as a fetcher.Fetcher interface object:
func sharedCount(c context.Context, f fetcher.Fetcher, uri string) (int, error) {
...
return countResp.Count, nil
}
- This function is now testable with a mocked client using fetchermock.
- Use your client to make a call:
func sharedCount(c context.Context, f fetcher.Fetcher, uri string) (int, error) {
apiURL := "http://www.linkedin.com/countserv/count/share?format=json&url=" + url.QueryEscape(uri)
resp, err := f.Get(c, apiURL, fetcher.WithMaxAttempts(3))
if err != nil {
return 0, err
}
- Handle the response
defer resp.Close()
switch {
case resp.StatusCode() == 400:
return 0, errors.New("invalid url")
case resp.StatusCode() > 300:
return 0, errors.New("bad status code")
}
type countResponse struct {
Count int `json:"count"`
URL string `json:"url"`
}
countResp := &countResponse{}
if err = resp.Decode(c, countResp, fetcher.WithJSONBody()); err != nil {
return 0, err
}
return countResp.Count, nil`
}
- Write your test
- you can now use
fetchermock
to create a testing client that satisfies the fetcher.Fetcher interface - including the expected response body, status code, and/or error.
Advanced features:
- Retry loop
- Copied response body for easier debugging
- Rate Limiting
- Max Idle Connections Per Host
- Custom Debug/Error Logging
- Request Backoff Options