httpclient

package
v0.15.1 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2024 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Index

Constants

View Source
const (
	HeaderContentType   = "Content-Type"
	HeaderAuthorization = "Authorization"
)
View Source
const (
	MediaTypeJson           = "application/json"
	MediaTypeFormUrlEncoded = "application/x-www-form-urlencoded"
)
View Source
const (
	ErrorTypeCodeInternal = Reserved + iota<<ErrorTypeOffset
	ErrorTypeCodeTransport
	ErrorTypeCodeResponse
)

All "Type" values are used as mask

View Source
const (
	ErrorSubTypeCodeInternal = ErrorTypeCodeInternal + iota<<ErrorSubTypeOffset
	ErrorSubTypeCodeDiscovery
)

All "SubType" values are used as mask sub types of ErrorTypeCodeInternal

View Source
const (
	ErrorSubTypeCodeServerSide = ErrorTypeCodeResponse + iota<<ErrorSubTypeOffset
	ErrorSubTypeCodeClientSide
	ErrorSubTypeCodeMedia
)

All "SubType" values are used as mask sub types of ErrorTypeCodeResponse

View Source
const (
	ErrorCodeDiscoveryDown = ErrorSubTypeCodeDiscovery + iota
	ErrorCodeNoEndpointFound
)

ErrorSubTypeCodeDiscovery

View Source
const (
	ErrorCodeMediaType = ErrorSubTypeCodeMedia + iota
	ErrorCodeSerialization
)

ErrorSubTypeCodeMedia

View Source
const (
	ErrorCodeGenericClientSide = ErrorSubTypeCodeClientSide + iota
	ErrorCodeUnauthorized
	ErrorCodeForbidden
)

ErrorSubTypeCodeClientSide

View Source
const (
	HighestReservedHookOrder  = -10000
	LowestReservedHookOrder   = 10000
	HookOrderTokenPassthrough = HighestReservedHookOrder + 10
	HookOrderRequestLogger    = LowestReservedHookOrder
	HookOrderResponseLogger   = HighestReservedHookOrder
)
View Source
const (
	ErrorCodeGenericServerSide = ErrorSubTypeCodeServerSide + iota
)

ErrorSubTypeCodeServerSide

View Source
const (
	ErrorCodeInternal = ErrorSubTypeCodeInternal + iota
)

ErrorSubTypeCodeInternal

View Source
const (
	ErrorCodeServerTimeout = ErrorSubTypeCodeTimeout + iota
)

ErrorSubTypeCodeTimeout

View Source
const (
	ErrorSubTypeCodeTimeout = ErrorTypeCodeTransport + iota<<ErrorSubTypeOffset
)

All "SubType" values are used as mask sub types of ErrorTypeCodeTransport

View Source
const (
	FxGroup = "http-client"
)
View Source
const (
	PropertiesPrefix = "integrate.http"
)
View Source
const (
	// Reserved http client reserved error range
	Reserved = 0xcc << ReservedOffset
)

Variables

View Source
var (
	ErrorCategoryHttpClient = NewErrorCategory(Reserved, errors.New("error type: http client"))
	ErrorTypeInternal       = NewErrorType(ErrorTypeCodeInternal, errors.New("error type: internal"))
	ErrorTypeTransport      = NewErrorType(ErrorTypeCodeTransport, errors.New("error type: http transport"))
	ErrorTypeResponse       = NewErrorType(ErrorTypeCodeResponse, errors.New("error type: error status code"))

	ErrorSubTypeInternalError = NewErrorSubType(ErrorSubTypeCodeInternal, errors.New("error sub-type: internal"))
	ErrorSubTypeDiscovery     = NewErrorSubType(ErrorSubTypeCodeDiscovery, errors.New("error sub-type: discover"))
	ErrorSubTypeTimeout       = NewErrorSubType(ErrorSubTypeCodeTimeout, errors.New("error sub-type: server timeout"))
	ErrorSubTypeServerSide    = NewErrorSubType(ErrorSubTypeCodeServerSide, errors.New("error sub-type: server side"))
	ErrorSubTypeClientSide    = NewErrorSubType(ErrorSubTypeCodeClientSide, errors.New("error sub-type: client side"))
	ErrorSubTypeMedia         = NewErrorSubType(ErrorSubTypeCodeMedia, errors.New("error sub-type: server timeout"))
)

