httpsling

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2024 License: Apache-2.0 Imports: 24 Imported by: 2

README

Build status Quality Gate Status Go Report Card Go Reference

Slinging HTTP

The httpsling library simplifies the way you make HTTP requests. It's intended to provide an easy-to-use interface for sending requests and handling responses, reducing the boilerplate code typically associated with the net/http package.

Overview

Creating a new Requester and making a request should be straightforward:

package main

import (
	"log"
	"net/http"

	"github.com/theopenlane/httpsling"
)

func main() {
	requester, err := httpsling.New(
		httpsling.Client(), // use the default sling client
		httpsling.URL("https://api.example.com"),
	)
	if err != nil {
		log.Fatal(err)
	}

	// Perform a GET request
	var out map[string]interface{}
	resp, err := requester.Receive(&out, httpsling.Get("resource"))
	if err != nil {
		log.Fatal(err)
	}

	defer resp.Body.Close()

	log.Println(out)
}
Core Functions
// build just the request
Request(...Option) (*http.Request, error)
RequestWithContext(context.Context, ...Option) (*http.Request, error)

// build the request and send the request
Send(...Option) (*http.Response, error)
SendWithContext(context.Context, ...Option) (*http.Response, error)

// build and send the request and parse the response into an interface
Receive(interface{}, ...Option) (*http.Response, []byte, error)
ReceiveWithContext(context.Context, interface{}, ...Option) (*http.Response, error)
Configuring BaseURL

Set the base URL for all requests using the Requester option URL:

 httpsling.URL("https://api.example.com"),
Setting Headers

Set default headers for all requests, e.g. Bearer token Authorization

    requester.Apply(httpsling.BearerAuth("YOUR_ACCESS_TOKEN"))
Setting up CookieJar

Add a Cookie Jar to the default client:

    requester, err = httpsling.New(
        httpsling.Client(
            httpclient.CookieJar(nil), // Use a cookie jar to store cookies
        ),
    )
    if err != nil {
        return nil, err
    }
Configuring Timeouts

Define a global timeout for all requests to prevent indefinitely hanging operations:

    httpsling.Client(
        httpclient.Timeout(time.Duration(30*time.Second)),
    ),
TLS Configuration

Custom TLS configurations can be applied for enhanced security measures, such as loading custom certificates:

    httpsling.Client(
        httpclient.SkipVerify(true),
    ),

Requests

The library provides a Receive to construct and dispatch HTTP. Here are examples of performing various types of requests, including adding query parameters, setting headers, and attaching a body to your requests.

GET Request
    resp, err := requester.ReceiveWithContext(context.Background(), &out,
        httpsling.Get("/path"),
        httpsling.QueryParam("query", "meow"),
    )
POST Request
    resp, err := requester.ReceiveWithContext(context.Background(), &out,
        httpsling.Post("/path"),
        httpsling.Body(map[string]interface{}{"key": "value"})
    )
PUT Request
    resp, err := requester.ReceiveWithContext(context.Background(), &out,
        httpsling.Put("/path/123456"),
        httpsling.Body(map[string]interface{}{"key": "newValue"})
    )
DELETE Request
    resp, err := requester.ReceiveWithContext(context.Background(), &out,
        httpsling.Delete("/path/123456"),
    )
Authentication

Supports various authentication methods:

  • Basic Auth:
    requester.Apply(httpsling.BasicAuth("username", "superSecurePassword!"))
  • Bearer Token:
    requester.Apply(httpsling.BearerAuth("YOUR_ACCESS_TOKEN"))

Responses

Handling responses is necessary in determining the outcome of your HTTP requests - the library has some built-in response code validators and other tasty things.

type APIResponse struct {
    Data string `json:"data"`
}

var out APIResponse
resp, err := s.Requester.ReceiveWithContext(ctx, &out,
		httpsling.Post("/path"),
		httpsling.Body(in))

defer resp.Body.Close()

