httpclient

package
v1.0.10458-9e886f5 Latest Latest
Warning

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

Go to latest
Published: May 23, 2024 License: MIT Imports: 14 Imported by: 1

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

Examples

Constants

View Source
const JSON = "application/json; charset=utf-8"

Variables

View Source
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

func BytesDecoder(resp *[]byte) func(*Request)

BytesDecoder is a shorthand to decode the success body as raw bytes

func Cookie(cookie *http.Cookie) func(*Request)

Cookie sets the cookie for the request

func Decoder

func Decoder(status int, decoder decoder) func(*Request)

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

func HasStatusCode(err error, codes ...int) bool

HasStatusCode tests err for HTTPError and returns true if any of the codes match the stored code.

func Header(key, val string) func(*Request)

Header sets one header value for the request

func Headers

func Headers(headers map[string]string) func(*Request)

Headers sets multiple headers in one go for the request

func IsNoContent

func IsNoContent(err error) bool

func IsRequestProblem

func IsRequestProblem(err error) bool

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

func Propagation(propagation bool) func(*Request)

Propagation sets the tracing propagation header on the request if set to true, the header is not set if set to false

func QueryParam

func QueryParam(key, value string) func(*Request)

QueryParam sets one query param for the request

func QueryParams

func QueryParams(params map[string]string) func(*Request)

QueryParams sets multiple query params for the request

func RawBody

func RawBody(body []byte) func(*Request)

RawBody sets the request body that will be sent as is

func RawQuery

func RawQuery(rawquery string) func(*Request)

RawQuery sets the unmodified raw query

func ResponseHeader

func ResponseHeader(f func(http.Header)) func(*Request)

func RouteParams

func RouteParams(routeParams ...interface{}) func(*Request)

func StringDecoder

func StringDecoder(resp *string) func(*Request)

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

func Timeout(timeout time.Duration) func(*Request)

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

func UnixTransport(socket string) *http.Transport

Types

type Client

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

Client is the o11y instrumented http client.

func New

func New(cfg Config) *Client

New creates a client configured with the config param

func (*Client) Call

func (c *Client) Call(ctx context.Context, r Request) (err error)

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
}

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

func (*HTTPError) Code

func (e *HTTPError) Code() int

Code returns the status code recorded in this error.

func (*HTTPError) Error

func (e *HTTPError) Error() string

func (*HTTPError) Is

func (e *HTTPError) Is(target error) bool

Is checks that this error is being checked for the special o11y error that is not added to the trace as an error. If the error is due to relatively expected failure response codes return true so it does not appear in the traces as an error.

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

func NewRequest(method, route string, opts ...func(*Request)) Request

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),
)

Directories

Path Synopsis
Package dnscache contains a simple in-process cache for DNS lookups
Package dnscache contains a simple in-process cache for DNS lookups

Jump to

Keyboard shortcuts

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