Documentation ¶
Overview ¶
Package httpclient provides an HTTP client instrumented with the ex/o11y package, it includes resiliency behaviour such as configurable timeouts, retries, authentication and connection pooling, with support for backing off when a 429 response code is seen.
Example (RouteParams) ¶
package main import ( "context" hc "github.com/circleci/ex/httpclient" ) func main() { q := map[string]string{ "branch": "BranchName", "reporting-window": "ReportingWindow", "analytics-segmentation": "bxp-service", } req := hc.NewRequest("GET", "/v2/service/%s/%s/%s/workflows/%s/summary", hc.RouteParams("VcsType", "OrgName", "ProjectName", "WorkflowName"), hc.QueryParams(q), ) client := hc.New( hc.Config{ Name: "my client", BaseURL: "http://127.0.0.1:52484/api", AcceptType: hc.JSON, }) err := client.Call(context.Background(), req) if err != nil { // do something } }
Output:
Index ¶
- Constants
- Variables
- func AllowGETWithBody() func(*Request)
- func Body(body interface{}) func(*Request)
- func BytesDecoder(resp *[]byte) func(*Request)
- func Cookie(cookie *http.Cookie) func(*Request)
- func Decoder(status int, decoder decoder) func(*Request)
- func Flatten(prefix string) func(*Request)
- func HasStatusCode(err error, codes ...int) bool
- func Header(key, val string) func(*Request)
- func Headers(headers map[string]string) func(*Request)
- func IsNoContent(err error) bool
- func IsRequestProblem(err error) bool
- func JSONDecoder(resp interface{}) func(*Request)
- func NewBytesDecoder(resp *[]byte) decoder
- func NewJSONDecoder(resp interface{}) decoder
- func NewStringDecoder(resp *string) decoder
- func NoRetry() func(*Request)
- func Propagation(propagation bool) func(*Request)
- func QueryParam(key, value string) func(*Request)
- func QueryParams(params map[string]string) func(*Request)
- func RawBody(body []byte) func(*Request)
- func RawQuery(rawquery string) func(*Request)
- func ResponseHeader(f func(http.Header)) func(*Request)
- func RouteParams(routeParams ...interface{}) func(*Request)
- func StringDecoder(resp *string) func(*Request)
- func SuccessDecoder(decoder decoder) func(*Request)
- func Timeout(timeout time.Duration) func(*Request)
- func UnixTransport(socket string) *http.Transport
- type Client
- type Config
- type HTTPError
- type Request
Examples ¶
Constants ¶
const JSON = "application/json; charset=utf-8"
Variables ¶
var ( ErrNoContent = o11y.NewWarning("no content") ErrServerBackoff = errors.New("server requested explicit backoff") )
Functions ¶
func AllowGETWithBody ¶
func AllowGETWithBody() func(*Request)
AllowGETWithBody will allow the client to send a GET request with a body, which we error on by default. We should remove this once RT-724 is completed.
func Body ¶
func Body(body interface{}) func(*Request)
Body sets the request body that will be sent as JSON
func BytesDecoder ¶
BytesDecoder is a shorthand to decode the success body as raw bytes
func Decoder ¶
Decoder adds a response body decoder to some http status code Note this will modify the original Request.
Example:
err := client.Call(ctx, httpclient.NewRequest("POST", "/bad", httpclient.Decoder(http.StatusBadRequest, httpclient.NewStringDecoder(&s)), ))
func HasStatusCode ¶
HasStatusCode tests err for HTTPError and returns true if any of the codes match the stored code.
func IsNoContent ¶
func IsRequestProblem ¶
IsRequestProblem checks the err for HTTPError and returns true if the stored status code is in the 4xx range
func JSONDecoder ¶
func JSONDecoder(resp interface{}) func(*Request)
JSONDecoder is a shorthand to decode the success body as JSON
func NewBytesDecoder ¶
func NewBytesDecoder(resp *[]byte) decoder
NewBytesDecoder decodes the response body into a byte slice
func NewJSONDecoder ¶
func NewJSONDecoder(resp interface{}) decoder
NewJSONDecoder returns a decoder func enclosing the resp param the func returned takes an io reader which will be passed to a json decoder to decode into the resp.
func NewStringDecoder ¶
func NewStringDecoder(resp *string) decoder
NewStringDecoder decodes the response body into a string
func NoRetry ¶
func NoRetry() func(*Request)
NoRetry prevents any retries from being made for this request.
func Propagation ¶
Propagation sets the tracing propagation header on the request if set to true, the header is not set if set to false
func QueryParam ¶
QueryParam sets one query param for the request
func QueryParams ¶
QueryParams sets multiple query params for the request
func ResponseHeader ¶
func RouteParams ¶
func RouteParams(routeParams ...interface{}) func(*Request)
func StringDecoder ¶
StringDecoder is a shorthand to decode the success body as a string
func SuccessDecoder ¶
func SuccessDecoder(decoder decoder) func(*Request)
SuccessDecoder sets the decoder for all 2xx statuses
func Timeout ¶
Timeout sets the individual request timeout, and does not take into account of retries. This is different from setting the timeout field on the http client, which is the total timeout across all retries.
func UnixTransport ¶
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the o11y instrumented http client.
func (*Client) Call ¶
Call makes the Request call. It will trace out a top level span and a span for any retry attempts. Retries will be attempted on any 5XX responses. If the http call completed with a non 2XX status code then an HTTPError will be returned containing details of result of the call.
Example:
err := client.Call(ctx, httpclient.NewRequest("POST", "/api/fruit/%s", httpclient.RouteParams("apple"), httpclient.Timeout(time.Second), )) if err != nil { panic(err) }
nolint:funlen
func (*Client) CloseIdleConnections ¶
func (c *Client) CloseIdleConnections()
CloseIdleConnections is only used for testing.
type Config ¶
type Config struct { // Name is used to identify the client in spans Name string // BaseURL is the URL and optional path prefix to the server that this is a client of. BaseURL string // AuthHeader the name of the header that the AuthToken will be set on. If empty then // the AuthToken will be used in a bearer token authorization header AuthHeader string // AuthToken is the token to use for authentication. AuthToken string // AcceptType if set will be used to set the Accept header. AcceptType string // Timeout is the maximum time any call can take including any retries. // Note that a zero Timeout is not defaulted, but means the client will retry indefinitely. Timeout time.Duration // MaxConnectionsPerHost sets the connection pool size MaxConnectionsPerHost int // UserAgent that will be used for every request UserAgent string // Transport allows overriding the default HTTP transport the client will use. Transport http.RoundTripper // TransportModifier can modify the transport after the client has applied other config settings TransportModifier func(Transport *http.Transport) // Tracer allows http stats tracing to be enabled. Tracer tracer // DialContext allows a dial context to be injected into the HTTP transport. DialContext func(ctx context.Context, network string, addr string) (net.Conn, error) // NoRateLimitBackoff disables the circuit breaker behaviour when the client receives a 429 // response. This is useful if the server rate-limits more granularly than requests-per-client // (e.g. if it uses specific query params or headers when bucketing requests) but should be enabled // with care as it can lead to thrashing the server if not used appropriately. NoRateLimitBackoff bool // DisableW3CTracePropagation is a temporary option to disable sending w3c trace propagation headers DisableW3CTracePropagation bool }
Config provides the client configuration
type HTTPError ¶
type HTTPError struct {
// contains filtered or unexported fields
}
HTTPError represents an error in an HTTP call when the response status code is not 2XX
type Request ¶
type Request struct {
// contains filtered or unexported fields
}
Request is an individual http Request that the Client will send NewRequest should be used to create a new Request rather than constructing a Request directly.
func NewRequest ¶
NewRequest should be used to create a new Request rather than constructing a Request directly. This encourages the user to specify a "route" for the tracing, and avoid high cardinality routes (when parts of the url may contain many varying values).
Example:
req := httpclient.NewRequest("POST", "/api/person/%s", httpclient.RouteParams("person-id"), httpclient.Timeout(time.Second), )