ErrorTypes, can be used in errors.Is

View Source
var (
	ErrorDiscoveryDown = NewError(ErrorCodeDiscoveryDown, "service discovery is not available")
)
View Source
var Module = &bootstrap.Module{
	Name:       "http-client",
	Precedence: bootstrap.HttpClientPrecedence,
	Options: []fx.Option{
		appconfig.FxEmbeddedDefaults(defaultConfigFS),
		fx.Provide(bindHttpClientProperties),
		fx.Provide(provideHttpClient),
		fx.Provide(tracingProvider()),
	},
}

Functions

func EncodeJSONRequestBody added in v0.14.0

func EncodeJSONRequestBody(_ context.Context, r *http.Request, body interface{}) error

func EncodeURLEncodedRequestBody added in v0.14.0

func EncodeURLEncodedRequestBody(_ context.Context, r *http.Request, body interface{}) error

func FxClientCustomizers

func FxClientCustomizers(providers ...interface{}) []fx.Annotated

FxClientCustomizers takes providers of ClientCustomizer and wrap them with FxGroup

func Use

func Use()

Types

type AfterHook

type AfterHook interface {
	// After is invoked after HTTP response is returned and before the response is decoded.
	After(context.Context, *http.Response) context.Context
}

AfterHook is used for ClientConfig and ClientOptions, The implementing class could also implement order.Ordered interface. Highest order is invoked first

func AfterHookWithOrder added in v0.14.0

func AfterHookWithOrder(order int, hook AfterHook) AfterHook

func HookResponseLogger

func HookResponseLogger(cfg *ClientConfig) AfterHook

type AfterHookFunc added in v0.14.0

type AfterHookFunc func(context.Context, *http.Response) context.Context

AfterHookFunc implements Hook with only "after" operation

func (AfterHookFunc) After added in v0.14.0

func (fn AfterHookFunc) After(ctx context.Context, resp *http.Response) context.Context

type BeforeHook

type BeforeHook interface {
	// Before is invoked after the HTTP request is encoded and before the request is sent.
	Before(context.Context, *http.Request) context.Context
}

BeforeHook is used for ClientConfig and ClientOptions, The implementing class could also implement order.Ordered interface. Highest order is invoked first

func BeforeHookWithOrder added in v0.14.0

func BeforeHookWithOrder(order int, hook BeforeHook) BeforeHook

func HookRequestLogger

func HookRequestLogger(cfg *ClientConfig) BeforeHook

func HookTokenPassthrough

func HookTokenPassthrough() BeforeHook

type BeforeHookFunc added in v0.14.0

type BeforeHookFunc func(context.Context, *http.Request) context.Context

BeforeHookFunc implements Hook with only "before" operation

func (BeforeHookFunc) Before added in v0.14.0

func (fn BeforeHookFunc) Before(ctx context.Context, req *http.Request) context.Context

type Client

type Client interface {
	// Execute send the provided request and parse the response using provided ResponseOptions
	// When using default decoding function:
	// 		- it returns non-nil Response only if the response has 2XX status code
	// 		- it returns non-nil error for 4XX, 5XX status code or any other type of errors
	// 		- the returned error can be casted to *Error
	Execute(ctx context.Context, request *Request, opts ...ResponseOptions) (*Response, error)

	// WithService create a client with specific service with given instance selectors.
	// The returned client is responsible to track service instance changes with help of discovery package,
	// and to perform load-balancing and retrying.
	// The returned client is goroutine-safe and can be reused
	WithService(service string, opts ...SDOptions) (Client, error)

	// WithBaseUrl create a client with specific base URL.
	// The returned client is responsible to perform retrying.
	// The returned client is goroutine-safe and can be reused
	WithBaseUrl(baseUrl string) (Client, error)

	// WithConfig create a shallow copy of the client with specified config.
	// Service (with LB) or BaseURL cannot be changed with this method.
	// If any field of provided config is zero value, this value is not applied.
	// The returned client is goroutine-safe and can be reused
	WithConfig(config *ClientConfig) Client
}

func NewClient added in v0.14.0

