gent

package module
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Feb 16, 2024 License: MIT Imports: 10 Imported by: 0

README

Go HTTP Client

Build Coverage Go Report Card Go Reference

Gent is a Golang HTTP Client wrapper that provides additional features for flexibility and increased performance.

Usage

Create a Client that lets you to make requests. The constructor accepts a list of options to customize it.

// Default client
cl := gent.NewClient()

To make requests, use the functions named after HTTP methods. The following example sends a POST request to http://localhost:8080/employees/create with an application/json body containing an employee id and name, an Authorization header, and a query parameter set to true.

res, err := cl.Post(
    context.Background(),
    "http://localhost:8080/{}/{}",
    map[string]string{
        "id": "4481e035-1711-419f-82bc-bfb72da06375",
        "name": "John Smith",
    },
    gent.NewJSONMarshaler(),
    map[string]string{
 		"Authorization": "Bearer x.y.z",
	},
    map[string][]string{
 		"strict":    {"true"},
 	},
    "employees",
    "create",
)
Placeholders

The request's endpoint supports placeholders in the form of {}. Placeholders will be populated by the trailing variadic path parameters that get escaped before replacing the placeholders in the order they were provided.

Request Body

Any data can be provided as a request body, and it is up to the marshaler to transform it into a byte array for the request. By default the package supports JSON, XML and Form marshalers. If you do not require a request body, leave both the body and the marshaler nil.

Marshalers must implement Marshal(body any) (data []byte, content string, err error), which take any input and return a byte array data, a content type for the header and any error. The following is the implementation of the JSON Marshaler for reference.

type jsonMarshaler struct{}

func (m *jsonMarshaler) Marshal(
    v any,
) (dat []byte, t string, err error) {
	t = "application/json"
	dat, err = json.Marshal(v)
	return
}
Query Parameters

Query parameters are constructed from a map and include a ? if there is at least one query parameter provided. It is recommended to add query parameters via the map, as they get escaped. Parameters support arrays, which get added in the following format:

map[string][]string{
    // ?ids=123&ids=456&ids=789
    "ids": {"123", "456", "789"}
}

Options and Modules

The Client can be configured during creation with a variety of options.

cl := gent.NewClient(
    /* ... Option */
)
HTTP Client

The client internally uses the default HTTP Client to make requests. This can be changed with the UseHttpClient option. The default behavior is to reuse clients between requests. This can also be changed by providing a constructor function that returns a new client for each request.

// Client that uses a new HTTP client
cl := gent.NewClient(
    gent.UseHttpClient(&http.Client{}),
)
// Client that creates a new HTTP client for each request
cl := gent.NewClient(
    gent.UseHttpClientConstructor(func() gent.HttpClient{
        return &http.Client{}
    }),
)
Memory Pool

Each client uses a memory pool internally to speed up string operations by reusing memory allocations. By default, each client creates its own memory pool with default page sizes and pool sizes. A pre-configured memory pool can be provided to and even shared between clients.

cl := gent.NewClient(
    gent.UseMemoryPool(gent.NewMemPool(
        512, // Page size in bytes
        200, // Pool size in pages
    )),
)

You can provide your own implementation of memory pool if it implements how to acquire byte arrays from the pool with Acquire() []byte and release byte arrays into the pool with Release(...[]byte)

Retrier

Requests can be retried on failure if the client uses a retrier. The package provides two retrier implementations, one which only retries requests if they failed with an error, and one which can optionally retry requests which failed with specific status codes. Both retriers need a numeric limit on retries and a delay function that returns a duration to wait for before trying again.

cl := gent.NewClient(
    gent.UseRetrier(gent.NewStatusCodeRetrier(
        10, // Max retries (-1 for infinite)
        retrier.ConstantDelay(time.Second), // Delay function
        []int{418,425,429,500}, // Retried status codes
    )),
)

The retrier package used internally has a range of delay functions to be used

Middlewares

Clients can be given middlewares that are executed for each request. There are two types of middlewares. High Level middlewares are executed before the endpoint is constructed from path and query parameters or the body is marshaled. Low Level middlewares are executed right before the request is constructed and handled by the internal client.

The following is an example of a middleware that injects an Authorization header.

cl := gent.NewClient(
    gent.UseLowLevelMiddleware(
        func(c context.Context, r *gent.Request) {
            r.AddHeader("Authorization", "Bearer x.y.z")
            r.Next()
        },
    ),
)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewBasicRetrier

func NewBasicRetrier(
	max int,
	delayf func(int) time.Duration,
) *retrier

NewBasicRetrier creates a retrier that retries requests up to an upper limit and waits for some duration between retries defined by the delay function. The basic retrier will only retry when the error is not nil.

func NewStatusCodeRetrier

func NewStatusCodeRetrier(
	max int,
	delayf func(int) time.Duration,
	retryCodes []int,
) *retrier

NewStatusCodeRetrier creates a retrier that retries requests up to an upper limit and waits for some duration between retries defined by the delay function. The basic retrier will only retry when the error is not nil.

Types

type Client

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

Client wraps an http.Client with additional functionality.

func NewClient

func NewClient(opts ...Option) *Client

NewClient creates a Client with options.

func (*Client) Delete

func (c *Client) Delete(
	ctx context.Context,
	endpoint string,
	body any,
	marshaler Marshaler,
	headers map[string]string,
	queryParam map[string][]string,
	pathParams ...string,
) (res *http.Response, err error)

func (*Client) Do

