hx

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Nov 14, 2019 License: MIT Imports: 14 Imported by: 3

README

hx

CI GoDoc codecov License

Developer-friendly, Production-ready and extensible HTTP client for Go

Features

...

Plugins
  • retry
  • pb - Marshaling and Unmarshaling protocol buffers

Examples

Simple GET
type Content struct {
	Body string `json:"body"`
}

var cont Content

ctx := context.Background()
err := hx.Get(ctx, "https://api.example.com/contents/1",
	hx.WhenSuccess(hx.AsJSON(&cont)),
	hx.WhenFailure(hx.AsError()),
)
Real-world
func init() {
	defaultTransport := hxutil.CloneTransport(http.DefaultTransport.(*http.Transport))

	// Tweak keep-alive configuration
	defaultTransport.MaxIdleConns = 500
	defaultTransport.MaxIdleConnsPerHost = 100

	// Set global options
	hx.DefaultOptions = append(
		hx.DefaultOptions,
		hx.UserAgent(fmt.Sprintf("yourapp (%s)", hx.DefaultUserAgent)),
		hx.Transport(defaultTransport),
		hx.TransportFrom(func(rt http.RoundTripper) http.RoundTripper {
			return &ochttp.Transport{Base: rt}
		}),
	)
}

func NewContentAPI() *hx.Client {
	// Set common options for API ciient
	return &ContentAPI{
		client: hx.NewClient(
			hx.BaseURL("https://api.example.com"),
		),
	}
}

type ContentAPI struct {
	client *hx.Client
}

func (a *ContentAPI) GetContent(ctx context.Context, id int) (*Content, error) {
	var cont Content

	err := a.client.Get(ctx, hx.Path("api", "contents", id),
		hx.WhenSuccess(hx.AsJSON(&cont)),
		hx.WhenFailure(hx.AsError()),
	)

	if err != nil {
		// ...
	}

	return &cont, nil
}

func (a *ContentAPI) CreateContent(ctx context.Context, in *Content) (*Content, error) {
	var out Content

	err := a.client.Post(ctx, "/api/contents",
		hx.JSON(in),
		hx.WhenSuccess(hx.AsJSON(&out)),
		hx.WhenStatus(hx.AsJSONError(&InvalidArgument{}), http.StatusBadRequest),
		hx.WhenFailure(hx.AsError()),
	)

	if err != nil {
		var (
			invalidArgErr *InvalidArgument
			respErr       *hx.ResponseError
		)
		if errors.As(err, &invalidArgErr) {
			// handle known error
		} else if errors.As(err, &respErr) {
			// handle unknown response error
		} else {
			err := errors.Unwrap(err)
			// handle unknown error
		}
	}

	return &out, nil
}

Documentation

Index

Examples

Constants

View Source
const Version = "0.3.0"

Variables

View Source
var (
	DefaultUserAgent = fmt.Sprintf("hx/%s; %s", Version, runtime.Version())
	DefaultOptions   = []Option{
		UserAgent(DefaultUserAgent),
	}
)

Functions

func Delete

func Delete(ctx context.Context, url string, opts ...Option) error

func Get

func Get(ctx context.Context, url string, opts ...Option) error
Example
package main

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/izumin5210/hx"
)

func main() {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		switch {
		case r.Method == http.MethodGet && r.URL.Path == "/echo":
			err := json.NewEncoder(w).Encode(map[string]string{
				"message": r.URL.Query().Get("message"),
			})
			if err != nil {
				w.WriteHeader(http.StatusInternalServerError)
				return
			}
		default:
			w.WriteHeader(http.StatusNotFound)
		}
	}))
	defer ts.Close()

	var out struct {
		Message string `json:"message"`
	}

	ctx := context.Background()
	err := hx.Get(
		ctx,
		ts.URL+"/echo",
		hx.Query("message", "It Works!"),
		hx.WhenSuccess(hx.AsJSON(&out)),
		hx.WhenFailure(hx.AsError()),
	)
	if err != nil {
		// Handle errors...
	}
	fmt.Println(out.Message)

}
Output:

It Works!

func Patch

func Patch(ctx context.Context, url string, opts ...Option) error

func Path

func Path(elem ...interface{}) string

func Post

func Post(ctx context.Context, url string, opts ...Option) error

func Put

func Put(ctx context.Context, url string, opts ...Option) error

Types

type Client

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

func NewClient

func NewClient(opts ...Option) *Client

NewClient creates a new http client instance.

func (*Client) Delete

func (c *Client) Delete(ctx context.Context, url string, opts ...Option) error

func (*Client) Get

func (c *Client) Get(ctx context.Context, url string, opts ...Option) error

func (*Client) Patch

func (c *Client) Patch(ctx context.Context, url string, opts ...Option) error

func (*Client) Post

func (c *Client) Post(ctx context.Context, url string, opts ...Option) error

func (*Client) Put

func (c *Client) Put(ctx context.Context, url string, opts ...Option) error

func (*Client) With added in v0.2.0

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

With clones the current client and applies the given options.

type Config