func NewClient(opts ...ClientOptions) Client

type ClientConfig

type ClientConfig struct {
	// HTTPClient underlying http.Client to use
	HTTPClient *http.Client
	// BeforeHooks hooks to use before sending HTTP request
	BeforeHooks []BeforeHook
	// AfterHooks hooks to use before sending HTTP request
	AfterHooks []AfterHook
	// MaxRetries number of retries in case of error. Negative value means no retry.
	// Note: by default, non-2XX response status code error is not retried
	MaxRetries int
	// RetryBackoff time to wait between retries. Negative means retry immediately
	RetryBackoff time.Duration
	// RetryCallback allows fine control when and how to retry.
	// If set, this override MaxRetries and RetryBackoff
	RetryCallback RetryCallback
	// Timeout how long to wait for each execution.
	// Note: this is total duration including RetryBackoff between each attempt, not per-retry timeout.
	Timeout time.Duration
	// Logger used for logging request/response
	Logger log.ContextualLogger
	// Logging configuration of request/response logging
	Logging LoggingConfig
}

ClientConfig is used to change Client's config

func DefaultConfig

func DefaultConfig() *ClientConfig

type ClientCustomizer

type ClientCustomizer interface {
	Customize(opt *ClientOption)
}

type ClientCustomizerFunc

type ClientCustomizerFunc func(opt *ClientOption)

func (ClientCustomizerFunc) Customize

func (fn ClientCustomizerFunc) Customize(opt *ClientOption)

type ClientOption

type ClientOption struct {
	ClientConfig
	SDClient           discovery.Client
	DefaultSelector    discovery.InstanceMatcher
	DefaultBeforeHooks []BeforeHook
	DefaultAfterHooks  []AfterHook
}

ClientOption carries initial configurations of Clients

type ClientOptions

type ClientOptions func(opt *ClientOption)

ClientOptions is used for creating Client and its customizers

type ConfigurableAfterHook

type ConfigurableAfterHook interface {
	WithConfig(cfg *ClientConfig) AfterHook
}

ConfigurableAfterHook is an additional interface that AfterHook can implement

type ConfigurableBeforeHook

type ConfigurableBeforeHook interface {
	WithConfig(cfg *ClientConfig) BeforeHook
}

ConfigurableBeforeHook is an additional interface that BeforeHook can implement

type CreateRequestFunc added in v0.14.0

type CreateRequestFunc func(ctx context.Context, method string, target *url.URL) (*http.Request, error)

CreateRequestFunc is a function to create http.Request with given context, method and target URL

type DecodeResponseFunc added in v0.14.0

type DecodeResponseFunc func(context.Context, *http.Response) (response interface{}, err error)

type EncodeRequestFunc added in v0.14.0

type EncodeRequestFunc func(ctx context.Context, req *http.Request, val interface{}) error

EncodeRequestFunc is a function to modify http.Request for encoding given value

type Error

type Error struct {
	CodedError
	Response *ErrorResponse
}

Error can optionally store *http.Response's status code, headers and body

func NewDiscoveryDownError

func NewDiscoveryDownError(value interface{}, causes ...interface{}) *Error

func NewError

func NewError(code int64, e interface{}, causes ...interface{}) *Error

func NewErrorWithResponse

func NewErrorWithResponse(code int64, e interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error

NewErrorWithResponse create a Error with ErrorResponse. if given "e" is an ErrorResponseBody, it saved into ErrorResponse

func NewErrorWithStatusCode

func NewErrorWithStatusCode(e interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error

NewErrorWithStatusCode create a Error with ErrorResponse, and choose error code based on status code if given "e" is an ErrorResponseBody, it saved into ErrorResponse

func NewInternalError

func NewInternalError(value interface{}, causes ...interface{}) *Error

func NewMediaTypeError

func NewMediaTypeError(value interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error

func NewNoEndpointFoundError

func NewNoEndpointFoundError(value interface{}, causes ...interface{}) *Error

func NewRequestSerializationError

func NewRequestSerializationError(value interface{}, causes ...interface{}) *Error

func NewSerializationError

func NewSerializationError(value interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error

func NewServerTimeoutError

func NewServerTimeoutError(value interface{}, causes ...interface{}) *Error

func (Error) Error

func (e Error) Error() string

func (Error) String

func (e Error) String() string

func (Error) WithMessage

func (e Error) WithMessage(msg string, args ...interface{}) *Error

type ErrorResponse

type ErrorResponse struct {
	http.Response
	RawBody []byte
	Body    ErrorResponseBody
}

func (ErrorResponse) Error

func (er ErrorResponse) Error() string

func (ErrorResponse) Message

func (er ErrorResponse) Message() string

type ErrorResponseBody

type ErrorResponseBody interface {
	Error() string
	Message() string
	Details() map[string]string
}

type Hook added in v0.14.0

type Hook interface {
	// Before is invoked after the HTTP request is encoded and before the request is sent.
	// The implementing class could also implement order.Ordered interface. Highest order is invoked first
	Before(context.Context, *http.Request) context.Context
	// After is invoked after HTTP response is returned and before the response is decoded.
	// The implementing class could also implement order.Ordered interface. Highest order is invoked first
	After(context.Context, *http.Response) context.Context
}

Hook is used for intercepting is used for ClientConfig and ClientOptions,

type HttpClientProperties

type HttpClientProperties struct {
	MaxRetries int              `json:"max-retries"` // negative value means no retry
	Timeout    utils.Duration   `json:"timeout"`
	Logger     LoggerProperties `json:"logger"`
}

type LogDetailsLevel

type LogDetailsLevel int
const (
	LogDetailsLevelUnknown LogDetailsLevel = iota
	LogDetailsLevelNone
	LogDetailsLevelMinimum
	LogDetailsLevelHeaders
	LogDetailsLevelFull
)

func (LogDetailsLevel) MarshalText

func (l LogDetailsLevel) MarshalText() ([]byte, error)

func (LogDetailsLevel) String

func (l LogDetailsLevel) String() string

func (*LogDetailsLevel) UnmarshalText

func (l *LogDetailsLevel) UnmarshalText(data []byte) error

type LoggerProperties

type LoggerProperties struct {
	Level           log.LoggingLevel          `json:"level"`
	DetailsLevel    LogDetailsLevel           `json:"details-level"`
	SanitizeHeaders utils.CommaSeparatedSlice `json:"sanitize-headers"`
	ExcludeHeaders  utils.CommaSeparatedSlice `json:"exclude-headers"`
}

type LoggingConfig

type LoggingConfig struct {
	Level           log.LoggingLevel
	DetailsLevel    LogDetailsLevel
	SanitizeHeaders utils.StringSet
	ExcludeHeaders  utils.StringSet
}

type Request

type Request struct {
	Path           string
	Method         string
	Params         map[string]string
	Headers        http.Header
	Body           interface{}
	BodyEncodeFunc EncodeRequestFunc
	CreateFunc     CreateRequestFunc
}

Request is wraps all information about the request

func NewRequest

func NewRequest(path, method string, opts ...RequestOptions) *Request

type RequestOptions

type RequestOptions func(r *Request)

RequestOptions used to configure Request in NewRequest

func WithBasicAuth

func WithBasicAuth(username, password string) RequestOptions

func WithBody

func WithBody(body interface{}) RequestOptions

func WithHeader

func WithHeader(key, value string) RequestOptions

func WithParam

func WithParam(key, value string) RequestOptions

func WithRequestBodyEncoder added in v0.14.0

func WithRequestBodyEncoder(enc EncodeRequestFunc) RequestOptions

func WithRequestCreator added in v0.14.0

func WithRequestCreator(enc CreateRequestFunc) RequestOptions

func WithUrlEncodedBody

func WithUrlEncodedBody(body url.Values) RequestOptions

func WithoutHeader

func WithoutHeader(key string) RequestOptions

type Response

type Response struct {
	StatusCode int
	Headers    http.Header
	Body       interface{}
	RawBody    []byte `json:"-"`
}

type ResponseOptions

type ResponseOptions func(opt *responseOption)

func CustomResponseDecoder

func CustomResponseDecoder(dec DecodeResponseFunc) ResponseOptions

CustomResponseDecoder returns a ResponseOptions that specify custom decoding function of http.Response this options overwrite JsonBody and JsonErrorBody

func JsonBody

func JsonBody(body interface{}) ResponseOptions

JsonBody returns a ResponseOptions that specify interface{} to use for parsing response body as JSON

func JsonErrorBody

func JsonErrorBody(errBody ErrorResponseBody) ResponseOptions

JsonErrorBody returns a ResponseOptions that specify interface{} to use for parsing error response as JSON

type RetryCallback added in v0.14.0

type RetryCallback func(n int, rs interface{}, err error) (shouldContinue bool, backoff time.Duration)

RetryCallback retry control function. RetryCallback is executed each time when non-nil error is returned. "n": indicate the iteration number of attempts. "rs" and "err" indicate the result of the current attempt RetryCallback returns whether Retryable need to keep trying and optionally wait for "backoff" before next attempt

type Retryable added in v0.14.0

type Retryable func(ctx context.Context) (interface{}, error)

func (Retryable) Try added in v0.14.0

func (r Retryable) Try(ctx context.Context, timeout time.Duration, cb RetryCallback) (interface{}, error)

Try keep trying to execute the Retryable until 1. No error is returned 2. Timeout reached 3. RetryCallback tells it to stop The Retryable is executed in separated goroutine, and the RetryCallback is invoked in current goroutine when non-nil error is returned. If the execution finished without any successful result, latest error is returned if available, otherwise context.Err()

type SDOption added in v0.14.0

type SDOption struct {
	// Selector Used to filter targets during service discovery.
	// Default: discovery.InstanceIsHealthy()
	Selector discovery.InstanceMatcher
	// InvalidateOnError Whether to return previously known targets in case service discovery is temporarily unavailable
	// Default: true
	InvalidateOnError bool
	// InvalidateTimeout How long to keep previously known targets in case service discovery is temporarily unavailable.
	// < 0:  Always use previously known targets, equivalent to InvalidateOnError = false
	// == 0: Never use previously known targets.
	// > 0:  Use previously known targets for the specified duration since the first error received from SD client
	// Default: -1 if InvalidateOnError = false, 0 if InvalidateOnError = true
	InvalidateTimeout time.Duration
	// Scheme HTTP scheme to use.
	// If not set, the actual scheme is resolved from target instance's Meta/Tags.
	// Possible values: "http", "https", "" (empty string).
	// Default: ""
	Scheme string
	// ContextPath Path prefix for any given Request.
	// If not set, the context path is resolved from target instance's Meta/Tags.
	// e.g. "/auth/api"
	// Default: ""
	ContextPath string
}

type SDOptions added in v0.14.0

type SDOptions func(opt *SDOption)

SDOptions allows control of endpointCache behavior.

type SDTargetResolver added in v0.14.0

type SDTargetResolver struct {
	SDOption
	// contains filtered or unexported fields
}

SDTargetResolver implements TargetResolver interface that use the discovery.Instancer to resolve target's address. It also attempts to resolve the http scheme and context path from instance's tags/meta. In case of failed service discovery with error, this resolver keeps using previously found instances assuming they are still good of period of time configured by SDOption. Currently, this resolver only support round-robin load balancing.

func NewSDTargetResolver added in v0.14.0

func NewSDTargetResolver(instancer discovery.Instancer, opts ...SDOptions) (*SDTargetResolver, error)

NewSDTargetResolver creates a TargetResolver that work with discovery.Instancer. See SDTargetResolver

func (*SDTargetResolver) Resolve added in v0.14.0

func (ke *SDTargetResolver) Resolve(_ context.Context, req *Request) (*url.URL, error)

type TargetResolver added in v0.14.0

type TargetResolver interface {
	Resolve(ctx context.Context, req *Request) (*url.URL, error)
}

type TargetResolverFunc added in v0.14.0

type TargetResolverFunc func(ctx context.Context, req *Request) (*url.URL, error)

func NewStaticTargetResolver added in v0.14.0

func NewStaticTargetResolver(baseUrl string) (TargetResolverFunc, error)

func (TargetResolverFunc) Resolve added in v0.14.0

func (fn TargetResolverFunc) Resolve(ctx context.Context, req *Request) (*url.URL, error)

Jump to

Keyboard shortcuts

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