httpclient

package
v0.13.0 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 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),
	},
}

Functions

func EncodeJSONRequest

func EncodeJSONRequest(c context.Context, r *http.Request, request 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 {
	ResponseFunc() httptransport.ClientResponseFunc
}

AfterHook is used for ClientConfig and ClientOptions, the ResponseFunc is invoked after response is returned implementing class could also implement order.Ordered interface. Highest order is invoked first

func After

func HookResponseLogger

func HookResponseLogger(logger log.ContextualLogger, logging *LoggingConfig) AfterHook

type BeforeHook

type BeforeHook interface {
	RequestFunc() httptransport.RequestFunc
}

BeforeHook is used for ClientConfig and ClientOptions, the RequestFunc is invoked before request is sent implementing class could also implement order.Ordered interface. Highest order is invoked first

func Before

func Before(order int, fn httptransport.RequestFunc) BeforeHook

func HookRequestLogger

func HookRequestLogger(logger log.ContextualLogger, logging *LoggingConfig) BeforeHook

func HookTokenPassthrough

func HookTokenPassthrough() BeforeHook

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, selectors ...discovery.InstanceMatcher) (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 non-primitive 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
}

type ClientConfig

type ClientConfig struct {
	HTTPClient  *http.Client // underlying http.Client to use
	BeforeHooks []BeforeHook
	AfterHooks  []AfterHook
	MaxRetries  int // negative value means no retry
	Timeout     time.Duration
	Logger      log.ContextualLogger
	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
	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 EndpointFactory

type EndpointFactory func(instDesp interface{}) (endpoint.Endpoint, error)

EndpointFactory takes a instance descriptor and create endpoint.Endpoint Supported instance type could be :

  • *discovery.Instance
  • *url.URL as base url

type Endpointer

type Endpointer interface {
	sd.Endpointer
	WithConfig(config *EndpointerConfig) Endpointer
}

type EndpointerConfig

type EndpointerConfig struct {
	EndpointFactory EndpointFactory
	Selector        discovery.InstanceMatcher
	Logger          log.ContextualLogger
}

EndpointerConfig is a subset of EndpointerOption, which can be changed after endpointer is created

type EndpointerOption

type EndpointerOption struct {
	ServiceName       string
	EndpointFactory   EndpointFactory
	Selector          discovery.InstanceMatcher
	InvalidateOnError bool
	InvalidateTimeout time.Duration
	Logger            log.ContextualLogger
}

type EndpointerOptions

type EndpointerOptions func(*EndpointerOption)

EndpointerOptions allows control of endpointCache behavior.

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 HttpClientProperties

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

type KitEndpointer

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

KitEndpointer implements sd.Endpointer interface and works with discovery.Instancer. When created with NewKitEndpointer function, it automatically registers as a subscriber to events from the Instances and maintains a list of active Endpoints.

func NewKitEndpointer

func NewKitEndpointer(instancer discovery.Instancer, opts ...EndpointerOptions) (*KitEndpointer, error)

NewKitEndpointer creates a slim custom sd.Endpointer that work with discovery.Instancer and uses factory f to create Endpoints. If src notifies of an error, the Endpointer keeps returning previously created Endpoints assuming they are still good, unless this behavior is disabled via InvalidateOnError option.

func (*KitEndpointer) Endpoints

func (ke *KitEndpointer) Endpoints() ([]endpoint.Endpoint, error)

Endpoints implements sd.Endpointer.

func (*KitEndpointer) WithConfig

func (ke *KitEndpointer) WithConfig(cfg *EndpointerConfig) Endpointer

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{}
	EncodeFunc httptransport.EncodeRequestFunc
}

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)

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 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 httptransport.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 SimpleEndpointer

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

func NewSimpleEndpointer

func NewSimpleEndpointer(baseUrls ...string) (*SimpleEndpointer, error)

func (*SimpleEndpointer) Endpoints

func (se *SimpleEndpointer) Endpoints() (ret []endpoint.Endpoint, err error)

func (*SimpleEndpointer) WithConfig

func (se *SimpleEndpointer) WithConfig(cfg *EndpointerConfig) Endpointer

Jump to

Keyboard shortcuts

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