client

package
v0.18.3 Latest Latest
Warning

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

Go to latest
Published: Dec 19, 2022 License: MIT Imports: 31 Imported by: 0

Documentation

Overview

Package client provides support for defining an HTTP client for an API.

Use HTTPRequest interface to define immutable HTTP requests, see NewHTTPRequest function. Requests are sent using the Sender interface.

Client is a default implementation of the Sender interface. Client is based on the standard net/http package and contains retry and tracing/telemetry support. It is easy to implement your custom HTTP client, by implementing Sender interface.

APIRequest[R Result] is a generic type that contains target data type to which the API response will be mapped. Use NewAPIRequest function to create a APIRequest from a HTTPRequest.

RunGroup and WaitGroup are helpers for concurrent requests.

Index

Constants

View Source
const (
	ContentTypeApplicationJson       = "application/json"
	ContentTypeApplicationJsonRegexp = `^application/([a-zA-Z0-9\.\-]+\+)?json$`
)
View Source
const DialTimeout = 3 * time.Second

DialTimeout specifies the default maximum connection initialization time.

View Source
const KeepAlive = 10 * time.Second

KeepAlive specifies the default interval between keep-alive probes.

View Source
const MaxConnectionsPerHost = 32

MaxConnectionsPerHost specifies the default maximum number of open connections to a host.

View Source
const RequestTimeout = 30 * time.Second

RequestTimeout - default request timeout.

View Source
const ResponseHeaderTimeout = 20 * time.Second

ResponseHeaderTimeout specifies the default amount of time to wait for a server's response headers.

View Source
const RetriesCount = 5

RetriesCount - default retries count.

View Source
const RetryAttemptContextKey = ContextKey("retryAttempt")
View Source
const RetryWaitTimeMax = 3 * time.Second

RetryWaitTimeMax - default maximum retry interval.

View Source
const RetryWaitTimeStart = 100 * time.Millisecond

RetryWaitTimeStart - default retry interval.

View Source
const RunGroupConcurrencyLimit = 32

RunGroupConcurrencyLimit is the maximum number of concurrent requests in one RunGroup.

View Source
const TLSHandshakeTimeout = 5 * time.Second

TLSHandshakeTimeout specifies the default timeout of TLS handshake.

View Source
const WaitGroupConcurrencyLimit = 8

WaitGroupConcurrencyLimit is the maximum number of concurrent requests in one WaitGroup.

Variables

This section is empty.

Functions

func ContextRetryAttempt added in v0.15.0

func ContextRetryAttempt(ctx context.Context) (int, bool)

func DefaultTransport

func DefaultTransport() http.RoundTripper

DefaultTransport is the default Client transport with reasonable limits.

func Dialer

func Dialer() *net.Dialer

Dialer is the default dialer.

func HTTP2Transport

func HTTP2Transport() http.RoundTripper

HTTP2Transport forces HTTP2 protocol.

func StructToMap

func StructToMap(in any, allowedFields []string) (out map[string]any)

StructToMap converts a struct to values map. Only defined allowedFields are converted. If allowedFields = nil, then all fields are exported.

Field name is read from `writeas` tag or from "json" tag as fallback. Field with tag `readonly:"true"` is ignored. Field with tag `writeoptional` is exported only if value is not empty.

func ToFormBody

func ToFormBody(in map[string]any) (out map[string]string)

ToFormBody converts a JSON like map to form body map, any type is mapped to string.

Types

type APIRequest

type APIRequest[R Result] interface {
	// WithBefore method registers callback to be executed before the request.
	// If an error is returned, the request is not sent.
	WithBefore(func(ctx context.Context, sender Sender) error) APIRequest[R]
	// WithOnComplete method registers callback to be executed when the request is completed.
	WithOnComplete(func(ctx context.Context, sender Sender, result R, err error) error) APIRequest[R]
	// WithOnSuccess method registers callback to be executed when the request is completed and `code >= 200 and <= 299`.
	WithOnSuccess(func(ctx context.Context, sender Sender, result R) error) APIRequest[R]
	// WithOnError method registers callback to be executed when the request is completed and `code >= 400`.
	WithOnError(func(ctx context.Context, sender Sender, err error) error) APIRequest[R]
	// Send sends the request by the sender.
	Send(ctx context.Context, sender Sender) (result R, err error)
	SendOrErr(ctx context.Context, sender Sender) error
}

