cake

package module
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Jul 10, 2023 License: MIT Imports: 18 Imported by: 1

README

Cake

Cake is a lightweight HTTP client library for GO, inspired by java feign.

Installation

# With Go Modules, recommanded with go version > 1.16
go get github.com/snownd/cake

Usage

Simple Get
type User struct {
	ID        string    `json:"id"`
	Phone     string    `json:"phone"`
	Name      string    `json:"name"`
	Avatar    string    `json:"avatar"`
	CreatedAt time.Time `json:"createdAt"`
}

type UserListRequestConfig struct {
	cake.RequestConfig
	Limit    int    `query:"limit"`
	Page     int    `query:"page"`
}

type TestApi struct {
	Users func(ctx context.Context, config *UserListRequestConfig) ([]*User, error) `method:"GET" url:"/users"`
}

func main() {
	factory := cake.NewFactoryWithClient(http.DefaultClient)
	apiIntf, err := factory.Build(&TestApi{}, cake.WithBaseURL("https://{id}.mockapi.io/api/v1"))
	if err != nil {
		panic(err)
	}
	api := apiIntf.(*TestApi)
	u, err := api.Users(context.Background(), &UserListRequestConfig{
		Limit:    10,
		Page:     1,
	})
	if err != nil {
		panic(err)
	}
	r, _ := json.Marshal(u)
	fmt.Println(string(r))
	if len(u) != 10 {
		panic(errors.New("invalid result set"))
	}
}

Post with body
type UserCreateRequestConfig struct {
	cake.RequestConfig
  Data *User `body:"application/json"`
}

type TestApi struct {
	Users func(ctx context.Context, config *UserListRequestConfig) ([]*User, error) `method:"GET" url:"/users"`
  CreateUser func(ctx context.Context, config *UserCreateRequestConfig) ([]*User, error) `method:"POST" url:"/users"`
}

For more, see example

Performance

Ran GOMAXPROCS=1 go test -bench=. -benchtime=5s -benchmem on a Macbook Pro 14(M1 Pro) with go1.18:

goos: darwin
goarch: arm64
pkg: github.com/snownd/cake
BenchmarkHTTPClientGet            240624             23627 ns/op            6368 B/op         76 allocs/op
BenchmarkCakeGet                  235514             24969 ns/op            7479 B/op         96 allocs/op
BenchmarkHTTPClientPost           239326             24438 ns/op            7841 B/op         91 allocs/op
BenchmarkCakePost                 222906             26909 ns/op            8866 B/op        106 allocs/op
PASS
ok      github.com/snownd/cake  24.612s

For Get request, there are 5 out of 20 allocs simply caused by extra headers like Accept, Accept-Encoding and User-Agent.

There is a bit of performance impacts because of uses of reflect(nearly 8%). Still, it should be fast enough for most cases.

Documentation

Index

Constants

View Source
const (
	ContentTypeJson = "application/json"
	ContentTypeText = "text/plain"
	ContentTypeForm = "application/x-www-form-urlencoded"
)
View Source
const (
	// alias for ContentTypeJson
	ContentTypeAliasJson ContentTypeAlias = "json"
	// alias for ContentTypeText
	ContentTypeAliasText = "text"
	// alias for ContentTypeForm
	ContentTypeAliasForm = "form"
)
View Source
const (
	HeaderAccept          = "Accept"
	HeaderAcceptEncoding  = "Accept-Encoding"
	HeaderContentType     = "Content-Type"
	HeaderContentEncoding = "Content-Encoding"
	HeaderContentLength   = "Content-Length"
	HeaderUserAgent       = "User-Agent"
)
View Source
const (
	APIFuncArgTagParam   = "param"
	APIFuncArgTagHeader  = "header"
	APIFuncArgTagHeaders = "headers"
	APIFuncArgTagBody    = "body"
	APIFuncArgTagQuery   = "query"
	// application/x-www-form-urlencoded
	APIFuncArgTagForm = "form"
)
View Source
const (
	TagMethod  = "method"
	TagURL     = "url"
	TagHeaders = "headers"
)
View Source
const Version = "0.6.0"