type Config struct {
	URL              *url.URL
	Body             io.Reader
	HTTPClient       *http.Client
	QueryParams      url.Values
	RequestHandlers  []RequestHandler
	ResponseHandlers []ResponseHandler
}

func NewConfig added in v0.1.1

func NewConfig() (*Config, error)

func (*Config) Apply

func (cfg *Config) Apply(opts ...Option) error

func (*Config) DoRequest

func (cfg *Config) DoRequest(ctx context.Context, meth string) (*http.Response, error)

type Option

type Option interface {
	ApplyOption(*Config) error
}

func Authorization

func Authorization(scheme, token string) Option

Authorization sets an authorization scheme and a token of an user.

func BaseURL

func BaseURL(baseURL *url.URL) Option

func BasicAuth

func BasicAuth(username, password string) Option

BasicAuth sets an username and a password for basic authentication.

func Bearer

func Bearer(token string) Option

func Body

func Body(v interface{}) Option

Body sets data to request body.

func CombineOptions

func CombineOptions(opts ...Option) Option

func HTTPClient

func HTTPClient(cli *http.Client) Option

HTTPClient sets a HTTP client that used to send HTTP request(s).

func HandleRequest added in v0.2.0

func HandleRequest(f func(*http.Request) (*http.Request, error)) Option

func HandleResponse added in v0.2.0

func HandleResponse(f func(*http.Response, error) (*http.Response, error)) Option
func Header(k, v string) Option

Header sets a value to request header.

func JSON

func JSON(v interface{}) Option

JSON sets data to request body as json.

func Query

func Query(k, v string) Option

Query sets an url query parameter.

func Timeout

func Timeout(t time.Duration) Option

Timeout sets the max duration for http request(s).

func Transport

func Transport(rt http.RoundTripper) Option

Transport sets the round tripper to http.Client.

func TransportFrom

func TransportFrom(f func(http.RoundTripper) http.RoundTripper) Option

TransportFrom sets the round tripper to http.Client.

func TransportFunc added in v0.2.0

func TransportFunc(f func(*http.Request, http.RoundTripper) (*http.Response, error)) Option

func URL

func URL(urlStr string) Option

func UserAgent

func UserAgent(ua string) Option

func When

func WhenClientError

func WhenClientError(h ResponseHandler) Option

func WhenFailure

func WhenFailure(h ResponseHandler) Option

func WhenServerError

func WhenServerError(h ResponseHandler) Option

func WhenStatus

func WhenStatus(h ResponseHandler, codes ...int) Option

func WhenSuccess

func WhenSuccess(h ResponseHandler) Option

type OptionFunc

type OptionFunc func(*Config) error

func (OptionFunc) ApplyOption added in v0.1.1

func (f OptionFunc) ApplyOption(c *Config) error

type RequestHandler

type RequestHandler func(*http.Request) (*http.Request, error)

type ResponseError

type ResponseError struct {
	Response *http.Response
	Err      error
}

func (*ResponseError) Error

func (e *ResponseError) Error() string

func (*ResponseError) Unwrap

func (e *ResponseError) Unwrap() error

type ResponseHandler

type ResponseHandler func(*http.Response, error) (*http.Response, error)

func AsError

func AsError() ResponseHandler

func AsJSON

func AsJSON(dst interface{}) ResponseHandler

func AsJSONError added in v0.2.0

func AsJSONError(dst error) ResponseHandler

AsJSONError is ResponseHandler that will populate an error with the JSON returned within the response body. And it will wrap the error with ResponseError and return it.

err := hx.Post(ctx, "https://example.com/posts",
	hx.JSON(body)
	hx.WhenSuccess(hx.AsJSON(&post), http.StatusBadRequest),
	hx.WhenStatus(hx.AsErrorOf(&InvalidArgument{}), http.StatusBadRequest),
	hx.WhenFailure(hx.AsError()),
)
if err != nil {
	var (
		invalidArgErr *InvalidArgument
		respErr       *hx.ResponseError
	)
	if errors.As(err, &invalidArgErr) {
		// handle known error
	} else if errors.As(err, &respErr) {
		// handle unknown response error
	} else {
		err := errors.Unwrap(err)
		// handle unknown error
	}
}

type ResponseHandlerCond

type ResponseHandlerCond func(*http.Response, error) bool
var (
	IsSuccess        ResponseHandlerCond = checkStatus(func(c int) bool { return c/100 == 2 })
	IsFailure        ResponseHandlerCond = Not(IsSuccess)
	IsClientError    ResponseHandlerCond = checkStatus(func(c int) bool { return c/100 == 4 })
	IsServerError    ResponseHandlerCond = checkStatus(func(c int) bool { return c/100 == 5 })
	IsTemporaryError ResponseHandlerCond = func(r *http.Response, err error) bool {
		terr, ok := err.(interface{ Temporary() bool })
		return ok && terr.Temporary()
	}
)

func Any

func IsStatus

func IsStatus(codes ...int) ResponseHandlerCond

Directories

Path Synopsis
pb module
retry module

Jump to

Keyboard shortcuts

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