APIRequest with response mapped to the generic type R.

func NewAPIRequest

func NewAPIRequest[R Result](result R, requests ...Sendable) APIRequest[R]

NewAPIRequest creates an API request with the result mapped to the R type. It is composed of one or multiple Sendable (HTTPRequest or APIRequest).

func NewNoOperationAPIRequest

func NewNoOperationAPIRequest[R Result](result R) APIRequest[R]

NewNoOperationAPIRequest returns an APIRequest that immediately returns a Result without calling any HTTPRequest. It is handy in situations where there is no work to be done.

type Client

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

Client is a default and configurable implementation of the Sender interface by Go native http.Client. It supports retry and tracing/telemetry.

func New

func New() Client

New creates new HTTP Client.

func NewMockedClient

func NewMockedClient() (Client, *httpmock.MockTransport)

NewMockedClient creates the Client with mocked HTTP transport.

func NewTestClient

func NewTestClient() Client

NewTestClient creates the Client for tests.

If the TEST_HTTP_CLIENT_VERBOSE environment variable is set to "true", then all HTTP requests and responses are dumped to stdout.

Output may contain unmasked tokens, do not use it in production!

func (Client) AndTrace

func (c Client) AndTrace(fn TraceFactory) Client

AndTrace returns a clone of the Client with Trace hooks added. The last registered hook is executed first.

func (Client) Send

func (c Client) Send(ctx context.Context, reqDef HTTPRequest) (res *http.Response, result any, err error)

Send method sends HTTP request and returns HTTP response, it implements the Sender interface.

func (Client) WithBaseURL

func (c Client) WithBaseURL(baseURLStr string) Client

WithBaseURL returns a clone of the Client with base url set.

func (Client) WithHeader

func (c Client) WithHeader(key, value string) Client

WithHeader returns a clone of the Client with common header set.

func (Client) WithHeaders

func (c Client) WithHeaders(headers map[string]string) Client

WithHeaders returns a clone of the Client with common headers set.

func (Client) WithRetry

func (c Client) WithRetry(retry RetryConfig) Client

WithRetry returns a clone of the Client with retry config set.

func (Client) WithTransport

func (c Client) WithTransport(transport http.RoundTripper) Client

WithTransport returns a clone of the Client with a HTTP transport set.

func (Client) WithUserAgent

func (c Client) WithUserAgent(v string) Client

WithUserAgent returns a clone of the Client with user agent set.

type ContextKey added in v0.15.0

type ContextKey string

type DurationSeconds added in v0.13.0

type DurationSeconds time.Duration

DurationSeconds is time.Duration encoded/decoded as number of seconds.

func (DurationSeconds) MarshalJSON added in v0.13.0

func (d DurationSeconds) MarshalJSON() ([]byte, error)

MarshalJSON implements JSON encoding.

func (DurationSeconds) String added in v0.13.0

func (d DurationSeconds) String() string

func (*DurationSeconds) UnmarshalJSON added in v0.13.0

func (d *DurationSeconds) UnmarshalJSON(data []byte) (err error)

UnmarshalJSON implements JSON decoding.

type HTTPRequest

type HTTPRequest interface {

	// WithGet is shortcut for WithMethod(http.MethodGet).WithURL(url)
	WithGet(url string) HTTPRequest
	// WithPost is shortcut for WithMethod(http.MethodPost).WithURL(url)
	WithPost(url string) HTTPRequest
	// WithPut is shortcut for WithMethod(http.MethodPut).WithURL(url)
	WithPut(url string) HTTPRequest
	// WithDelete is shortcut for WithMethod(http.MethodDelete).WithURL(url)
	WithDelete(url string) HTTPRequest
	// WithMethod method sets the HTTP method.
	WithMethod(method string) HTTPRequest
	// WithBaseURL method sets the base URL.
	WithBaseURL(baseURL string) HTTPRequest
	// WithURL method sets the URL.
	WithURL(url string) HTTPRequest
	// AndHeader method sets a single header field and its value.
	AndHeader(header string, value string) HTTPRequest
	// AndQueryParam method sets single parameter and its value.
	AndQueryParam(param, value string) HTTPRequest
	// WithQueryParams method sets multiple parameters and its values.
	WithQueryParams(params map[string]string) HTTPRequest
	// AndPathParam method sets single URL path key-value pair.
	AndPathParam(param, value string) HTTPRequest
	// WithPathParams method sets multiple URL path key-value pairs.
	WithPathParams(params map[string]string) HTTPRequest
	// WithFormBody method sets Form parameters and Content-Type header to "application/x-www-form-urlencoded".
	WithFormBody(form map[string]string) HTTPRequest
	// WithJSONBody method sets request body to the JSON value and Content-Type header to "application/json".
	WithJSONBody(body any) HTTPRequest
	// WithBody method sets request body.
	WithBody(body any) HTTPRequest
	// WithContentType method sets custom content type.
	WithContentType(contentType string) HTTPRequest
	// WithError method registers the request `Error` value for automatic mapping.
	WithError(err error) HTTPRequest
	// WithResult method registers the request `Result` value for automatic mapping.
	WithResult(result any) HTTPRequest
	// WithOnComplete method registers callback to be executed when the request is completed.
	WithOnComplete(func(ctx context.Context, sender Sender, response HTTPResponse, err error) error) HTTPRequest
	// WithOnSuccess method registers callback to be executed when the request is completed and `code >= 200 and <= 299`.
	WithOnSuccess(func(ctx context.Context, sender Sender, response HTTPResponse) error) HTTPRequest
	// WithOnError method registers callback to be executed when the request is completed and `code >= 400`.
	WithOnError(func(ctx context.Context, sender Sender, response HTTPResponse, err error) error) HTTPRequest
	// Send method sends defined request and returns response, mapped result and error.
	Send(ctx context.Context, sender Sender) (response HTTPResponse, result any, err error)
	SendOrErr(ctx context.Context, sender Sender) error
	// contains filtered or unexported methods
}

HTTPRequest is an immutable HTTP request.

func NewHTTPRequest

func NewHTTPRequest() HTTPRequest

NewHTTPRequest creates immutable HTTP request.

type HTTPResponse

type HTTPResponse interface {

	// Result method returns the response mapped as a data type, if any.
	Result() any
	// contains filtered or unexported methods
}

HTTPResponse with response mapped to the Result() value.

type NoResult

type NoResult struct{}

NoResult type.

type ParallelAPIRequests added in v0.18.0

type ParallelAPIRequests []Sendable

func Parallel added in v0.18.0

func Parallel(requests ...Sendable) ParallelAPIRequests

Parallel wraps parallel requests to one Sendable interface.

func (ParallelAPIRequests) SendOrErr added in v0.18.0

func (v ParallelAPIRequests) SendOrErr(ctx context.Context, sender Sender) error

type Result

type Result = any

Result - any value.

type RetryCondition

type RetryCondition func(*http.Response, error) bool

RetryCondition defines which responses should retry.

func DefaultRetryCondition

func DefaultRetryCondition() RetryCondition

DefaultRetryCondition retries on common network and HTTP errors.

type RetryConfig

type RetryConfig struct {
	Condition           RetryCondition
	Count               int
	TotalRequestTimeout time.Duration
	WaitTimeStart       time.Duration
	WaitTimeMax         time.Duration
}

RetryConfig configures Client retries.

func DefaultRetry

func DefaultRetry() RetryConfig

DefaultRetry returns a default RetryConfig.

func TestingRetry

func TestingRetry() RetryConfig

TestingRetry - fast retry for use in tests.

func (RetryConfig) NewBackoff

func (c RetryConfig) NewBackoff() backoff.BackOff

NewBackoff returns an exponential backoff for HTTP retries.

type RunGroup

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

