Documentation ¶
Index ¶
- Constants
- Variables
- func EncodeJSONRequestBody(_ context.Context, r *http.Request, body interface{}) error
- func EncodeURLEncodedRequestBody(_ context.Context, r *http.Request, body interface{}) error
- func FxClientCustomizers(providers ...interface{}) []fx.Annotated
- func Use()
- type AfterHook
- type AfterHookFunc
- type BeforeHook
- type BeforeHookFunc
- type Client
- type ClientConfig
- type ClientCustomizer
- type ClientCustomizerFunc
- type ClientOption
- type ClientOptions
- type ConfigurableAfterHook
- type ConfigurableBeforeHook
- type CreateRequestFunc
- type DecodeResponseFunc
- type EncodeRequestFunc
- type Error
- func NewDiscoveryDownError(value interface{}, causes ...interface{}) *Error
- func NewError(code int64, e interface{}, causes ...interface{}) *Error
- func NewErrorWithResponse(code int64, e interface{}, resp *http.Response, rawBody []byte, ...) *Error
- func NewErrorWithStatusCode(e interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error
- func NewInternalError(value interface{}, causes ...interface{}) *Error
- func NewMediaTypeError(value interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error
- func NewNoEndpointFoundError(value interface{}, causes ...interface{}) *Error
- func NewRequestSerializationError(value interface{}, causes ...interface{}) *Error
- func NewSerializationError(value interface{}, resp *http.Response, rawBody []byte, causes ...interface{}) *Error
- func NewServerTimeoutError(value interface{}, causes ...interface{}) *Error
- type ErrorResponse
- type ErrorResponseBody
- type Hook
- type HttpClientProperties
- type LogDetailsLevel
- type LoggerProperties
- type LoggingConfig
- type Request
- type RequestOptions
- func WithBasicAuth(username, password string) RequestOptions
- func WithBody(body interface{}) RequestOptions
- func WithHeader(key, value string) RequestOptions
- func WithParam(key, value string) RequestOptions
- func WithRequestBodyEncoder(enc EncodeRequestFunc) RequestOptions
- func WithRequestCreator(enc CreateRequestFunc) RequestOptions
- func WithUrlEncodedBody(body url.Values) RequestOptions
- func WithoutHeader(key string) RequestOptions
- type Response
- type ResponseOptions
- type RetryCallback
- type Retryable
- type SDOption
- type SDOptions
- type SDTargetResolver
- type TargetResolver
- type TargetResolverFunc
Constants ¶
const ( HeaderContentType = "Content-Type" HeaderAuthorization = "Authorization" )
const ( MediaTypeJson = "application/json" MediaTypeFormUrlEncoded = "application/x-www-form-urlencoded" )
const ( ErrorTypeCodeInternal = Reserved + iota<<ErrorTypeOffset ErrorTypeCodeTransport ErrorTypeCodeResponse )
All "Type" values are used as mask
const ( ErrorSubTypeCodeInternal = ErrorTypeCodeInternal + iota<<ErrorSubTypeOffset ErrorSubTypeCodeDiscovery )
All "SubType" values are used as mask sub types of ErrorTypeCodeInternal
const ( ErrorSubTypeCodeServerSide = ErrorTypeCodeResponse + iota<<ErrorSubTypeOffset ErrorSubTypeCodeClientSide ErrorSubTypeCodeMedia )
All "SubType" values are used as mask sub types of ErrorTypeCodeResponse
const ( ErrorCodeDiscoveryDown = ErrorSubTypeCodeDiscovery + iota ErrorCodeNoEndpointFound )
ErrorSubTypeCodeDiscovery
const ( ErrorCodeMediaType = ErrorSubTypeCodeMedia + iota ErrorCodeSerialization )
ErrorSubTypeCodeMedia
const ( ErrorCodeGenericClientSide = ErrorSubTypeCodeClientSide + iota ErrorCodeForbidden )
ErrorSubTypeCodeClientSide
const ( HighestReservedHookOrder = -10000 LowestReservedHookOrder = 10000 HookOrderTokenPassthrough = HighestReservedHookOrder + 10 HookOrderRequestLogger = LowestReservedHookOrder HookOrderResponseLogger = HighestReservedHookOrder )
const (
ErrorCodeGenericServerSide = ErrorSubTypeCodeServerSide + iota
)
ErrorSubTypeCodeServerSide
const (
ErrorCodeInternal = ErrorSubTypeCodeInternal + iota
)
ErrorSubTypeCodeInternal
const (
ErrorCodeServerTimeout = ErrorSubTypeCodeTimeout + iota
)
ErrorSubTypeCodeTimeout
const (
ErrorSubTypeCodeTimeout = ErrorTypeCodeTransport + iota<<ErrorSubTypeOffset
)
All "SubType" values are used as mask sub types of ErrorTypeCodeTransport
const (
FxGroup = "http-client"
)
const (
PropertiesPrefix = "integrate.http"
)
const (
// Reserved http client reserved error range
Reserved = 0xcc << ReservedOffset
)
Variables ¶
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
var (
ErrorDiscoveryDown = NewError(ErrorCodeDiscoveryDown, "service discovery is not available")
)
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 EncodeURLEncodedRequestBody ¶ added in v0.14.0
func FxClientCustomizers ¶
FxClientCustomizers takes providers of ClientCustomizer and wrap them with FxGroup
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 HookResponseLogger ¶
func HookResponseLogger(cfg *ClientConfig) AfterHook
type AfterHookFunc ¶ added in v0.14.0
AfterHookFunc implements Hook with only "after" operation
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
BeforeHookFunc implements Hook with only "before" operation
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 EncodeRequestFunc ¶ added in v0.14.0
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 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 NewNoEndpointFoundError ¶
func NewNoEndpointFoundError(value interface{}, causes ...interface{}) *Error
func NewRequestSerializationError ¶
func NewRequestSerializationError(value interface{}, causes ...interface{}) *Error
func NewSerializationError ¶
func NewServerTimeoutError ¶
func NewServerTimeoutError(value interface{}, causes ...interface{}) *Error
func (Error) WithMessage ¶
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 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 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
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
type TargetResolver ¶ added in v0.14.0
type TargetResolverFunc ¶ added in v0.14.0
func NewStaticTargetResolver ¶ added in v0.14.0
func NewStaticTargetResolver(baseUrl string) (TargetResolverFunc, error)