func (c *Client) Do(
	ctx context.Context,
	method string,
	endpoint string,
	body any,
	marshaler Marshaler,
	headers map[string]string,
	queryParam map[string][]string,
	pathParams ...string,
) (res *http.Response, err error)

func (*Client) Get

func (c *Client) Get(
	ctx context.Context,
	endpoint string,
	body any,
	marshaler Marshaler,
	headers map[string]string,
	queryParam map[string][]string,
	pathParams ...string,
) (res *http.Response, err error)

func (*Client) Patch

func (c *Client) Patch(
	ctx context.Context,
	endpoint string,
	body any,
	marshaler Marshaler,
	headers map[string]string,
	queryParam map[string][]string,
	pathParams ...string,
) (res *http.Response, err error)

func (*Client) Post

func (c *Client) Post(
	ctx context.Context,
	endpoint string,
	body any,
	marshaler Marshaler,
	headers map[string]string,
	queryParam map[string][]string,
	pathParams ...string,
) (res *http.Response, err error)

func (*Client) Put

func (c *Client) Put(
	ctx context.Context,
	endpoint string,
	body any,
	marshaler Marshaler,
	headers map[string]string,
	queryParam map[string][]string,
	pathParams ...string,
) (res *http.Response, err error)

type Configuration

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

Configuration is a collection of options that apply to the client.

type HttpClient

type HttpClient interface {
	Do(r *http.Request) (*http.Response, error)
}

HttpClient defines features of an internal http clients that is used to execute http requests.

type Marshaler

type Marshaler interface {
	Marshal(body any) (data []byte, content string, err error)
}

Marshaler defines how to convert an object into a byte array and its content type for making HTTP requests.

func NewFormMarshaler

func NewFormMarshaler() Marshaler

NewXMLMarshaler creates a marshaler for application/x-www-form-urlencoded content type.

func NewJSONMarshaler

func NewJSONMarshaler() Marshaler

NewJSONMarshaler creates a marshaler for application/json content type.

func NewXMLMarshaler

func NewXMLMarshaler() Marshaler

NewXMLMarshaler creates a marshaler for application/xml content type.

type MemPool

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

MemPool manages pooling memory allocations for reusing dyanmic memory.

func NewDefaultMemPool

func NewDefaultMemPool() *MemPool

NewDefaultMemPool creates a memory pool with default page and pool size.

func NewMemPool

func NewMemPool(
	pageSize int,
	poolSize int,
) *MemPool

NewMemPool creates a memory pool with a channel that provides byte arrays with the configured page size. The pool's channel has an upper limit of pool size.

func (*MemPool) Acquire

func (m *MemPool) Acquire() []byte

Acquire returns a byte array from the pool, or creates a new one if the pool is empty.

func (*MemPool) Release

func (c *MemPool) Release(mem ...[]byte)

Release resets and inserts byte arrays into the pool. If the pool's channel is full, the byte array is discarded.

type MemoryPool

type MemoryPool interface {
	Acquire() []byte
	Release(...[]byte)
}

MemoryPool defines a pool that can be used to acquire memory and release memory as byte arrays.

type Option

type Option interface {
	Configure(c *Configuration)
}

Option defines objects that can change a Configuration.

func UseHighLevelMiddleware

func UseHighLevelMiddleware(mdw func(context.Context, *Request)) Option

UseHighLevelMiddleware creates an option for adding a high level middleware that is executed before the endpoint url and request data are processed.

func UseHttpClient

func UseHttpClient(client HttpClient) Option

UseHttpClient creates an option for setting the internal http client.

func UseHttpClientConstructor

func UseHttpClientConstructor(constr func() HttpClient) Option

UseHttpClientConstructor creates an option for setting the constructor to create a new http client for each request.

func UseLowLevelMiddleware

func UseLowLevelMiddleware(mdw func(context.Context, *Request)) Option

UseLowLevelMiddleware creates an option for adding a low level middleware that is executed before the headers are added and the request is executed.

func UseMemoryPool

func UseMemoryPool(pool MemoryPool) Option

UseMemoryPool creates an option for setting the client's memory pool.

func UseRetrier

func UseRetrier(retr Retrier) Option

UseRetrier creates an option for adding a retrier that retries the request until it succeeds.

type Request

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

Request stores details about the request

func (*Request) AddHeader

func (r *Request) AddHeader(k, v string)

func (*Request) Error

func (r *Request) Error(err error)

Error inserts an error to the errors slice.

func (*Request) Errors

func (r *Request) Errors() []error

Errors retruns all the errors as a slice.

func (*Request) GetData

func (r *Request) GetData() []byte

func (*Request) GetEndpoint

func (r *Request) GetEndpoint() []byte

func (*Request) GetHeader

func (r *Request) GetHeader(k string) (v string, ok bool)

func (*Request) GetMethod

func (r *Request) GetMethod() string

func (*Request) GetQueryParam

func (r *Request) GetQueryParam(k string) (v []string, ok bool)

func (*Request) GetResponse

func (r *Request) GetResponse() *http.Response

func (*Request) Next

func (r *Request) Next()

Next executes the next function on the function middleware on the request. If there are no more functions to call, it does nothing.

func (*Request) RemoveHeader

func (r *Request) RemoveHeader(k string)

type Retrier

type Retrier interface {
	Run(context.Context, func(ctx context.Context) (error, bool)) error
	ShouldRetry(*http.Response, error) (error, bool)
}

Retrier defines a wrapper that can retry a request

Jump to

Keyboard shortcuts

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