Documentation ¶
Overview ¶
Package httpsling is a wrapper for creating and sending http httpsling (e.g. for webhooks, external 3d party integrations)
Example ¶
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) w.Write([]byte(`{"color":"red"}`)) })) defer s.Close() var out map[string]string resp, _ := Receive( out, Get(s.URL), ) fmt.Println(resp.StatusCode) fmt.Printf("%s", out)
Output:
Example (Everything) ¶
type Resource struct { ID string `json:"id"` Color string `json:"color"` } s := httptest.NewServer(MockHandler(201, JSON(true), Body(&Resource{Color: "red", ID: "123"}), )) defer s.Close() r := httptestutil.Requester(s, Post("/resources?size=big"), BearerAuth("atoken"), JSON(true), Body(&Resource{Color: "red"}), ExpectCode(201), Header("X-Request-Id", "5"), QueryParam("flavor", "vanilla"), QueryParams(&struct { Type string `url:"type"` }{Type: "upload"}), Client( httpclient.SkipVerify(true), httpclient.Timeout(5*time.Second), httpclient.MaxRedirects(3), ), ) r.MustApply(DumpToStderr()) httptestutil.Dump(s, os.Stderr) serverInspector := httptestutil.Inspect(s) clientInspector := Inspect(r) var resource Resource resp, err := r.Receive(&resource) if err != nil { panic(err) } fmt.Println("client-side request url path:", clientInspector.Request.URL.Path) fmt.Println("client-side request query:", clientInspector.Request.URL.RawQuery) fmt.Println("client-side request body:", clientInspector.RequestBody.String()) ex := serverInspector.LastExchange() fmt.Println("server-side request authorization header:", ex.Request.Header.Get("Authorization")) fmt.Println("server-side request request body:", ex.RequestBody.String()) fmt.Println("server-side request response body:", ex.ResponseBody.String()) fmt.Println("client-side response body:", clientInspector.ResponseBody.String()) fmt.Println("response status code:", resp.StatusCode) fmt.Println("unmarshaled response body:", resource)
Output:
Example (Receive) ¶
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(200) w.Write([]byte(`{"color":"red"}`)) })) defer s.Close() r := struct { Color string `json:"color"` }{} Receive(&r, Get(s.URL)) fmt.Println(r.Color)
Output:
Example (RequesterReceive) ¶
type Resource struct { Color string `json:"color"` } r := MustNew(MockDoer(200, JSON(true), Body(Resource{Color: "red"}), )) var resource Resource resp, _ := r.Receive(&resource, Get("http://api.com/resource")) defer resp.Body.Close() fmt.Println(resp.StatusCode) fmt.Println(resource.Color)
Output: 200 red
Index ¶
- Constants
- Variables
- func ChannelHandler() (chan<- *http.Response, http.Handler)
- func DefaultShouldRetry(_ int, _ *http.Request, resp *http.Response, err error) bool
- func IsSuccess(resp *http.Response) bool
- func MockHandler(statusCode int, options ...Option) http.Handler
- func MockResponse(statusCode int, options ...Option) *http.Response
- func OnlyIdempotentShouldRetry(_ int, req *http.Request, _ *http.Response, _ error) bool
- func Receive(into interface{}, opts ...Option) (*http.Response, error)
- func ReceiveWithContext(ctx context.Context, into interface{}, opts ...Option) (*http.Response, error)
- func Request(opts ...Option) (*http.Request, error)
- func RequestWithContext(ctx context.Context, opts ...Option) (*http.Request, error)
- func Send(opts ...Option) (*http.Response, error)
- func SendWithContext(ctx context.Context, opts ...Option) (*http.Response, error)
- type Backoffer
- type BackofferFunc
- type ContentTypeUnmarshaler
- type Doer
- type DoerFunc
- type ErrResponseHandler
- type ExponentialBackoff
- type File
- type Files
- type FormMarshaler
- type Inspector
- type JSONMarshaler
- type MarshalFunc
- type Marshaler
- type Middleware
- type NameGeneratorFunc
- type Option
- func Accept(accept string) Option
- func AddHeader(key, value string) Option
- func AppendPath(elements ...string) Option
- func BasicAuth(username, password string) Option
- func BearerAuth(token string) Option
- func Body(body interface{}) Option
- func Client(opts ...httpclient.Option) Option
- func ContentType(contentType string) Option
- func Delete(paths ...string) Option
- func DeleteHeader(key string) Option
- func Form() Option
- func Get(paths ...string) Option
- func Head(paths ...string) Option
- func Header(key, value string) Option
- func Host(host string) Option
- func JSON(indent bool) Option
- func Method(m string, paths ...string) Option
- func Patch(paths ...string) Option
- func Post(paths ...string) Option
- func Put(paths ...string) Option
- func QueryParam(k, v string) Option
- func QueryParams(queryStructs ...interface{}) Option
- func Range(byteRange string) Option
- func RelativeURL(paths ...string) Option
- func URL(rawurl string) Option
- func Use(m ...Middleware) Option
- func WithDoer(d Doer) Option
- func WithFileErrorResponseHandler(errHandler ErrResponseHandler) Option
- func WithMarshaler(m Marshaler) Option
- func WithMaxFileSize(i int64) Option
- func WithNameFuncGenerator(nameFunc NameGeneratorFunc) Option
- func WithUnmarshaler(m Unmarshaler) Option
- func WithValidationFunc(validationFunc ValidationFunc) Option
- func XML(indent bool) Option
- type OptionFunc
- type Requester
- func (r *Requester) Apply(opts ...Option) error
- func (r *Requester) Clone() *Requester
- func (r *Requester) CookieJar() http.CookieJar
- func (r *Requester) Do(req *http.Request) (*http.Response, error)
- func (r *Requester) HTTPClient() *http.Client
- func (r *Requester) Headers() http.Header
- func (r *Requester) MustApply(opts ...Option)
- func (r *Requester) MustWith(opts ...Option) *Requester
- func (r *Requester) Params() url.Values
- func (r *Requester) Receive(into interface{}, opts ...Option) (resp *http.Response, err error)
- func (r *Requester) ReceiveWithContext(ctx context.Context, into interface{}, opts ...Option) (resp *http.Response, err error)
- func (r *Requester) Request(opts ...Option) (*http.Request, error)
- func (r *Requester) RequestWithContext(ctx context.Context, opts ...Option) (*http.Request, error)
- func (r *Requester) Send(opts ...Option) (*http.Response, error)
- func (r *Requester) SendWithContext(ctx context.Context, opts ...Option) (*http.Response, error)
- func (r *Requester) Trailers() http.Header
- func (r *Requester) With(opts ...Option) (*Requester, error)
- type RetryConfig
- type ShouldRetryer
- type ShouldRetryerFunc
- type TextUnmarshaler
- type UnmarshalFunc
- type Unmarshaler
- type ValidationFunc
- type XMLMarshaler
Examples ¶
- Package
- Package (Everything)
- Package (Receive)
- Package (RequesterReceive)
- Accept
- AddHeader
- AppendPath
- BasicAuth
- BearerAuth
- Body
- Body (Map)
- Body (Raw)
- ChannelDoer
- ChannelHandler
- Client
- ContentType
- Delete
- DeleteHeader
- DumpToLog
- ExpectCode
- ExpectSuccessCode
- FormMarshaler
- Get
- Head
- Header
- Host
- Inspect
- JSONMarshaler
- Method
- Middleware
- MockDoer
- MockHandler
- Patch
- Post
- Put
- QueryParam
- QueryParams
- RelativeURL
- Request
- Requester.Clone
- Requester.Receive
- Requester.Request
- Requester.Send
- XMLMarshaler
Constants ¶
const ( // Authentication HeaderAuthorization = "Authorization" HeaderProxyAuthenticate = "Proxy-Authenticate" HeaderProxyAuthorization = "Proxy-Authorization" HeaderWWWAuthenticate = "WWW-Authenticate" BearerAuthHeader = "Bearer " BasicAuthHeader = "Basic " // Caching HeaderAge = "Age" HeaderCacheControl = "Cache-Control" HeaderClearSiteData = "Clear-Site-Data" HeaderExpires = "Expires" HeaderPragma = "Pragma" HeaderWarning = "Warning" // Client hints HeaderAcceptCH = "Accept-CH" HeaderAcceptCHLifetime = "Accept-CH-Lifetime" HeaderContentDPR = "Content-DPR" HeaderDPR = "DPR" HeaderEarlyData = "Early-Data" HeaderSaveData = "Save-Data" HeaderViewportWidth = "Viewport-Width" HeaderWidth = "Width" // Conditionals HeaderETag = "ETag" HeaderIfMatch = "If-Match" HeaderIfModifiedSince = "If-Modified-Since" HeaderIfNoneMatch = "If-None-Match" HeaderIfUnmodifiedSince = "If-Unmodified-Since" HeaderLastModified = "Last-Modified" HeaderVary = "Vary" // Connection management HeaderConnection = "Connection" HeaderKeepAlive = "Keep-Alive" HeaderProxyConnection = "Proxy-Connection" // Content negotiation HeaderAccept = "Accept" HeaderAcceptCharset = "Accept-Charset" HeaderAcceptEncoding = "Accept-Encoding" HeaderAcceptLanguage = "Accept-Language" // Controls HeaderCookie = "Cookie" HeaderExpect = "Expect" HeaderMaxForwards = "Max-Forwards" HeaderSetCookie = "Set-Cookie" // CORS HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials" HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers" HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods" HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin" HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers" HeaderAccessControlMaxAge = "Access-Control-Max-Age" HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers" HeaderAccessControlRequestMethod = "Access-Control-Request-Method" HeaderOrigin = "Origin" HeaderTimingAllowOrigin = "Timing-Allow-Origin" HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies" // Do Not Track HeaderDNT = "DNT" HeaderTk = "Tk" // Downloads HeaderContentDisposition = "Content-Disposition" // Message body information HeaderContentEncoding = "Content-Encoding" HeaderContentLanguage = "Content-Language" HeaderContentLength = "Content-Length" HeaderContentLocation = "Content-Location" HeaderContentType = "Content-Type" // Content Types ContentTypeForm = "application/x-www-form-urlencoded" // https://datatracker.ietf.org/doc/html/rfc1866 ContentTypeMultipart = "multipart/form-data" // https://datatracker.ietf.org/doc/html/rfc2388 ContentTypeJSON = "application/json" // https://datatracker.ietf.org/doc/html/rfc4627 ContentTypeJSONUTF8 = "application/json;charset=utf-8" // https://datatracker.ietf.org/doc/html/rfc4627 ContentTypeXML = "application/xml" // https://datatracker.ietf.org/doc/html/rfc3023 ContentTypeXMLUTF8 = "application/xml;charset=utf-8" ContentTypeYAML = "application/yaml" // https://www.rfc-editor.org/rfc/rfc9512.html ContentTypeYAMLUTF8 = "application/yaml;charset=utf-8" ContentTypeText = "text/plain" ContentTypeTextUTF8 = "text/plain;charset=utf-8" ContentTypeApplicationOctetStream = "application/octet-stream" // Proxies HeaderForwarded = "Forwarded" HeaderVia = "Via" HeaderXForwardedFor = "X-Forwarded-For" HeaderXForwardedHost = "X-Forwarded-Host" HeaderXForwardedProto = "X-Forwarded-Proto" // Redirects HeaderLocation = "Location" // Request context HeaderFrom = "From" HeaderHost = "Host" HeaderReferer = "Referer" HeaderReferrerPolicy = "Referrer-Policy" HeaderUserAgent = "User-Agent" // Response context HeaderAllow = "Allow" HeaderServer = "Server" // Range requests. HeaderAcceptRanges = "Accept-Ranges" HeaderContentRange = "Content-Range" HeaderIfRange = "If-Range" HeaderRange = "Range" // Security HeaderContentSecurityPolicy = "Content-Security-Policy" HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only" HeaderCrossOriginResourcePolicy = "Cross-Origin-Resource-Policy" HeaderExpectCT = "Expect-CT" HeaderFeaturePolicy = "Feature-Policy" HeaderPublicKeyPins = "Public-Key-Pins" HeaderPublicKeyPinsReportOnly = "Public-Key-Pins-Report-Only" HeaderStrictTransportSecurity = "Strict-Transport-Security" HeaderUpgradeInsecureRequests = "Upgrade-Insecure-Requests" HeaderXContentTypeOptions = "X-Content-Type-Options" HeaderXDownloadOptions = "X-Download-Options" HeaderXFrameOptions = "X-Frame-Options" HeaderXPoweredBy = "X-Powered-By" HeaderXXSSProtection = "X-XSS-Protection" // Server-sent event HeaderLastEventID = "Last-Event-ID" HeaderNEL = "NEL" HeaderPingFrom = "Ping-From" HeaderPingTo = "Ping-To" HeaderReportTo = "Report-To" // Transfer coding HeaderTE = "TE" HeaderTrailer = "Trailer" HeaderTransferEncoding = "Transfer-Encoding" // WebSockets HeaderSecWebSocketAccept = "Sec-WebSocket-Accept" HeaderSecWebSocketExtensions = "Sec-WebSocket-Extensions" /* #nosec G101 */ HeaderSecWebSocketKey = "Sec-WebSocket-Key" HeaderSecWebSocketProtocol = "Sec-WebSocket-Protocol" HeaderSecWebSocketVersion = "Sec-WebSocket-Version" // Other HeaderAcceptPatch = "Accept-Patch" HeaderAcceptPushPolicy = "Accept-Push-Policy" HeaderAcceptSignature = "Accept-Signature" HeaderAltSvc = "Alt-Svc" HeaderDate = "Date" HeaderIndex = "Index" HeaderLargeAllocation = "Large-Allocation" HeaderLink = "Link" HeaderPushPolicy = "Push-Policy" HeaderRetryAfter = "Retry-After" HeaderServerTiming = "Server-Timing" HeaderSignature = "Signature" HeaderSignedHeaders = "Signed-Headers" HeaderSourceMap = "SourceMap" HeaderUpgrade = "Upgrade" HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control" HeaderXPingback = "X-Pingback" HeaderXRequestedWith = "X-Requested-With" HeaderXRobotsTag = "X-Robots-Tag" HeaderXUACompatible = "X-UA-Compatible" )
Variables ¶
var ( // ErrUnsupportedContentType is returned when the content type is unsupported ErrUnsupportedContentType = errors.New("unsupported content type") // ErrUnsuccessfulResponse is returned when the response is unsuccessful ErrUnsuccessfulResponse = errors.New("unsuccessful response") // ErrNoFilesUploaded is returned when no files are found in a multipart form request ErrNoFilesUploaded = errors.New("no uploadable files found in request") // ErrUnsupportedMimeType is returned when the mime type is unsupported ErrUnsupportedMimeType = errors.New("unsupported mime type") )
var DefaultBackoff = ExponentialBackoff{ BaseDelay: 1.0 * time.Second, Multiplier: 1.6, Jitter: 0.2, MaxDelay: 120 * time.Second, }
DefaultBackoff is a backoff configuration with the default values
var DefaultRequester = Requester{}
var DefaultRetryConfig = RetryConfig{}
DefaultRetryConfig is the default retry configuration used if nil is passed to Retry()
Functions ¶
func ChannelHandler ¶ added in v0.2.0
ChannelHandler returns an http.Handler and an input channel
Example ¶
in, h := ChannelHandler() // nolint: bodyclose ts := httptest.NewServer(h) defer ts.Close() in <- &http.Response{ StatusCode: 201, Body: io.NopCloser(strings.NewReader("pong")), } var out string resp, _ := Receive(&out, URL(ts.URL)) defer resp.Body.Close() fmt.Println(resp.StatusCode) fmt.Println(out)
Output: 201 pong
func DefaultShouldRetry ¶ added in v0.2.0
DefaultShouldRetry is the default ShouldRetryer
func MockHandler ¶ added in v0.2.0
MockHandler returns an http.Handler which returns responses built from the args
Example ¶
h := MockHandler(201, JSON(false), Body(map[string]interface{}{"color": "blue"}), ) ts := httptest.NewServer(h) defer ts.Close() var out map[string]interface{} resp, _ := Receive(&out, URL(ts.URL)) defer resp.Body.Close() j, _ := json.Marshal(out) fmt.Println(resp.StatusCode) fmt.Println(resp.Header.Get(HeaderContentType)) fmt.Printf("%s", j)
Output: 201 application/json;charset=utf-8 {"color":"blue"}
func MockResponse ¶ added in v0.2.0
MockResponse creates an *http.Response from the Options
func OnlyIdempotentShouldRetry ¶ added in v0.2.0
OnlyIdempotentShouldRetry returns true if the request is using one of the HTTP methods which are intended to be idempotent: GET, HEAD, OPTIONS, and TRACE
func Receive ¶ added in v0.2.0
Receive uses the DefaultRequester to create a request, execute it, and read the response
func ReceiveWithContext ¶ added in v0.2.0
func ReceiveWithContext(ctx context.Context, into interface{}, opts ...Option) (*http.Response, error)
ReceiveWithContext does the same as Receive(), but attaches a Context to the request
func Request ¶ added in v0.2.0
Request uses the DefaultRequester to create a request
Example ¶
req, err := Request(Get("http://api.com/resource")) fmt.Println(req.URL.String(), err)
Output: http://api.com/resource <nil>
func RequestWithContext ¶ added in v0.2.0
RequestWithContext does the same as Request(), but attaches a Context to the request
Types ¶
type BackofferFunc ¶ added in v0.2.0
BackofferFunc adapts a function to the Backoffer interface
type ContentTypeUnmarshaler ¶ added in v0.2.0
type ContentTypeUnmarshaler struct {
Unmarshalers map[string]Unmarshaler
}
ContentTypeUnmarshaler selects an unmarshaler based on the content type
func NewContentTypeUnmarshaler ¶ added in v0.2.0
func NewContentTypeUnmarshaler() *ContentTypeUnmarshaler
NewContentTypeUnmarshaler returns a new ContentTypeUnmarshaler preconfigured to handle application/json and application/xml
func (*ContentTypeUnmarshaler) Apply ¶ added in v0.2.0
func (c *ContentTypeUnmarshaler) Apply(r *Requester) error
Apply implements Option
type Doer ¶ added in v0.2.0
Doer executes http requests
func Wrap ¶ added in v0.2.0
func Wrap(d Doer, m ...Middleware) Doer
Wrap applies a set of middleware to a Doer. The returned Doer will invoke the middleware in the order of the arguments.
type DoerFunc ¶ added in v0.2.0
DoerFunc adapts a function to implement Doer
func ChannelDoer ¶ added in v0.2.0
ChannelDoer returns a DoerFunc and a channel
Example ¶
in, d := ChannelDoer() // nolint: bodyclose in <- &http.Response{ StatusCode: 201, Body: io.NopCloser(strings.NewReader("pong")), Header: http.Header{HeaderContentType: []string{ContentTypeText}}, } var out string resp, _ := Receive(&out, d) defer resp.Body.Close() fmt.Println(resp.StatusCode) fmt.Printf("%s", out)
Output: 201 pong
func MockDoer ¶ added in v0.2.0
MockDoer creates a Doer which returns a mocked response, for writing tests
Example ¶
d := MockDoer(201, JSON(false), Body(map[string]interface{}{"color": "blue"}), ) // Since DoerFunc is an Option, it can be passed directly to functions // which accept Options. var out map[string]interface{} resp, _ := Receive(&out, d) defer resp.Body.Close() j, _ := json.Marshal(out) fmt.Println(resp.StatusCode) fmt.Println(resp.Header.Get(HeaderContentType)) fmt.Printf("%s", j)
Output: 201 application/json;charset=utf-8 {"color":"blue"}
type ErrResponseHandler ¶ added in v0.2.1
type ErrResponseHandler func(error) http.HandlerFunc
ErrResponseHandler is a custom error that should be used to handle errors when an upload fails
type ExponentialBackoff ¶ added in v0.2.0
type ExponentialBackoff struct { // BaseDelay is the amount of time to backoff after the first failure BaseDelay time.Duration // Multiplier is the factor with which to multiply backoffs after a failed retry Multiplier float64 // Jitter is the factor with which backoffs are randomized Jitter float64 // MaxDelay is the upper bound of backoff delay - 0 means no max MaxDelay time.Duration }
ExponentialBackoff defines the configuration options for an exponential backoff strategy
func ConstantBackoff ¶ added in v0.2.0
func ConstantBackoff(delay time.Duration) *ExponentialBackoff
ConstantBackoff returns a Backoffer with a fixed, constant delay between retries and no jitter
func ConstantBackoffWithJitter ¶ added in v0.2.0
func ConstantBackoffWithJitter(delay time.Duration) *ExponentialBackoff
ConstantBackoffWithJitter returns a Backoffer with a fixed, constant delay between retries with 20% jitter
func NoBackoff ¶ added in v0.2.0
func NoBackoff() *ExponentialBackoff
NoBackoff returns a Backoffer with zero backoff, and zero delay between retries
type File ¶
type File struct { // FieldName denotes the field from the multipart form FieldName string `json:"field_name,omitempty"` // OriginalName is he name of the file from the client side / which was sent in the request OriginalName string `json:"original_name,omitempty"` // MimeType of the uploaded file MimeType string `json:"mime_type,omitempty"` // Size in bytes of the uploaded file Size int64 `json:"size,omitempty"` }
File represents a file that has been sent in an http request
type FormMarshaler ¶ added in v0.2.0
type FormMarshaler struct{}
FormMarshaler implements Marshaler
Example ¶
req, _ := Request(&FormMarshaler{}, Body(url.Values{"color": []string{"red"}})) b, _ := io.ReadAll(req.Body) fmt.Println(string(b)) fmt.Println(req.Header.Get(HeaderContentType))
Output: color=red application/x-www-form-urlencoded
func (*FormMarshaler) Apply ¶ added in v0.2.0
func (m *FormMarshaler) Apply(r *Requester) error
Apply implements Option
type Inspector ¶ added in v0.2.0
type Inspector struct { // The last request sent by the client Request *http.Request // The last response received by the client Response *http.Response // The last client request body RequestBody *bytes.Buffer // The last client response body ResponseBody *bytes.Buffer }
Inspector is a Requester Option which captures requests and responses
func Inspect ¶ added in v0.2.0
Inspect installs and returns an Inspector
Example ¶
r := MustNew( MockDoer(201, Body("pong")), Header(HeaderAccept, ContentTypeText), Body("ping"), ) i := Inspect(r) resp, err := r.Receive(nil) if err != nil { fmt.Println(err) return } defer resp.Body.Close() fmt.Println(i.Request.Header.Get(HeaderAccept)) fmt.Println(i.RequestBody.String()) fmt.Println(i.Response.StatusCode) fmt.Println(i.ResponseBody.String())
Output:
type JSONMarshaler ¶ added in v0.2.0
type JSONMarshaler struct {
Indent bool
}
JSONMarshaler implement Marshaler and Unmarshaler
Example ¶
req, _ := Request(&JSONMarshaler{Indent: false}, Body(map[string]interface{}{"color": "red"})) b, _ := io.ReadAll(req.Body) fmt.Println(string(b)) fmt.Println(req.Header.Get(HeaderContentType))
Output: {"color":"red"} application/json;charset=utf-8
func (*JSONMarshaler) Apply ¶ added in v0.2.0
func (m *JSONMarshaler) Apply(r *Requester) error
Apply implements Option
type MarshalFunc ¶ added in v0.2.0
MarshalFunc adapts a function to the Marshaler interface
func (MarshalFunc) Apply ¶ added in v0.2.0
func (f MarshalFunc) Apply(r *Requester) error
Apply implements Option
type Marshaler ¶ added in v0.2.0
Marshaler marshals values into a []byte
var DefaultMarshaler Marshaler = &JSONMarshaler{}
type Middleware ¶
Middleware can be used to wrap Doers with additional functionality.
Example ¶
var m Middleware = func(next Doer) Doer { return DoerFunc(func(req *http.Request) (*http.Response, error) { d, _ := httputil.DumpRequest(req, true) fmt.Println(string(d)) return next.Do(req) }) } resp, err := Send(m) if err != nil { fmt.Println(err) } defer resp.Body.Close() resp, err = Send(Use(m)) if err != nil { fmt.Println(err) } defer resp.Body.Close() _ = Requester{ Middleware: []Middleware{m}, }
Output:
func Dump ¶ added in v0.2.0
func Dump(w io.Writer) Middleware
Dump dumps requests and responses to a writer. Just intended for debugging.
func DumpToLog ¶ added in v0.2.0
func DumpToLog(logf func(a ...interface{})) Middleware
DumpToLog dumps the request and response to a logging function. logf is compatible with fmt.Print(), testing.T.Log, or log.XXX() functions.
logf will be invoked once for the request, and once for the response. Each invocation will only have a single argument (the entire request or response is logged as a single string value).
Example ¶
resp, err := Send(DumpToLog(func(a ...interface{}) { fmt.Println(a...) })) if err != nil { fmt.Println(err) } defer resp.Body.Close() resp, err = Send(DumpToLog(sdklog.Println)) if err != nil { fmt.Println(err) } defer resp.Body.Close() var t *testing.T resp, err = Send(DumpToLog(t.Log)) if err != nil { fmt.Println(err) } defer resp.Body.Close()
Output:
func DumpToStderr ¶ added in v0.2.0
func DumpToStderr() Middleware
DumpToStderr dumps requests and responses to os.Stderr
func DumpToStout ¶ added in v0.2.0
func DumpToStout() Middleware
DumpToStout dumps requests and responses to os.Stdout
func ExpectCode ¶ added in v0.2.0
func ExpectCode(code int) Middleware
ExpectCode generates an error if the response's status code does not match the expected code.
The response body will still be read and returned.
Example ¶
resp, err := Receive( MockDoer(400), ExpectCode(201), ) fmt.Println(err.Error()) defer resp.Body.Close()
Output:
func ExpectSuccessCode ¶ added in v0.2.0
func ExpectSuccessCode() Middleware
ExpectSuccessCode is middleware which generates an error if the response's status code is not between 200 and 299.
The response body will still be read and returned.
Example ¶
resp, err := Receive( MockDoer(400), ExpectSuccessCode(), ) fmt.Println(err.Error()) defer resp.Body.Close()
Output:
func Retry ¶ added in v0.2.0
func Retry(config *RetryConfig) Middleware
Retry retries the http request under certain conditions - the number of retries, retry conditions, and the time to sleep between retries can be configured
func (Middleware) Apply ¶ added in v0.2.0
func (m Middleware) Apply(r *Requester) error
Apply implements Option
type NameGeneratorFunc ¶ added in v0.2.1
NameGeneratorFunc allows you alter the name of the file before it is ultimately uploaded and stored
type Option ¶ added in v0.2.0
Option applies some setting to a Requester object
func Accept ¶ added in v0.2.0
Accept sets the Accept header
Example ¶
r := MustNew(Accept(ContentTypeJSON)) fmt.Println(r.Headers().Get(HeaderAccept))
Output: application/json
func AddHeader ¶ added in v0.2.0
AddHeader adds a header value, using Header.Add()
Example ¶
r := MustNew( AddHeader("color", "red"), AddHeader("color", "blue"), ) fmt.Println(r.Headers()["Color"])
Output: [red blue]
func AppendPath ¶ added in v0.2.0
AppendPath appends path elements to the end of the URL.Path
Example ¶
r := MustNew(URL("http://test.com/users/bob")) fmt.Println("RelativeURL: " + r.MustWith(RelativeURL("frank")).URL.String()) fmt.Println("AppendPath: " + r.MustWith(AppendPath("frank")).URL.String()) fmt.Println("RelativeURL: " + r.MustWith(RelativeURL("/frank")).URL.String()) fmt.Println("AppendPath: " + r.MustWith(AppendPath("/frank")).URL.String()) fmt.Println("RelativeURL: " + r.MustWith(RelativeURL("frank", "nicknames")).URL.String()) fmt.Println("AppendPath: " + r.MustWith(AppendPath("frank", "nicknames")).URL.String())
Output: RelativeURL: http://test.com/users/frank AppendPath: http://test.com/users/bob/frank RelativeURL: http://test.com/frank AppendPath: http://test.com/users/bob/frank RelativeURL: http://test.com/users/nicknames AppendPath: http://test.com/users/bob/frank/nicknames
func BasicAuth ¶
BasicAuth sets the Authorization header to "Basic <encoded username and password>"
Example ¶
r := MustNew(BasicAuth("user", "password")) fmt.Println(r.Header.Get(HeaderAuthorization))
Output: Basic dXNlcjpwYXNzd29yZA==
func BearerAuth ¶
BearerAuth sets the Authorization header to "Bearer <token>"
Example ¶
r := MustNew(BearerAuth("1234")) fmt.Println(r.Header.Get(HeaderAuthorization))
Output: Bearer 1234
func Body ¶ added in v0.2.0
func Body(body interface{}) Option
Body sets the body of the request
Example ¶
v := struct { Color string `json:"color"` }{ Color: "red", } req, _ := Request(Body(v)) b, _ := io.ReadAll(req.Body) fmt.Println(string(b))
Output: {"color":"red"}
Example (Map) ¶
req, _ := Request(Body(map[string]interface{}{"color": "red"})) b, _ := io.ReadAll(req.Body) fmt.Println(string(b))
Output: {"color":"red"}
Example (Raw) ¶
req, _ := Request( Body("red"), Body([]byte("red")), Body(strings.NewReader("red")), ) b, _ := io.ReadAll(req.Body) fmt.Println(string(b))
Output: red
func Client ¶
func Client(opts ...httpclient.Option) Option
Client replaces Requester.Doer with an *http.Client
Example ¶
nolint: errcheck
Send( // nolint: bodyclose URL("https://localhost:6060"), Client(httpclient.SkipVerify(true)), )
Output:
func ContentType ¶ added in v0.2.0
ContentType sets the Content-Type header
Example ¶
r := MustNew(ContentType(ContentTypeText)) fmt.Println(r.Headers().Get(HeaderContentType))
Output: text/plain
func Delete ¶ added in v0.2.0
Delete sets the HTTP method to "DELETE"
Example ¶
r := MustNew(Delete("/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: DELETE /resources/1
func DeleteHeader ¶ added in v0.2.0
DeleteHeader deletes a header key, using Header.Del()
Example ¶
r := Requester{ Header: http.Header{ "Color": []string{"red"}, "Flavor": []string{"vanilla"}, }, } r.MustApply(DeleteHeader("color")) fmt.Println(r.Header)
Output: map[Flavor:[vanilla]]
func Form ¶ added in v0.2.0
func Form() Option
Form sets Requester.Marshaler to the FormMarshaler which marshals the body into form-urlencoded
func Get ¶ added in v0.2.0
Get sets the HTTP method to "GET"
Example ¶
r := MustNew(Get("/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: GET /resources/1
func Head ¶ added in v0.2.0
Head sets the HTTP method to "HEAD"
Example ¶
r := MustNew(Head("/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: HEAD /resources/1
func Header ¶ added in v0.2.0
Header sets a header value, using Header.Set()
Example ¶
r := MustNew(Header("color", "red")) fmt.Println(r.Header)
Output: map[Color:[red]]
func Host ¶ added in v0.2.0
Host sets Requester.Host
Example ¶
r, _ := Request(Host("api.com")) fmt.Println(r.Host)
Output: api.com
func Method ¶ added in v0.2.0
Method sets the HTTP method
Example ¶
r := MustNew(Method("CONNECT", "/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: CONNECT /resources/1
func Patch ¶ added in v0.2.0
Patch sets the HTTP method to "PATCH"
Example ¶
r := MustNew(Patch("/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: PATCH /resources/1
func Post ¶ added in v0.2.0
Post sets the HTTP method to "POST"
Example ¶
r := MustNew(Post("/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: POST /resources/1
func Put ¶ added in v0.2.0
Put sets the HTTP method to "PUT"
Example ¶
r := MustNew(Put("/resources/", "1")) fmt.Println(r.Method, r.URL.String())
Output: PUT /resources/1
func QueryParam ¶ added in v0.2.0
QueryParam adds a query parameter
Example ¶
r := MustNew(QueryParam("color", "red")) fmt.Println(r.Params().Encode())
Output: color=red
func QueryParams ¶ added in v0.2.0
func QueryParams(queryStructs ...interface{}) Option
QueryParams adds params to the Requester.QueryParams member
Example ¶
type Params struct { Color string `url:"color"` } r := MustNew(QueryParams( Params{Color: "red"}, // struct with url tags map[string]string{"flavor": "vanilla"}, // map[string]string map[string][]string{"size": {"big"}}, // map[string][]string url.Values{"volume": []string{"loud"}}, // url.Values )) req, _ := r.Request(RelativeURL("?weight=heavy")) fmt.Println(req.URL.RawQuery)
Output: color=red&flavor=vanilla&size=big&volume=loud&weight=heavy
func RelativeURL ¶ added in v0.2.0
RelativeURL resolves the arg as a relative URL references against the current URL, using the standard lib's url.URL.ResolveReference() method
Example ¶
r := MustNew( Get("http://test.com/green/"), RelativeURL("red/", "blue"), ) fmt.Println(r.URL.String())
Output: http://test.com/green/red/blue
func Use ¶ added in v0.2.0
func Use(m ...Middleware) Option
Use appends middleware to Requester.Middleware
func WithFileErrorResponseHandler ¶ added in v0.2.1
func WithFileErrorResponseHandler(errHandler ErrResponseHandler) Option
WithFileErrorResponseHandler allows you to configure how you'd like to handle errors when a file upload fails either to your own server or the destination server or both
func WithMarshaler ¶ added in v0.2.0
WithMarshaler sets Requester.WithMarshaler
func WithMaxFileSize ¶ added in v0.2.1
WithMaxFileSize sets the maximum file size for file uploads
func WithNameFuncGenerator ¶ added in v0.2.1
func WithNameFuncGenerator(nameFunc NameGeneratorFunc) Option
WithNameFuncGenerator allows you configure how you'd like to rename your uploaded files
func WithUnmarshaler ¶ added in v0.2.0
func WithUnmarshaler(m Unmarshaler) Option
WithUnmarshaler sets Requester.WithUnmarshaler
func WithValidationFunc ¶ added in v0.2.1
func WithValidationFunc(validationFunc ValidationFunc) Option
WithValidationFunc allows you to set a function that can be used to perform validations
type OptionFunc ¶ added in v0.2.0
OptionFunc adapts a function to the Option interface
func (OptionFunc) Apply ¶ added in v0.2.0
func (f OptionFunc) Apply(r *Requester) error
Apply implements Option
type Requester ¶ added in v0.2.0
type Requester struct { // Method is the HTTP method to use for the request Method string // URL is the URL to request URL *url.URL // Header supplies the request headers; if the Content-Type header is set here, it will override the Content-Type header supplied by the Marshaler Header http.Header // GetBody is a function that returns a ReadCloser for the request body GetBody func() (io.ReadCloser, error) // ContentLength is the length of the request body ContentLength int64 // TransferEncoding is the transfer encoding for the request body TransferEncoding []string // Close indicates whether the connection should be closed after the request Close bool // Host is the host to use for the request Host string // Trailer is the trailer for the request Trailer http.Header // QueryParams are added to the request, in addition to any query params already encoded in the URL QueryParams url.Values // Body can be set to a string, []byte, io.Reader, or a struct; if set to a string, []byte, or io.Reader, the value will be used as the body of the request // If set to a struct, the Marshaler will be used to marshal the value into the request body Body interface{} // Marshaler will be used to marshal the Body value into the body of the request. Marshaler Marshaler // Doer holds the HTTP client for used to execute httpsling Doer Doer // Middleware wraps the Doer Middleware []Middleware // Unmarshaler will be used by the Receive methods to unmarshal the response body Unmarshaler Unmarshaler // MaxFileSize is the maximum size of a file to download MaxFileSize int64 // contains filtered or unexported fields }
Requester is a struct that contains the information needed to make an HTTP request
func (*Requester) Clone ¶ added in v0.2.0
Clone returns a deep copy of a Requester
Example ¶
base, _ := New(Get("https://api.io/")) foo := base.Clone() if err := foo.Apply(Get("foo/")); err != nil { fmt.Println(err) } bar := base.Clone() if err := bar.Apply(Get("bar/")); err != nil { fmt.Println(err) }
Output:
func (*Requester) CookieJar ¶ added in v0.2.0
CookieJar returns the CookieJar used by the Requester, if it exists
func (*Requester) HTTPClient ¶ added in v0.2.0
HTTPClient returns the HTTP client used by the Requester
func (*Requester) MustWith ¶ added in v0.2.0
MustWith clones the Requester, then applies the options to the clone
func (*Requester) Receive ¶ added in v0.2.0
Receive creates a new HTTP request and returns the response
Example ¶
r := MustNew(MockDoer(200, Body("red"), Header(HeaderContentType, ContentTypeText), )) var out string resp, _ := r.Receive(&out, Get("http://api.com/resource")) defer resp.Body.Close() fmt.Println(resp.StatusCode) fmt.Println(out)
Output: 200 red
func (*Requester) ReceiveWithContext ¶ added in v0.2.0
func (r *Requester) ReceiveWithContext(ctx context.Context, into interface{}, opts ...Option) (resp *http.Response, err error)
ReceiveWithContext does the same as Receive, but requires a context
func (*Requester) Request ¶ added in v0.2.0
Request returns a new http.Request
Example ¶
r := MustNew( Get("http://api.com/resource"), Header("X-Color", "red"), QueryParam("flavor", "vanilla"), ) req, _ := r.Request( JSON(true), Body(map[string]interface{}{"size": "big"}), ) fmt.Printf("%s %s %s\n", req.Method, req.URL.String(), req.Proto) fmt.Println(HeaderContentType+":", req.Header.Get(HeaderContentType)) fmt.Println(HeaderAccept+":", req.Header.Get(HeaderAccept)) fmt.Println("X-Color:", req.Header.Get("X-Color")) if _, err := io.Copy(os.Stdout, req.Body); err != nil { fmt.Println(err) }
Output: GET http://api.com/resource?flavor=vanilla HTTP/1.1 Content-Type: application/json;charset=utf-8 Accept: application/json X-Color: red { "size": "big" }
func (*Requester) RequestWithContext ¶ added in v0.2.0
RequestWithContext does the same as Request, but requires a context
func (*Requester) Send ¶ added in v0.2.0
Send executes a request with the Doer
Example ¶
r := MustNew(MockDoer(204)) resp, _ := r.Send(Get("resources/1")) defer resp.Body.Close() fmt.Println(resp.StatusCode)
Output: 204
func (*Requester) SendWithContext ¶ added in v0.2.0
SendWithContext does the same as Send, but requires a context
type RetryConfig ¶
type RetryConfig struct { // MaxAttempts is the number of times to attempt the request (default 3) MaxAttempts int // ShouldRetry tests whether a response should be retried ShouldRetry ShouldRetryer // Backoff returns how long to wait between retries Backoff Backoffer // ReadResponse will ensure the entire response is read before considering the request a success ReadResponse bool }
RetryConfig defines settings for the Retry middleware
type ShouldRetryer ¶ added in v0.2.0
type ShouldRetryer interface {
ShouldRetry(attempt int, req *http.Request, resp *http.Response, err error) bool
}
ShouldRetryer evaluates whether an HTTP request should be retried
func AllRetryers ¶ added in v0.2.0
func AllRetryers(s ...ShouldRetryer) ShouldRetryer
AllRetryers returns a ShouldRetryer which returns true only if all the supplied retryers return true
type ShouldRetryerFunc ¶ added in v0.2.0
ShouldRetryerFunc adapts a function to the ShouldRetryer interface
func (ShouldRetryerFunc) ShouldRetry ¶ added in v0.2.0
func (s ShouldRetryerFunc) ShouldRetry(attempt int, req *http.Request, resp *http.Response, err error) bool
ShouldRetry implements ShouldRetryer
type TextUnmarshaler ¶ added in v0.2.0
type TextUnmarshaler struct {
Indent bool
}
TextUnmarshaler implements Marshaler and Unmarshaler
func (*TextUnmarshaler) Apply ¶ added in v0.2.0
func (m *TextUnmarshaler) Apply(r *Requester) error
Apply implements Option
type UnmarshalFunc ¶ added in v0.2.0
UnmarshalFunc adapts a function to the Unmarshaler interface
func (UnmarshalFunc) Apply ¶ added in v0.2.0
func (f UnmarshalFunc) Apply(r *Requester) error
Apply implements Option
type Unmarshaler ¶ added in v0.2.0
Unmarshaler unmarshals a []byte response body into a value
var DefaultUnmarshaler Unmarshaler = NewContentTypeUnmarshaler()
type ValidationFunc ¶ added in v0.2.1
ValidationFunc is a type that can be used to dynamically validate a file
func ChainValidators ¶ added in v0.2.1
func ChainValidators(validators ...ValidationFunc) ValidationFunc
ChainValidators returns a validator that accepts multiple validating criteras
func MimeTypeValidator ¶ added in v0.2.1
func MimeTypeValidator(validMimeTypes ...string) ValidationFunc
MimeTypeValidator makes sure we only accept a valid mimetype. It takes in an array of supported mimes
type XMLMarshaler ¶ added in v0.2.0
type XMLMarshaler struct {
Indent bool
}
XMLMarshaler implements Marshaler and Unmarshaler
Example ¶
type Resource struct { Color string } req, _ := Request(&XMLMarshaler{Indent: false}, Body(Resource{Color: "red"})) b, _ := io.ReadAll(req.Body) fmt.Println(string(b)) fmt.Println(req.Header.Get(HeaderContentType))
Output: <Resource><Color>red</Color></Resource> application/xml;charset=utf-8
func (*XMLMarshaler) Apply ¶ added in v0.2.0
func (m *XMLMarshaler) Apply(r *Requester) error
Apply implements Option
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package httpclient is a set of utilities for creating and configuring instances of http.Client
|
Package httpclient is a set of utilities for creating and configuring instances of http.Client |
Package httptestutil contains utilities for use in HTTP tests, particular when using httptest.Server
|
Package httptestutil contains utilities for use in HTTP tests, particular when using httptest.Server |