log.Printf("Status Code: %d\n", resp.StatusCode)
log.Printf("Response Data: %s\n", out.Data)
Evaluating Response Success

To assess whether the HTTP request was successful:

  • IsSuccess: Check if the status code signifies a successful response
    if httpsling.IsSuccess(resp) {
        fmt.Println("The request succeeded hot diggity dog")
    }

Inspirations

This library was inspired by and built upon the work of several other HTTP client libraries:

Contributing

See contributing for details.

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

Examples

Constants

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

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

View Source
var DefaultRequester = Requester{}
View Source
var DefaultRetryConfig = RetryConfig{}

DefaultRetryConfig is the default retry configuration used if nil is passed to Retry()

Functions

func ChannelHandler added in v0.2.0

func ChannelHandler() (chan<- *http.Response, http.Handler)

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

func DefaultShouldRetry(_ int, _ *http.Request, resp *http.Response, err error) bool

DefaultShouldRetry is the default ShouldRetryer

func IsSuccess added in v0.2.0

func IsSuccess(resp *http.Response) bool

IsSuccess checks if the response status code indicates success

func MockHandler added in v0.2.0

func MockHandler(statusCode int, options ...Option) http.Handler

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

func MockResponse(statusCode int, options ...Option) *http.Response

MockResponse creates an *http.Response from the Options

func OnlyIdempotentShouldRetry added in v0.2.0

func OnlyIdempotentShouldRetry(_ int, req *http.Request, _ *http.Response, _ error) bool

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

func Receive(into interface{}, opts ...Option) (*http.Response, error)

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

func Request(opts ...Option) (*http.Request, error)

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

func RequestWithContext(ctx context.Context, opts ...Option) (*http.Request, error)

RequestWithContext does the same as Request(), but attaches a Context to the request

func Send added in v0.2.0

func Send(opts ...Option) (*http.Response, error)

Send uses the DefaultRequester to create a request and execute it

func SendWithContext added in v0.2.0

func SendWithContext(ctx context.Context, opts ...Option) (*http.Response, error)

SendWithContext does the same as Send(), but attaches a Context to the request

Types

type Backoffer added in v0.2.0

type Backoffer interface {
	Backoff(attempt int) time.Duration
}

Backoffer calculates how long to wait between attempts

type BackofferFunc added in v0.2.0

type BackofferFunc func(int) time.Duration

BackofferFunc adapts a function to the Backoffer interface

func (BackofferFunc) Backoff added in v0.2.0

func (b BackofferFunc) Backoff(attempt int) time.Duration

Backoff implements Backoffer

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

func (*ContentTypeUnmarshaler) Unmarshal added in v0.2.0

func (c *ContentTypeUnmarshaler) Unmarshal(data []byte, contentType string, v interface{}) error

Unmarshal implements Unmarshaler

type Doer added in v0.2.0

type Doer interface {
	Do(req *http.Request) (*http.Response, error)
}

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

type DoerFunc func(req *http.Request) (*http.Response, error)

DoerFunc adapts a function to implement Doer

func ChannelDoer added in v0.2.0

func ChannelDoer() (chan<- *http.Response, DoerFunc)

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

func MockDoer(statusCode int, options ...Option) DoerFunc

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"}

func (DoerFunc) Apply added in v0.2.0

func (f DoerFunc) Apply(r *Requester) error

Apply implements the Option interface

func (DoerFunc) Do added in v0.2.0

func (f DoerFunc) Do(req *http.Request) (*http.Response, error)

Do implements the Doer interface

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

func (*ExponentialBackoff) Backoff added in v0.2.0

func (c *ExponentialBackoff) Backoff(attempt int) time.Duration

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

func FilesFromContextWithKey added in v0.2.1

func FilesFromContextWithKey(r *http.Request, key string) ([]File, error)

FilesFromContextWithKey returns all files that have been uploaded during the request and sorts by the provided form field

type Files added in v0.2.1

type Files map[string][]File

Files is a map of form field names to a slice of files

func FilesFromContext added in v0.2.1

func FilesFromContext(r *http.Request, key string) (Files, error)

FilesFromContext returns all files that have been uploaded during the 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

func (*FormMarshaler) Marshal added in v0.2.0

func (*FormMarshaler) Marshal(v interface{}) (data []byte, contentType string, err error)

Marshal implements Marshaler

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

func Inspect(r *Requester) *Inspector

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:

func (*Inspector) Apply added in v0.2.0

func (i *Inspector) Apply(r *Requester) error

Apply implements Option

func (*Inspector) Clear added in v0.2.0

func (i *Inspector) Clear()

Clear clears the inspector's fields

func (*Inspector) Wrap added in v0.2.0

func (i *Inspector) Wrap(next Doer) Doer

Wrap implements Middleware

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

func (*JSONMarshaler) Marshal added in v0.2.0

func (m *JSONMarshaler) Marshal(v interface{}) (data []byte, contentType string, err error)

Marshal implements Marshaler

func (*JSONMarshaler) Unmarshal added in v0.2.0

func (m *JSONMarshaler) Unmarshal(data []byte, _ string, v interface{}) error

Unmarshal implements Unmarshaler

type MarshalFunc added in v0.2.0

type MarshalFunc func(v interface{}) ([]byte, string, error)

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

func (MarshalFunc) Marshal added in v0.2.0

func (f MarshalFunc) Marshal(v interface{}) ([]byte, string, error)

Marshal implements the Marshaler interface

type Marshaler added in v0.2.0

type Marshaler interface {
	Marshal(v interface{}) (data []byte, contentType string, err error)
}

Marshaler marshals values into a []byte

var DefaultMarshaler Marshaler = &JSONMarshaler{}

type Middleware

type Middleware func(Doer) Doer

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

type NameGeneratorFunc func(s string) string

NameGeneratorFunc allows you alter the name of the file before it is ultimately uploaded and stored

type Option added in v0.2.0

type Option interface {
	Apply(*Requester) error
}

Option applies some setting to a Requester object

func Accept added in v0.2.0

func Accept(accept string) Option

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

func AddHeader(key, value string) Option

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

func AppendPath(elements ...string) Option

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

func BasicAuth(username, password string) Option

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

func BearerAuth(token string) Option

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

func ContentType(contentType string) Option

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

func Delete(paths ...string) Option

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

func DeleteHeader(key string) Option

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

func Get(paths ...string) Option

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(paths ...string) Option

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(key, value string) Option

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

func Host(host string) Option

Host sets Requester.Host

Example
r, _ := Request(Host("api.com"))

fmt.Println(r.Host)
Output:

api.com

func JSON added in v0.2.0

func JSON(indent bool) Option

JSON sets Requester.Marshaler to the JSONMarshaler

func Method added in v0.2.0

func Method(m string, paths ...string) Option

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

func Patch(paths ...string) Option

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

func Post(paths ...string) Option

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

func Put(paths ...string) Option

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

func QueryParam(k, v string) Option

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 Range added in v0.2.0

func Range(byteRange string) Option

Range sets the Range header

func RelativeURL added in v0.2.0

func RelativeURL(paths ...string) Option

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 URL

func URL(rawurl string) Option

URL sets the request URL

func Use added in v0.2.0

func Use(m ...Middleware) Option

Use appends middleware to Requester.Middleware

func WithDoer added in v0.2.0

func WithDoer(d Doer) Option

WithDoer replaces Requester.Doer

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

func WithMarshaler(m Marshaler) Option

WithMarshaler sets Requester.WithMarshaler

func WithMaxFileSize added in v0.2.1

func WithMaxFileSize(i int64) Option

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

func XML added in v0.2.0

func XML(indent bool) Option

XML sets Requester.Marshaler to the XMLMarshaler

type OptionFunc added in v0.2.0

type OptionFunc func(*Requester) error

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 MustNew added in v0.2.0

func MustNew(options ...Option) *Requester

