transport

package module
v1.6.7 Latest Latest
Warning

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

Go to latest
Published: Jan 25, 2022 License: Apache-2.0 Imports: 14 Imported by: 9

README

transport

GoDoc Build Status codecov.io

An extendable toolkit for improving the standard library HTTP client.

-- transport

Usage

Creating A Transport

The standard library http.Transport implementation is largely sufficient for most uses of http.Client. However, the http.DefaultTransport used by the client is not configured for production use. Several of the timeout values, TLS handshake for example, are set in the seconds. Likewise, the dial methods used to establish TCP connections are allowed upwards of thirty seconds before they fail. Recreating the http.DefaultTransport settings before overwriting the value necessary for a production environment can be tedious. To help, this package offers an alternative constructor for http.Transport that leverages functional arguments to make it easier to configure. For example:

var client = &http.Client{
  Transport: transport.New(
    transport.OptionMaxResponseHeaderBytes(4096),
    transport.OptionDisableCompression(true),
  ),
}

Additionally, the same options may be used to create a factory function which is able to produce any number of transports with the same configuration:

var factory = transport.NewFactory(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var client1 = &http.Client{
  Transport: factory(),
}
var client2 = &http.Client{
  Transport: factory(),
}
Decorators

In addition to providing the transport constructor, this package provides a handful of tools that make operating the http.Transport a little easier for complex use cases. Each of these additions comes in the form of a wrapper around the transport in a way that is seamless to the http.Client and any code that uses the http.Client.

Retry

One of the most common needs for network based code is to retry on intermittent, or transient, errors. To help with this use case, this package provides a retry decorator that can be configured to retry on a number of conditions within a number of limits without adding more complexity to code using the http.Client.

var retryDecorator = transport.NewRetrier(
  transport.NewPercentJitteredBackoffPolicy(
    transport.NewFixedBackoffPolicy(50*time.Millisecond),
    .2, // Jitter within 20% of the delay.
  ),
  transport.NewLimitedRetryPolicy(
    3, // Only make up to 3 retry attempts
    transport.NewStatusCodeRetryPolicy(http.StatusInternalServerError),
    transport.NewTimeoutRetryPolicy(100*time.Millisecond),
  ),
)
var t = transport.New(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var client = &http.Client{
  Transport: retryDecorator(t),
}

The above snippet adds retry logic that:

  • Makes up to 3 additional attempts to get a valid response.
  • Adds a jittered delay between each retry of 40ms to 60ms.
  • Retries automatically if the response code is 500.
  • Cancels an active request and retries if it takes longer than 100ms.
Hedging

The hedging decorator fans out a new request at each time interval defined by the backoff policy, and returns the first response received. For latency-based retries, this will often be a better approach than a "stop-and-retry" policy (such as the Timeout Retry Policy). The hedging decorator allows for a worst case request to take up to a maximum configurable timeout, while pessimistically creating new requests before the timeout is reached.

var hedgingDecorator = transport.NewHedger(
	transport.NewFixedBackoffPolicy(50*time.Millisecond),
)
var t = transport.New(
	transport.OptionMaxResponseHeaderBytes(4096),
	transport.OptionDisableCompression(true),
)
var client = &http.Client{
	Transport: hedgingDecorator(t),
	Timeout:   500 * time.Millisecond,
}

The above snippet adds hedging logic that:

  • Fans out a new request if no response is received in 50ms.
  • Fans out a maximum of 10 parallel requests before all in-flight requests are cancelled.
Headers

Another common need is to inject headers automatically into outgoing requests so that application code doesn't have to be aware of elements like authentication or tracing. For these cases, this package provides a header injection decorator:

var headerDecorator = transport.NewHeader(
  func(*http.Request) (string, string) {
    return "Bearer", os.Getenv("SECURE_TOKEN")
  }
)
var t = transport.New(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var client = &http.Client{
  Transport: headerDecorator(t),
}

The above snippet configures the transport to automatically inject an auth token into the headers on each request. The constructor takes any function matching the signature shown above to allow for any level of complexity in selecting the header name and value.

<a id="markdown-accesslog" name"accesslog">

AccessLog

A cornerstone of operational maturity is visibility between dependencies across the network. This is typically achieved with a combination of robust logs and metrics. One aspect of this is access logs for every request a service makes as a client to another.

The access log transport decorator provides such a mechanism. By applying the snippet below, each request will emit a logline with key fields such as:

  • status
  • uri_path
  • http_method
  • port
  • site
  • duration

And several others.

var t = transport.New(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var client = &http.Client{
  Transport: transport.NewAccessLog()(t),
}

For critical metrics related to HTTP client traffic to other services, see the stating analog to this http.Transport decorator in httpstats.

Decorator Chains

Most use cases require more than one decorator. To help, this package provides a decorator chain implementation that can be used to collect a series of decorator behaviors and have them applied in a specific order to any given transport:

var retryDecorator = transport.NewRetrier(
  transport.RetrierOptionResponseCode(http.StatusInternalServerError),
  transport.RetrierOptionTimeout(100*time.Millisecond),
  transport.RetrierOptionLimit(3),
  transport.RetrierOptionDelay(50*time.Millisecond),
  transport.RetrierOptionDelayJitter(30*time.Millisecond),
)
var headerDecorator = transport.NewHeader(
  func(*http.Request) (string, string) {
    return "Bearer", os.Getenv("SECURE_TOKEN")
  }
)
var chain = transport.Chain{
  retryDecorator
  headerDecorator,
}
var t = transport.New(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var client = &http.Client{
  Transport: chain.Apply(t),
}

The decorators will be applied in the reverse order they are given. Another way to think of this is that the request will pass through the decorators in the same order they are given. For example, a chain containing middleware A, B, C, and D will be applied like:

A(B(C(D(TRANSPORT))))
Transport Extensions

Decorators are a powerful pattern and a great deal of complexity can be isolated by using them. However, there are still some aspects of the core http.Transport behavior that can be harmful in production if not altered. This package provides some modifications of the standard behavior to account for these cases.

Recycle Transport

The default settings of the http.Transport include enabling the connection pool. Having a connection pool can be a highly effective optimization by allowing the cost of performing DNS lookups, acquiring a TCP connection, and performing TLS handshakes to be amortized over a potentially large number of outgoing requests.

One of the major deficiencies of the built-in connection pool is that there are no limits on connection lifetime. Granted, there are limits on connection idle time but these limits only apply when a connection goes unused. A higher scale service may see that connections never go idle. If a service is using DNS in order to connect to an endpoint then it can miss a change in the DNS records because it does not generate new connections frequently enough. To help with this issue, the package provides a transport modifier that can reset the entire connection pool on certain triggers.

var retryDecorator = transport.NewRetrier(
  transport.RetrierOptionResponseCode(http.StatusInternalServerError),
  transport.RetrierOptionTimeout(100*time.Millisecond),
  transport.RetrierOptionLimit(3),
  transport.RetrierOptionDelay(50*time.Millisecond),
  transport.RetrierOptionDelayJitter(30*time.Millisecond),
)
var headerDecorator = transport.NewHeader(
  func(*http.Request) (string, string) {
    return "Bearer", os.Getenv("SECURE_TOKEN")
  }
)
var chain = transport.Chain{
  retryDecorator
  headerDecorator,
}
var factory = transport.NewFactory(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var finalTransport = transport.NewRecycler(
  chain.ApplyFactory(factory),
  transport.RecycleOptionTTL(5*time.Minute),
  transport.RecycleOptionTTLJitter(1*time.Minute),
)
var client = &http.Client{Transport: finalTransport}

Building on the decorator examples, in this snippet we construct a new transport factory that is bound to a set of decorators that add functionality. Then we wrap the factory in a recycler that is configured to refresh the connection pool every five minutes with a randomized jitter within +/- one minute.

Note: There is currently no reliable way by which per-connection lifetime limits can be added. We are limited to managing the entire pool.

Rotating Transport

The internal connection management strategies of the standard library HTTP/1 and HTTP/2 transports are quite different. The HTTP/1 transport must use a single connection per-request. If it is attempting to make a new request and there are no idle connections in the pool then it will make a new connection for that request. The HTTP/2 transport, however, re-uses a single TCP connection for all requests.

When communicating with an HTTP server that supports HTTP/2 the http.Transport automatically creates an HTTP/2 transport internally and re-routes all requests through it. Oftentimes, this is a great optimization that we get for free. However, there are some edge cases around using a single connection for all outgoing requests. One of the larger edge cases is related to increased latency when experiencing packet loss. Several folks have written about this problem if you're looking for more details.

As a tool for managing the impact of this particular problem, this package provides a transport modifier that is capable of creating and maintaining multiple connection pools for a single destination to ensure that requests are spread evenly over multiple TCP connection even when in HTTP/2 mode:

var retryDecorator = transport.NewRetrier(
  transport.RetrierOptionResponseCode(http.StatusInternalServerError),
  transport.RetrierOptionTimeout(100*time.Millisecond),
  transport.RetrierOptionLimit(3),
  transport.RetrierOptionDelay(50*time.Millisecond),
  transport.RetrierOptionDelayJitter(30*time.Millisecond),
)
var headerDecorator = transport.NewHeader(
  func(*http.Request) (string, string) {
    return "Bearer", os.Getenv("SECURE_TOKEN")
  }
)
var chain = transport.Chain{
  retryDecorator
  headerDecorator,
}
var factory = transport.NewFactory(
  transport.OptionMaxResponseHeaderBytes(4096),
  transport.OptionDisableCompression(true),
)
var recycleFactory = transport.NewRecyclerFactory(
  chain.ApplyFactory(factory),
  transport.RecycleOptionTTL(5*time.Minute),
  transport.RecycleOptionTTLJitter(1*time.Minute),
)
var finalTransport = transport.NewRotator(
  recycleFactory,
  transport.RotatorOptionInstances(5),
)
var client = &http.Client{Transport: finalTransport}

The above is meant to illustrate two things. The first is the configuration of a rotator modification that ensures there are always at least five TCP connections in use for each HTTP/2 endpoint rather than one. The other is how the tools of this package can be composed with each other. The example above configures each of the five connection pools to recycle every four to five minutes just like the previous example that focused on the recycler.

Underneath, this option will cause the service to actually create five, individual transports using whichever factory function is given to it. The requests made through the client will be spread across the transports using a round-robin policy.

It is important to note that using this option for HTTP/1 connections may make the connection pooling worse because the connection management is so different. It is only recommended to use this option with HTTP/2 connections.

Contributing

License

This project is licensed under Apache 2.0. See LICENSE.txt for details.

Contributing Agreement

Atlassian requires signing a contributor's agreement before we can accept a patch. If you are an individual you can fill out the individual CLA. If you are contributing on behalf of your company then please fill out the corporate CLA.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ErrorToStatusCode added in v1.5.0

func ErrorToStatusCode(err error) int

ErrorToStatusCode attempts to translate an HTTP request error to a meaningful HTTP status code.

There can be many reasons why we couldn't get a proper response from the upstream server. This includes timeouts, inability to connect, or the client canceling a request. If the error appears to indicate a timeout occurred, then return 504 Gateway Timeout, otherwise, return 502 Bad Gateway.

func New

func New(opts ...Option) *http.Transport

New applies the given options to a Transport and returns it.

func NewAccessLog added in v1.5.0

func NewAccessLog() func(http.RoundTripper) http.RoundTripper

NewAccessLog configures a RoundTripper decorator that generates log details for each request.

func NewHeader

func NewHeader(requestProvider HeaderProvider) func(http.RoundTripper) http.RoundTripper

NewHeader wraps a transport in order to include custom request headers.

func NewHeaders added in v1.3.0

func NewHeaders(requestProvider HeaderProvider, responseProvider ResponseHeaderProvider) func(http.RoundTripper) http.RoundTripper

NewHeaders wraps a transport in order to include custom request and response headers.

func NewHedger

func NewHedger(backoffPolicy BackoffPolicy) func(http.RoundTripper) http.RoundTripper

NewHedger configures a RoundTripper decorator to perform some number of hedged requests.

func NewRetrier

func NewRetrier(backoffPolicy BackoffPolicy, retryPolicies ...RetryPolicy) func(http.RoundTripper) http.RoundTripper

NewRetrier configures a RoundTripper decorator to perform some number of retries.

func NewRetryAfter added in v1.4.0

func NewRetryAfter() func(http.RoundTripper) http.RoundTripper

NewRetryAfter configures a RoundTripper decorator to honor a status code 429 response, using the Retry-After header directive when present, or the backoffPolicy if not present.

func OptionDefaultTransport deprecated

func OptionDefaultTransport(t *http.Transport) *http.Transport

OptionDefaultTransport configures a transport to match the http.DefaultTransport.

Deprecated: The New() method uses a copy of the http.DefaultTransport as the base transport on which options are applied. This option is redundant and can be removed wherever it is used.

Types

type BackoffPolicy

type BackoffPolicy func() Backoffer

BackoffPolicy is a factory that generates a Backoffer.

func NewExponentialBackoffPolicy added in v1.6.0

func NewExponentialBackoffPolicy(wait time.Duration) BackoffPolicy

NewExponentialBackoffPolicy generates a BackoffPolicy that returns double the value returned in the previous call, using the wait parameter as the initial backoff value

func NewFixedBackoffPolicy

func NewFixedBackoffPolicy(wait time.Duration) BackoffPolicy

NewFixedBackoffPolicy generates a BackoffPolicy that always returns the same value.

func NewPercentJitteredBackoffPolicy

func NewPercentJitteredBackoffPolicy(wrapped BackoffPolicy, jitterPercent float64) BackoffPolicy

NewPercentJitteredBackoffPolicy wraps any backoff policy and applies a percentage based jitter to the original policy's value. The percentage float should be between 0 and 1. The jitter will be applied as a positive and negative value equally.

type Backoffer

type Backoffer interface {
	Backoff(*http.Request, *http.Response, error) time.Duration
}

Backoffer determines how much time to wait in between automated retires.

type Chain

type Chain []Decorator

Chain is an ordered collection of Decorators.

func (Chain) Apply

func (c Chain) Apply(base http.RoundTripper) http.RoundTripper

Apply wraps the given RoundTripper with the Decorator chain.

func (Chain) ApplyFactory

func (c Chain) ApplyFactory(base Factory) Factory

ApplyFactory wraps the given Factory such that all new instances produced will be decorated with the contents of the chain.

type Decorator

type Decorator func(http.RoundTripper) http.RoundTripper

Decorator is a named type for any function that takes a RoundTripper and returns a RoundTripper.

type ExponentialBackoffer added in v1.6.0

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

ExponentialBackoffer signals the client to wait for an initial amount of time, doubling every retry

func (*ExponentialBackoffer) Backoff added in v1.6.0

Backoff for an initial amount of time, doubling each retry

type Factory

type Factory func() http.RoundTripper

Factory is any function that takes no arguments and returns a Transport.

func NewFactory

func NewFactory(opts ...Option) Factory

NewFactory returns a Factory that is bound to the given Option set.

func NewRecyclerFactory

func NewRecyclerFactory(factory Factory, opts ...RecycleOption) Factory

NewRecyclerFactory is a counterpart for NewRecycler that generates a Factory function for use with other decorators.

func NewRotatorFactory

func NewRotatorFactory(factory Factory, opts ...RotatorOption) Factory

NewRotatorFactory is a counterpart for NewRotator that generates a Factory function for use with other decorators.

type FixedBackoffer

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

FixedBackoffer signals the client to wait for a static amount of time.

func (*FixedBackoffer) Backoff

Backoff for a static amount of time.

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

Header is a decorator that injects a header value into every request.

func (*Header) RoundTrip

func (c *Header) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip annotates the outgoing request and calls the wrapped Client.

type HeaderProvider

type HeaderProvider func(*http.Request) (headerName string, headerValue string)

HeaderProvider is mapping function that generates the required header name and value from an outgoing request.

type Hedger

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

Hedger is a wrapper that fans out a new request at each time interval defined by the backoff policy, and returns the first response received. For latency-based retries, this will often be a better approach than a "stop-and-retry" policy (such as the TimeoutRetrier). The hedging decorator allows for a worst case request to take up to a maximum configurable timeout, while pessimistically creating new requests before the timeout is reached.

func (*Hedger) RoundTrip

func (c *Hedger) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip executes a new request at each time interval defined by the backoff policy, and returns the first response received.

type LimitedRetrier

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

LimitedRetrier wraps a series of retry policies in a hard upper limit.

func (*LimitedRetrier) Request

func (r *LimitedRetrier) Request(req *http.Request) *http.Request

Request implements Requester by calling the wrapped Request methods where needed.

func (*LimitedRetrier) Retry

func (r *LimitedRetrier) Retry(req *http.Request, resp *http.Response, e error) bool

Retry the request based on the wrapped policies until the limit is reached. Once the limit is reached then this method always returns false.

type Option

type Option func(*http.Transport) *http.Transport

Option is a function that either modifies or generates a new Transport.

func OptionDial

func OptionDial(dial func(network, addr string) (net.Conn, error)) Option

OptionDial installs a custom Dial configuration in the Transport.

func OptionDialContext

func OptionDialContext(dialCtx func(ctx context.Context, network, addr string) (net.Conn, error)) Option

OptionDialContext installs a custom DialContext configuration in the Transport.

func OptionDialTLS

func OptionDialTLS(dial func(network, addr string) (net.Conn, error)) Option

OptionDialTLS installs a custom DialTLS configuration in the Transport.

func OptionDisableCompression

func OptionDisableCompression(disabled bool) Option

OptionDisableCompression installs a custom DisableCompression option in the Transport.

func OptionDisableKeepAlives

func OptionDisableKeepAlives(disabled bool) Option

OptionDisableKeepAlives installs a custom DisableKeepAlives option in the Transport.

func OptionExpectContinueTimeout

func OptionExpectContinueTimeout(timeout time.Duration) Option

OptionExpectContinueTimeout installs a custom ExpectContinueTimeout option in the Transport.

func OptionIdleConnTimeout

func OptionIdleConnTimeout(timeout time.Duration) Option

OptionIdleConnTimeout installs a custom IdleConnTimeout option in the Transport.

func OptionMaxIdleConns

func OptionMaxIdleConns(max int) Option

OptionMaxIdleConns installs a custom MaxIdleConns option in the Transport.

func OptionMaxIdleConnsPerHost

func OptionMaxIdleConnsPerHost(max int) Option

OptionMaxIdleConnsPerHost installs a custom MaxIdleConnsPerHost option in the Transport.

func OptionMaxResponseHeaderBytes

func OptionMaxResponseHeaderBytes(max int64) Option

OptionMaxResponseHeaderBytes installs a custom MaxResponseHeaderBytes option in the Transport.

func OptionProxy

func OptionProxy(proxy func(*http.Request) (*url.URL, error)) Option

OptionProxy installs a custom Proxy configuration in the Transport.

func OptionProxyConnectHeader

func OptionProxyConnectHeader(header http.Header) Option

OptionProxyConnectHeader installs a custom ProxyConnectHeader option in the Transport.

func OptionResponseHeaderTimeout

func OptionResponseHeaderTimeout(timeout time.Duration) Option

OptionResponseHeaderTimeout installs a custom ResponseHeaderTimeout option in the Transport.

func OptionTLSClientConfig

func OptionTLSClientConfig(config *tls.Config) Option

OptionTLSClientConfig installs a custom TLSClientConfig in the Transport.

func OptionTLSHandshakeTimeout

func OptionTLSHandshakeTimeout(timeout time.Duration) Option

OptionTLSHandshakeTimeout installs a custom TLSHandshakeTimeout in the Transport.

func OptionTLSNextProto

func OptionTLSNextProto(next map[string]func(authority string, c *tls.Conn) http.RoundTripper) Option

OptionTLSNextProto installs a custom TLSNextProto option in the Transport.

type PercentJitteredBackoffer

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

PercentJitteredBackoffer adjusts the backoff time by a random amount within N percent of the duration to help with thundering herds.

func (*PercentJitteredBackoffer) Backoff

func (b *PercentJitteredBackoffer) Backoff(r *http.Request, response *http.Response, e error) time.Duration

Backoff for a jittered amount.

type RecycleOption

type RecycleOption func(*Recycler) *Recycler

RecycleOption is a configuration for the Recycler decorator

func RecycleOptionChannel

func RecycleOptionChannel(signal chan struct{}) RecycleOption

RecycleOptionChannel configures the recycler to rotate based on input from a channel.

func RecycleOptionMaxUsage

func RecycleOptionMaxUsage(max int) RecycleOption

RecycleOptionMaxUsage configures the recycler to rotate Transports after a number of uses.

func RecycleOptionTTL

func RecycleOptionTTL(ttl time.Duration) RecycleOption

RecycleOptionTTL configures the recycler to rotate Transports on an interval.

func RecycleOptionTTLJitter

func RecycleOptionTTLJitter(jitter time.Duration) RecycleOption

RecycleOptionTTLJitter adds a randomized jitter to the TTL that is plus or minus the duration value given.

type Recycler

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

Recycler is a decorator that discards and regenerates the transport after a given set of triggers.

func NewRecycler

func NewRecycler(factory Factory, opts ...RecycleOption) *Recycler

NewRecycler uses the given factory as a source and recycles the transport based on the options given.

func (*Recycler) RoundTrip

func (c *Recycler) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip applies the discard and regenerate policy.

type Requester

type Requester interface {
	Request(*http.Request) *http.Request
}

Requester can be implemented if the Retrier needs to manipulate the request or request context before it is executed.

type ResponseHeaderProvider added in v1.3.0

type ResponseHeaderProvider func(*http.Response) (headerName string, headerValue string)

ResponseHeaderProvider is mapping function that generates the required header name and value to an outgoing response.

type Retrier

type Retrier interface {
	Retry(*http.Request, *http.Response, error) bool
}

Retrier determines whether or not the transport will automatically retry a request.

type Retry

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

Retry is a wrapper for applying various retry policies to requests.

func (*Retry) RoundTrip

func (c *Retry) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip executes a request and applies one or more retry policies.

type RetryAfter added in v1.4.0

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

RetryAfter determines whether or not the transport will automatically retry a request based on configured behaviors for 429 responses with Retry-After header.

func (*RetryAfter) RoundTrip added in v1.4.0

func (c *RetryAfter) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip executes a request and applies one or more retry policies.

type RetryPolicy

type RetryPolicy func() Retrier

RetryPolicy is a factory that generates a Retrier.

func NewLimitedRetryPolicy

func NewLimitedRetryPolicy(limit int, policies ...RetryPolicy) RetryPolicy

NewLimitedRetryPolicy wraps a series of retry policies in an upper limit.

func NewStatusCodeRetryPolicy

func NewStatusCodeRetryPolicy(codes ...int) RetryPolicy

NewStatusCodeRetryPolicy generates a RetryPolicy that retries on specified status codes in the HTTP response.

func NewTimeoutRetryPolicy

func NewTimeoutRetryPolicy(timeout time.Duration) RetryPolicy

NewTimeoutRetryPolicy generates a RetryPolicy that ends a request after a given timeout duration and tries again.

type Rotator

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

Rotator contains multiple instances of a RoundTripper and rotates through them per-request. This is useful when dealing with HTTP/2 in situations where more than one TCP connection per host is required.

func NewRotator

func NewRotator(factory Factory, opts ...RotatorOption) *Rotator

NewRotator uses the given factory as a source and generates a number of instances based on the options given. The instances are called in a naive, round-robin manner.

func (*Rotator) RoundTrip

func (c *Rotator) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip round-robins the outgoing requests against all of the internal instances.

type RotatorOption

type RotatorOption func(*Rotator) *Rotator

RotatorOption is a configuration for the Rotator decorator

func RotatorOptionInstances

func RotatorOptionInstances(number int) RotatorOption

RotatorOptionInstances configurs a rotator with the number of internal RoundTripper instances it should maintain for the rotation.

type RoundTripperFunc

type RoundTripperFunc func(r *http.Request) (*http.Response, error)

RoundTripperFunc is modeled after the http.HandlerFunc and converts a function matching the RoundTrip signature to a RoundTripper implementation.

func (RoundTripperFunc) RoundTrip

func (d RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error)

RoundTrip calls the wrapped function.

type StatusCodeRetrier

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

StatusCodeRetrier retries based on HTTP status codes.

func (*StatusCodeRetrier) Retry

func (r *StatusCodeRetrier) Retry(req *http.Request, resp *http.Response, e error) bool

Retry the request if the response has a valid code that matches on of the codes given in the retry set.

type TimeoutRetrier

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

TimeoutRetrier applies a timeout to requests and retries if the request took longer than the timeout duration.

func (*TimeoutRetrier) Request

func (r *TimeoutRetrier) Request(req *http.Request) *http.Request

Request adds a timeout to the request context.

func (*TimeoutRetrier) Retry

func (r *TimeoutRetrier) Retry(req *http.Request, resp *http.Response, e error) bool

Retry the request if the context exceeded the deadline.

Jump to

Keyboard shortcuts

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