fetcher

package module
v0.0.0-...-612c04b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 2, 2020 License: MIT Imports: 20 Imported by: 0

README

fetcher CircleCI GoDoc Codecov Go Report Card

HTTP Client - Simplified - Mockable

  1. 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.
  1. 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
  }

  1. 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
  }
  1. 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`
}

  1. 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:

  1. Retry loop
  2. Copied response body for easier debugging
  3. Rate Limiting
  4. Max Idle Connections Per Host
  5. Custom Debug/Error Logging
  6. Request Backoff Options

Documentation

Index

Constants

View Source
const (
	// ContentTypeJSON = "application/json"
	ContentTypeJSON = "application/json"

	// ContentTypeGob = "application/gob"
	ContentTypeGob = "application/gob"

	// ContentTypeXML = "application/xml"
	ContentTypeXML = "application/xml"

	// ContentTypeURLEncoded = "application/x-www-form-urlencoded"
	ContentTypeURLEncoded = "application/x-www-form-urlencoded"

	// ContentTypeHeader = "Content-Type"
	ContentTypeHeader = "Content-Type"

	// AcceptHeader = "Accept"
	AcceptHeader = "Accept"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client implements Fetcher interface and is required to execute a Request

func NewClient

func NewClient(c context.Context, opts ...ClientOption) (*Client, error)

NewClient returns a new Client with the given options executed

func (*Client) Delete

func (cl *Client) Delete(c context.Context, url string, opts ...RequestOption) (*Response, error)

Delete is a helper func for Do, setting the Method internally

func (*Client) Do

func (cl *Client) Do(c context.Context, req *Request) (*Response, error)

Do uses the client receiver to execute the provided request

func (*Client) Get

func (cl *Client) Get(c context.Context, url string, opts ...RequestOption) (*Response, error)

Get is a helper func for Do, setting the Method internally

func (*Client) Head

func (cl *Client) Head(c context.Context, url string, opts ...RequestOption) (*Response, error)

Head is a helper func for Do, setting the Method internally

func (*Client) NewRequest

func (cl *Client) NewRequest(c context.Context, method, urlStr string, opts ...RequestOption) (*Request, error)

NewRequest returns a new Request with the given method/url and options executed

func (*Client) Patch

func (cl *Client) Patch(c context.Context, url string, opts ...RequestOption) (*Response, error)

Patch is a helper func for Do, setting the Method internally

func (*Client) Post

func (cl *Client) Post(c context.Context, url string, opts ...RequestOption) (*Response, error)

Post is a helper func for Do, setting the Method internally

func (*Client) Put

func (cl *Client) Put(c context.Context, url string, opts ...RequestOption) (*Response, error)

Put is a helper func for Do, setting the Method internally

type ClientOption

type ClientOption func(c context.Context, cl *Client) error

ClientOption is a func to configure optional Client settings

func WithClientDebugLogFunc

func WithClientDebugLogFunc(fn LogFunc) ClientOption

WithClientDebugLogFunc pipes all debug logs to the supplied function All requests from this client inherit this logger

func WithClientErrorLogFunc

func WithClientErrorLogFunc(fn LogFunc) ClientOption

WithClientErrorLogFunc pipes all error logs to the supplied function All requests from this client inherit this logger

func WithHandshakeTimeout

func WithHandshakeTimeout(dur time.Duration) ClientOption

WithHandshakeTimeout is a ClientOption that sets the cl.handshakeTimeout field to the given duration

func WithKeepAlive

func WithKeepAlive(dur time.Duration) ClientOption

WithKeepAlive is a ClientOption that sets the cl.keepAlive field to the given duration

func WithMaxIdleConnsPerHost

func WithMaxIdleConnsPerHost(maxConns int) ClientOption

WithMaxIdleConnsPerHost is a ClientOption that sets the cl.maxIdleConnsPerHost field to the given int

func WithRateLimit

func WithRateLimit(rate int, dur time.Duration) ClientOption

WithRateLimit is a ClientOption that sets the cl.rateLimitting up for this client

func WithRequestOptions

func WithRequestOptions(opts []RequestOption) ClientOption

WithRequestOptions sets RequestOptions to be inherited by each NewRequest

type DecodeFunc

type DecodeFunc func(io.Reader, interface{}) error

DecodeFunc allows users to provide a custom decoder to use with Decode

type DecodeOption

type DecodeOption func(c context.Context, resp *Response) error

DecodeOption is a func to configure optional Response settings

func WithCopiedBody

func WithCopiedBody() DecodeOption

WithCopiedBody makes a copy of the body available in the response. This is helpful if you anticipate the decode failing and want to do a full dump of the response.

func WithCustomFunc

func WithCustomFunc(decodeFunc DecodeFunc) DecodeOption

WithCustomFunc uses the provided DecodeFunc to Decode the response

func WithGobBody

func WithGobBody() DecodeOption

WithGobBody gob decodes the body of the Response

func WithJSONBody

func WithJSONBody() DecodeOption

WithJSONBody json decodes the body of the Response

func WithXMLBody

func WithXMLBody() DecodeOption

WithXMLBody xml decodes the body of the Response

type Fetcher

type Fetcher interface {
	Do(c context.Context, req *Request) (*Response, error)
	NewRequest(c context.Context, method, url string, opts ...RequestOption) (*Request, error)
	Get(c context.Context, url string, opts ...RequestOption) (*Response, error)
	Head(c context.Context, url string, opts ...RequestOption) (*Response, error)
	Post(c context.Context, url string, opts ...RequestOption) (*Response, error)
	Put(c context.Context, url string, opts ...RequestOption) (*Response, error)
	Patch(c context.Context, url string, opts ...RequestOption) (*Response, error)
	Delete(c context.Context, url string, opts ...RequestOption) (*Response, error)
}

Fetcher is the interface that a Client will need to implement in order to execute a Request

type LogFunc

type LogFunc func(string)

LogFunc is a pluggable log function

type Request

type Request struct {
	// contains filtered or unexported fields
}

Request contains the data for a http.Request to be created

func (*Request) Equal

func (req *Request) Equal(reqComp *Request) (bool, string)

Equal compares the request with another request If not equal, a string is returned with first field found different used by fetchermock

func (Request) String

func (req Request) String() string

String is a stringer for Request

type RequestOption

type RequestOption func(c context.Context, req *Request) error

RequestOption is a func to configure optional Request settings

func WithAcceptJSONHeader

func WithAcceptJSONHeader() RequestOption

WithAcceptJSONHeader adds Accept: application/json to the Request headers

func WithAfterDoFunc

func WithAfterDoFunc(afterDoFunc func(req *Request, resp *Response) error) RequestOption

WithAfterDoFunc allows user-defined functions to access Request and Response (read-only)

func WithBaseURL

func WithBaseURL(baseURL string) RequestOption

WithBaseURL prepends the req.url with the given baseURL

func WithBasicAuth

func WithBasicAuth(username, password string) RequestOption

WithBasicAuth sets HTTP Basic Authentication authorization header

func WithBytesPayload

func WithBytesPayload(payload []byte) RequestOption

WithBytesPayload sets the given payload for the Request

func WithClientTrace

func WithClientTrace(clientTrace *httptrace.ClientTrace) RequestOption

WithClientTrace is a convenience function around httptrace.WithClientTrace

func WithCookie

func WithCookie(cookie *http.Cookie) RequestOption

WithCookie adds a single cookie to the request

func WithCookies

func WithCookies(cookies []*http.Cookie) RequestOption

WithCookies adds a slice of cookies to the request

func WithDeadline

func WithDeadline(deadline time.Time) RequestOption

WithDeadline is a convenience function around context.WithDeadline

func WithDefaultBackoff

func WithDefaultBackoff() RequestOption

WithDefaultBackoff uses ExponentialJitterBackoff with min: 1s and max: 30s

func WithExponentialBackoff

func WithExponentialBackoff(min, max time.Duration) RequestOption

WithExponentialBackoff multiplies the min duration by 2^(attempt number - 1), doubling the delay on each attempt

func WithExponentialJitterBackoff

func WithExponentialJitterBackoff(min, max time.Duration) RequestOption

WithExponentialJitterBackoff multiplies the min duration by 2^(attempt number - 1), doubling the delay on each attempt with the each successive interval adjusted +/- 0-33%

func WithFilepathMultipartPayload

func WithFilepathMultipartPayload(fieldname, filepath string) RequestOption

WithFilepathMultipartPayload takes a filepath, opens the file and adds it to the request with the fieldname

func WithGobPayload

func WithGobPayload(payload interface{}) RequestOption

WithGobPayload gob encodes the payload for the Request and sets the content-type and accept header to application/gob

func WithHeader

func WithHeader(key, value string) RequestOption

WithHeader adds the given key/value combo to the Request headers

func WithJSONPayload

func WithJSONPayload(payload interface{}) RequestOption

WithJSONPayload json marshals the payload for the Request and sets the content-type and accept header to application/json

func WithLinearBackoff

func WithLinearBackoff(interval, min, max time.Duration) RequestOption

WithLinearBackoff increases its delay by interval duration on each attempt

func WithLinearJitterBackoff

func WithLinearJitterBackoff(interval, min, max time.Duration) RequestOption

WithLinearJitterBackoff increases its delay by interval duration on each attempt, with the each successive interval adjusted +/- 0-33%

func WithMaxAttempts

func WithMaxAttempts(maxAttempts int) RequestOption

WithMaxAttempts sets the max number of times to attempt the Request on 5xx status code must be at least 1

func WithMultipartField

func WithMultipartField(fieldname, value string) RequestOption

WithMultipartField adds the fieldname and value to the multipart fields

func WithNoBackoff

func WithNoBackoff(delay time.Duration) RequestOption

WithNoBackoff waits delay duration on each retry, regardless of attempt number

func WithParam

func WithParam(key, value string) RequestOption

WithParam adds parameter value to be encoded for the Request

func WithReaderMultipartPayload

func WithReaderMultipartPayload(fieldname, filename string, data io.Reader) RequestOption

WithReaderMultipartPayload takes a filepath, opens the file and adds it to the request with the fieldname

func WithReaderPayload

func WithReaderPayload(payload io.Reader) RequestOption

WithReaderPayload sets the given payload for the Request

func WithRequestDebugLogFunc

func WithRequestDebugLogFunc(fn LogFunc) RequestOption

WithRequestDebugLogFunc pipes all debug logs to the supplied function This overrides and replaces the inherited client functions

func WithRequestErrorLogFunc

func WithRequestErrorLogFunc(fn LogFunc) RequestOption

WithRequestErrorLogFunc pipes all error logs to the supplied function This overrides and replaces the inherited client functions

func WithRetryOnEOFError

func WithRetryOnEOFError() RequestOption

WithRetryOnEOFError adds the io.EOF error to the retry loop The io.EOF error indicates sending on a broken connection (see https://github.com/golang/go/issues/8946 & https://github.com/golang/go/issues/5312) Including this option with a Request will allow fetcher to retry the request on io.EOF, in attempt to obtain a valid connection

func WithTimeout

func WithTimeout(timeout time.Duration) RequestOption

WithTimeout is a convenience function around context.WithTimeout

func WithURLEncodedPayload

func WithURLEncodedPayload(payload url.Values) RequestOption

WithURLEncodedPayload encodes the payload for the Request and sets the content-type header to application/x-www-form-urlencoded

type Response

type Response struct {
	// contains filtered or unexported fields
}

Response is returned after executing client.Do

func NewResponse

func NewResponse(c context.Context, req *Request, resp *http.Response) *Response

NewResponse returns a Response with the given Request and http.Response

func (*Response) Body

func (resp *Response) Body() io.Reader

Body returns the resp.response.Body as io.Reader NOTE: original io.ReadCloser body is closed when Close is called by the user

func (*Response) Bytes

func (resp *Response) Bytes() ([]byte, error)

Bytes reads the body into a buffer and then returns the bytes returns error based on resp.response.Body.Close()

func (*Response) Close

func (resp *Response) Close() error

Close handles any needed clean-up after the user is done with the Response object

func (*Response) ContentType

func (resp *Response) ContentType() string

ContentType returns the Content-Type header value of the Response

func (*Response) Decode

func (resp *Response) Decode(c context.Context, v interface{}, opts ...DecodeOption) error

Decode decodes the resp.response.Body into the given object (v) using the specified decoder NOTE: v is assumed to be a pointer

func (*Response) FinalURL

func (resp *Response) FinalURL() *url.URL

FinalURL returns the final URL from resp.Request

func (*Response) MustBytes

func (resp *Response) MustBytes() []byte

MustBytes reads the body into a buffer and then returns the bytes

func (*Response) RequestURL

func (resp *Response) RequestURL() string

RequestURL returns the resp.request.url

func (*Response) Status

func (resp *Response) Status() string

Status exports resp.Status

func (*Response) StatusCode

func (resp *Response) StatusCode() int

StatusCode exports resp.StatusCode

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL