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
- func ContextRetryAttempt(ctx context.Context) (int, bool)
- func DefaultTransport() http.RoundTripper
- func Dialer() *net.Dialer
- func HTTP2Transport() http.RoundTripper
- func StructToMap(in any, allowedFields []string) (out map[string]any)
- func ToFormBody(in map[string]any) (out map[string]string)
- type APIRequest
- type Client
- func (c Client) AndTrace(fn TraceFactory) Client
- func (c Client) Send(ctx context.Context, reqDef HTTPRequest) (res *http.Response, result any, err error)
- func (c Client) WithBaseURL(baseURLStr string) Client
- func (c Client) WithHeader(key, value string) Client
- func (c Client) WithHeaders(headers map[string]string) Client
- func (c Client) WithRetry(retry RetryConfig) Client
- func (c Client) WithTransport(transport http.RoundTripper) Client
- func (c Client) WithUserAgent(v string) Client
- type ContextKey
- type DurationSeconds
- type HTTPRequest
- type HTTPResponse
- type NoResult
- type ParallelAPIRequests
- type ReqDefinitionError
- type Result
- type RetryCondition
- type RetryConfig
- type RunGroup
- type Sendable
- type Sender
- type Trace
- type TraceFactory
- type WaitGroup
Constants ¶
const ( ContentTypeApplicationJSON = "application/json" ContentTypeApplicationJSONRegexp = `^application/([a-zA-Z0-9\.\-]+\+)?json$` )
const DialTimeout = 3 * time.Second
DialTimeout specifies the default maximum connection initialization time.
const KeepAlive = 10 * time.Second
KeepAlive specifies the default interval between keep-alive probes.
const MaxConnectionsPerHost = 32
MaxConnectionsPerHost specifies the default maximum number of open connections to a host.
const RequestTimeout = 30 * time.Second
RequestTimeout - default request timeout.
const ResponseHeaderTimeout = 20 * time.Second
ResponseHeaderTimeout specifies the default amount of time to wait for a server's response headers.
const RetriesCount = 5
RetriesCount - default retries count.
const RetryAttemptContextKey = ContextKey("retryAttempt")
const RetryWaitTimeMax = 3 * time.Second
RetryWaitTimeMax - default maximum retry interval.
const RetryWaitTimeStart = 100 * time.Millisecond
RetryWaitTimeStart - default retry interval.
const RunGroupConcurrencyLimit = 32
RunGroupConcurrencyLimit is the maximum number of concurrent requests in one RunGroup.
const TLSHandshakeTimeout = 5 * time.Second
TLSHandshakeTimeout specifies the default timeout of TLS handshake.
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 DefaultTransport ¶
func DefaultTransport() http.RoundTripper
DefaultTransport is the default Client transport with reasonable limits.
func StructToMap ¶
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.
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) error) APIRequest[R] // WithOnComplete method registers callback to be executed when the request is completed. WithOnComplete(func(ctx context.Context, 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, 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, err error) error) APIRequest[R] // Send sends the request by the sender. Send(ctx context.Context) (result R, err error) SendOrErr(ctx context.Context) 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 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 ¶
WithBaseURL returns a clone of the Client with base url set.
func (Client) WithHeader ¶
WithHeader returns a clone of the Client with common header set.
func (Client) WithHeaders ¶
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 ¶
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
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, 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, response HTTPResponse) error) HTTPRequest // WithOnError method registers callback to be executed when the request is completed and `code >= 400`. WithOnError(func(ctx context.Context, response HTTPResponse, err error) error) HTTPRequest // Send method sends defined request and returns response, mapped result and error. Send(ctx context.Context) (response HTTPResponse, result any, err error) SendOrErr(ctx context.Context) error // contains filtered or unexported methods }
HTTPRequest is an immutable HTTP request.
func NewHTTPRequest ¶
func NewHTTPRequest(sender Sender) 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 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.
type ReqDefinitionError ¶ added in v1.1.0
type ReqDefinitionError struct {
// contains filtered or unexported fields
}
ReqDefinitionError can be used as the Sendable interface. So the error will be returned when you try to send the request. This simplifies usage, the error is checked only once, in one place.
func (ReqDefinitionError) SendOrErr ¶ added in v1.1.0
func (v ReqDefinitionError) SendOrErr(_ context.Context) error
func (ReqDefinitionError) Unwrap ¶ added in v1.1.0
func (v ReqDefinitionError) Unwrap() error
type RetryCondition ¶
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 (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 ¶
NewRunGroup creates a new RunGroup.
func RunGroupWithLimit ¶
RunGroupWithLimit creates a new RunGroup with given concurrent requests limit.
func (*RunGroup) Add ¶
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 ¶
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 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 ¶
NewWaitGroup creates new WaitGroup.
func NewWaitGroupWithLimit ¶
NewWaitGroupWithLimit creates new WaitGroup with given concurrent requests limit.