Variables

View Source
var AcceptEncoding = []string{"gzip", "deflate"}
View Source
var ErrInvalidBody = errors.New("cake: invalid body")
View Source
var ErrInvalidBuildTarget = errors.New("cake: invalid build target")
View Source
var ErrInvalidRequestFunction = errors.New("cake: invalid request function")
View Source
var ErrRequestFailed = errors.New("cake: request failed")
View Source
var ErrUnexpectedResponseContentType = errors.New("cake: unexpected response Content-Type")
View Source
var UserAgent = []string{"cake/" + Version}

Functions

func GetContentType added in v0.4.3

func GetContentType(header http.Header) string

GetContentType returns the content type of the request with try to get not CanonicalMIMEHeader

func IsContext

func IsContext(o interface{}) bool

func IsError

func IsError(o interface{}) bool

func IsRequestConfig

func IsRequestConfig(o interface{}) bool

Types

type BodyEncoder

type BodyEncoder interface {
	ContentType() string
	EncodeBody(body interface{}) (int, io.Reader, error)
}

type BuildOption

type BuildOption func(opt *buildOptions)

func WithBaseURL

func WithBaseURL(url string) BuildOption

func WithDefaultContenType added in v0.3.0

func WithDefaultContenType(ct string) BuildOption

func WithEncoder

func WithEncoder(contentType string, encoder BodyEncoder) BuildOption

func WithRequestMiddleware added in v0.2.0

func WithRequestMiddleware(mw RequestMiddleware) BuildOption

WithRequestMiddleware can be called multiple times

type ContentTypeAlias added in v0.4.0

type ContentTypeAlias string

func (ContentTypeAlias) GetContentType added in v0.4.0

func (c ContentTypeAlias) GetContentType() string

type DefaultJSONEncoder

type DefaultJSONEncoder struct {
}

func (*DefaultJSONEncoder) ContentType

func (e *DefaultJSONEncoder) ContentType() string

func (*DefaultJSONEncoder) EncodeBody

func (e *DefaultJSONEncoder) EncodeBody(body interface{}) (int, io.Reader, error)

type DefaultTextEncoder

type DefaultTextEncoder struct {
}

func (*DefaultTextEncoder) ContentType

func (e *DefaultTextEncoder) ContentType() string

func (*DefaultTextEncoder) EncodeBody

func (e *DefaultTextEncoder) EncodeBody(body interface{}) (int, io.Reader, error)

type Factory

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

func New

func New(opts ...BuildOption) *Factory

func NewFactoryWithClient

func NewFactoryWithClient(client *http.Client, opts ...BuildOption) *Factory

func (*Factory) Build

func (f *Factory) Build(target interface{}, opts ...BuildOption) (interface{}, error)

func (*Factory) Close added in v0.1.1

func (f *Factory) Close()

type RequestConfig

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

type RequestContext added in v0.5.0

type RequestContext struct {
	Request  *http.Request
	Response *http.Response
	// contains filtered or unexported fields
}

func (*RequestContext) Next added in v0.5.0

func (c *RequestContext) Next() error

type RequestError

type RequestError interface {
	error
	Unwrap() error
	StatusCode() int
	Request() *http.Request
	Response() *http.Response
	Body() []byte
}

func NewRequestError

func NewRequestError(req *http.Request, res *http.Response) RequestError

type RequestHandler added in v0.5.0

type RequestHandler func(c *RequestContext) error

type RequestMethod

type RequestMethod = string

type RequestMiddleware added in v0.2.0

type RequestMiddleware = RequestHandler

type RequestMiddlewareDesprate added in v0.5.0

type RequestMiddlewareDesprate func(*http.Request) error

type TagMap

type TagMap = map[string]string

func NewTagMap

func NewTagMap(tag reflect.StructTag) TagMap

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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