httpc

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2024 License: MIT Imports: 7 Imported by: 0

README

httpc

Simple wrapping of the existing http.Client with some additional functionality.

How to use

stdlib compatibility

As the client extends a *http.Client you can use the existing functionality as defined in the stdlib.

client := httpc.New()

resp, err := client.Get("example.com")
... // handle the response and error

resp, err := client.Do(req)
...

underlyingClient := client.Unwrap() // of type *http.Client
// pass this to calls that require type *http.Client
// still contains all layers of http.RoundTripper
Extensions

Beyond the existing functions of the stdlib http client there are few convenience wrappers in place to help reduce repetitive coding tasks. All outgoing calls DoReq(), JSON() and Stream() close the response's body and replace it with a NopCloser.

client := httpc.New(WithTimeout(10 * time.Second)) // optional options can be passed to the initial setup
h := http.Header{}
h.Set("key", "value")
client.AddOptions(WithHeaders(h)) // further options can be added

resp, err := client.DoReq(req, WithStatusCode(http.StatusOk)) // call like Do() with additional check of the status code
...

type Person struct {
	FirstName string `json:"firstName"`
	LastName string `json:"lastName"`
}

var p Person
resp, err := client.JSON(req, &p, WithStatusCode(http.StatusOk)) // decodes the response to the given pointer
...

f, _ := os.OpenFile("data.out", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
written, err := client.Stream(req, f) // stream the response to a file
...
Error Handling

Only additional functionality calls do support error handling. For HTTP status codes above 400 the error handler is called. By default, the response body is read as is and be added to the error message. See the examples below to add custom error types.

client := httpc.New(WithJSONError())

_, err := client.DoReq(req) // if fails, attempts to parse response body as arbitrary JSON
// err should be of type JSONErrorBody map[string]any
// can be used to access error details

type ApiError struct {
	Code int `json:"code"`
	Msg string `json:"msg"`
}

client := httpc.New(WithCustomJSONError[ApiError]())

_, err := client.DoReq(req) // if fails, attempts to parse response body as given error
// err should be of type ApiError

Documentation

Index

Constants

View Source
const DefaultTimeout = 30 * time.Second

Variables

View Source
var DefaultTransport = &http.Transport{
	Proxy:                 http.ProxyFromEnvironment,
	ForceAttemptHTTP2:     true,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
}

Functions

This section is empty.

Types

type BytesErrorBody

type BytesErrorBody []byte

func (BytesErrorBody) Error

func (e BytesErrorBody) Error() string

type Client

type Client struct {
	*http.Client
	// contains filtered or unexported fields
}

func New

func New(opts ...Option) *Client

func (*Client) AddOptions

func (c *Client) AddOptions(opts ...Option)

func (*Client) DoReq

func (c *Client) DoReq(req *http.Request, opts ...RespOption) (*http.Response, error)

func (*Client) Extend

func (c *Client) Extend(opts ...Option) *Client

func (*Client) JSON

func (c *Client) JSON(req *http.Request, obj any, opts ...RespOption) (*http.Response, error)

func (*Client) Stream

func (c *Client) Stream(req *http.Request, w io.Writer) (int64, error)

func (*Client) Unwrap

func (c *Client) Unwrap() *http.Client

type Config

type Config struct {
	Transport     *http.Transport
	CheckRedirect func(req *http.Request, via []*http.Request) error
	Jar           http.CookieJar
	Timeout       time.Duration
	JsonUnmarshal JsonUnmarshaler
	// contains filtered or unexported fields
}

type ErrorHandler

type ErrorHandler func(c *Client, resp *http.Response, body []byte) error

type HeaderLayer

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

func (*HeaderLayer) RoundTrip

func (h *HeaderLayer) RoundTrip(req *http.Request) (*http.Response, error)

type JSONErrorBody

type JSONErrorBody map[string]any

func (JSONErrorBody) Error

func (e JSONErrorBody) Error() string

type JsonUnmarshaler

type JsonUnmarshaler func(data []byte, obj any) error

type Layer

type Layer func(base http.RoundTripper) http.RoundTripper

type Option

type Option func(cfg *Config)

func WithBytesError

func WithBytesError() Option

func WithCheckRedirect

func WithCheckRedirect(fn func(req *http.Request, via []*http.Request) error) Option

func WithCookieJar

func WithCookieJar(jar http.CookieJar) Option

func WithCustomJSONError

func WithCustomJSONError[E error]() Option

func WithErrorHandler

func WithErrorHandler(h ErrorHandler) Option

func WithHeaders

func WithHeaders(h http.Header) Option

func WithJSONError

func WithJSONError() Option

func WithLayer

func WithLayer(l Layer) Option

func WithTimeout

func WithTimeout(t time.Duration) Option

func WithTransport

func WithTransport(t *http.Transport) Option

type RespOption

type RespOption func(c *Client, resp *http.Response, body []byte) error

RespOption is an option to handle a successful http.Response pointer. Aborts if the first option returns an error. The response's body is already read and closed. The read data is passed as parameter.

func WithCopy

func WithCopy(w io.Writer) RespOption

WithCopy copies the body of the http.Response to the given io.Writer.

func WithJSON

func WithJSON(obj any) RespOption

WithJSON unmarshalls the body of the http.Response into the given object using the Config.JsonUnmarshal function.

func WithStatusCode

func WithStatusCode(code int) RespOption

WithStatusCode checks if the http.Response matches the given HTTP status code. Returns an error if the status code does not match.

Jump to

Keyboard shortcuts

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