MustNew creates a new Requester, applying all options

func New added in v0.2.0

func New(options ...Option) (*Requester, error)

New returns a new Requester, applying all options

func (*Requester) Apply added in v0.2.0

func (r *Requester) Apply(opts ...Option) error

Apply applies the options to the receiver

func (*Requester) Clone added in v0.2.0

func (r *Requester) Clone() *Requester

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

func (r *Requester) CookieJar() http.CookieJar

CookieJar returns the CookieJar used by the Requester, if it exists

func (*Requester) Do added in v0.2.0

func (r *Requester) Do(req *http.Request) (*http.Response, error)

Do implements Doer

func (*Requester) HTTPClient added in v0.2.0

func (r *Requester) HTTPClient() *http.Client

HTTPClient returns the HTTP client used by the Requester

func (*Requester) Headers added in v0.2.0

func (r *Requester) Headers() http.Header

Headers returns the Header

func (*Requester) MustApply added in v0.2.0

func (r *Requester) MustApply(opts ...Option)

MustApply applies the options to the receiver

func (*Requester) MustWith added in v0.2.0

func (r *Requester) MustWith(opts ...Option) *Requester

MustWith clones the Requester, then applies the options to the clone

func (*Requester) Params added in v0.2.0

func (r *Requester) Params() url.Values

Params returns the QueryParams

func (*Requester) Receive added in v0.2.0

func (r *Requester) Receive(into interface{}, opts ...Option) (resp *http.Response, err error)

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

func (r *Requester) Request(opts ...Option) (*http.Request, error)

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

func (r *Requester) RequestWithContext(ctx context.Context, opts ...Option) (*http.Request, error)

RequestWithContext does the same as Request, but requires a context

func (*Requester) Send added in v0.2.0

func (r *Requester) Send(opts ...Option) (*http.Response, error)

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

func (r *Requester) SendWithContext(ctx context.Context, opts ...Option) (*http.Response, error)

SendWithContext does the same as Send, but requires a context

func (*Requester) Trailers added in v0.2.0

func (r *Requester) Trailers() http.Header

Trailers returns the Trailer, initializing it if necessary

func (*Requester) With added in v0.2.0

func (r *Requester) With(opts ...Option) (*Requester, error)

With clones the Requester, then applies the options to the clone

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

type ShouldRetryerFunc func(attempt int, req *http.Request, resp *http.Response, err error) bool

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

func (*TextUnmarshaler) Marshal added in v0.2.0

func (m *TextUnmarshaler) Marshal(v interface{}) (data []byte, contentType string, err error)

Marshal implements Marshaler

func (*TextUnmarshaler) Unmarshal added in v0.2.0

func (*TextUnmarshaler) Unmarshal(data []byte, _ string, v interface{}) error

Unmarshal implements Unmarshaler

type UnmarshalFunc added in v0.2.0

type UnmarshalFunc func(data []byte, contentType string, v interface{}) error

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

func (UnmarshalFunc) Unmarshal added in v0.2.0

func (f UnmarshalFunc) Unmarshal(data []byte, contentType string, v interface{}) error

Unmarshal implements the Unmarshaler interface

type Unmarshaler added in v0.2.0

type Unmarshaler interface {
	Unmarshal(data []byte, contentType string, v interface{}) error
}

Unmarshaler unmarshals a []byte response body into a value

var DefaultUnmarshaler Unmarshaler = NewContentTypeUnmarshaler()

type ValidationFunc added in v0.2.1

type ValidationFunc func(f File) error

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

func (*XMLMarshaler) Marshal added in v0.2.0

func (m *XMLMarshaler) Marshal(v interface{}) (data []byte, contentType string, err error)

Marshal implements Marshaler

func (*XMLMarshaler) Unmarshal added in v0.2.0

func (*XMLMarshaler) Unmarshal(data []byte, _ string, v interface{}) error

Unmarshal implements Unmarshaler

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

Jump to

Keyboard shortcuts

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