RunGroup allows scheduling requests by Add method and then send them concurrently by the RunAndWait method.

The sending will stop when the first error occurs. The first error will be returned from the RunAndWait method.

If you need to send requests immediately, or if you want to wait and collect all errors, use client.WaitGroup instead.

func NewRunGroup

func NewRunGroup(ctx context.Context, sender Sender) *RunGroup

NewRunGroup creates a new RunGroup.

func RunGroupWithLimit

func RunGroupWithLimit(ctx context.Context, sender Sender, limit int64) *RunGroup

RunGroupWithLimit creates a new RunGroup with given concurrent requests limit.

func (*RunGroup) Add

func (g *RunGroup) Add(request Sendable)

Add request for sending. The request will be sent on call of the RunAndWait method. Additional requests can be added using the Add method (for example from a request callback), even if RunAndWait has already been called, but is not yet finished.

func (*RunGroup) RunAndWait

func (g *RunGroup) RunAndWait() error

RunAndWait starts sending requests and waits for the result. After the first error sending stops and the error is returned.

Additional requests can be added using the Add method (for example from a request callback), even if RunAndWait has already been called, but is not yet finished.

type Sendable

type Sendable interface {
	SendOrErr(ctx context.Context, sender Sender) error
}

Sendable is HTTPRequest or APIRequest.

type Sender

type Sender interface {
	// Send method sends defined request and returns response.
	// Type of the return value "result" must be the same as type of the HTTPRequest.ResultDef(), otherwise panic will occur.
	//   In Go, this rule cannot be written using generic types yet, methods cannot have generic types.
	//   Send[R Result](ctx context.Context, request HTTPRequest[R]) (rawResponse *http.Response, result R, error error)
	Send(ctx context.Context, request HTTPRequest) (rawResponse *http.Response, result any, err error)
}

Sender represents an HTTP client, the Client is a default implementation using the standard net/http package.

type Trace

type Trace struct {
	httptrace.ClientTrace // native, low level trace
	// GotRequest is called when Client.Send method is called.
	GotRequest func(ctx context.Context, request HTTPRequest) context.Context
	// RequestProcessed is called when Client.Send method is done.
	RequestProcessed func(result any, err error)
	// HTTPRequestStart is called when the request begins. It includes redirects and retries.
	HTTPRequestStart func(request *http.Request)
	// HTTPRequestStart is called when the request completes. It includes redirects and retries.
	HTTPRequestDone func(response *http.Response, err error)
	// HttpRequestRetry is called before retry delay.
	HTTPRequestRetry func(attempt int, delay time.Duration)
}

Trace is a set of hooks to run at various stages of an outgoing HTTPRequest.

type TraceFactory

type TraceFactory func() *Trace

TraceFactory creates Trace hooks for a request.

func DumpTracer

func DumpTracer(wr io.Writer) TraceFactory

DumpTracer dumps HTTP request and response to a writer. Output may contain unmasked tokens, do not use it in production!

func LogTracer

func LogTracer(wr io.Writer) TraceFactory

type WaitGroup

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

WaitGroup allows sending requests concurrently using Send method and wait until all requests are completed using the Wait method.

The request starts immediately after calling the Send method. If an error occurs, sending will not stop, all requests will be sent. Wait method at the end returns all errors that have occurred, if any.

If you need to schedule requests and send them later, or if you want to stop at the first error, use client.RunGroup instead.

func NewWaitGroup

func NewWaitGroup(ctx context.Context, sender Sender) *WaitGroup

NewWaitGroup creates new WaitGroup.

func NewWaitGroupWithLimit

func NewWaitGroupWithLimit(ctx context.Context, sender Sender, limit int64) *WaitGroup

NewWaitGroupWithLimit creates new WaitGroup with given concurrent requests limit.

func (*WaitGroup) Send

func (g *WaitGroup) Send(request Sendable)

Send a concurrent request.

func (*WaitGroup) Wait

func (g *WaitGroup) Wait() error

Wait for all requests to complete. All errors that have occurred will be returned.

Jump to

Keyboard shortcuts

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