autorest

package
v7.2.3+incompatible Latest Latest
Warning

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

Go to latest
Published: Jan 17, 2017 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/) generated Go code.

The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending, and Responding. A typical pattern is:

req, err := Prepare(&http.Request{},
  token.WithAuthorization())

resp, err := Send(req,
  WithLogging(logger),
  DoErrorIfStatusCode(http.StatusInternalServerError),
  DoCloseIfError(),
  DoRetryForAttempts(5, time.Second))

err = Respond(resp,
  ByClosing())

Each phase relies on decorators to modify and / or manage processing. Decorators may first modify and then pass the data along, pass the data first and then modify the result, or wrap themselves around passing the data (such as a logger might do). Decorators run in the order provided. For example, the following:

req, err := Prepare(&http.Request{},
  WithBaseURL("https://microsoft.com/"),
  WithPath("a"),
  WithPath("b"),
  WithPath("c"))

will set the URL to:

https://microsoft.com/a/b/c

Preparers and Responders may be shared and re-used (assuming the underlying decorators support sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders shared among multiple go-routines, and a single Sender shared among multiple sending go-routines, all bound together by means of input / output channels.

Decorators hold their passed state within a closure (such as the path components in the example above). Be careful to share Preparers and Responders only in a context where such held state applies. For example, it may not make sense to share a Preparer that applies a query string from a fixed set of values. Similarly, sharing a Responder that reads the response body into a passed struct (e.g., ByUnmarshallingJson) is likely incorrect.

Lastly, the Swagger specification (https://swagger.io) that drives AutoRest (https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure correct parsing and formatting.

Errors raised by autorest objects and methods will conform to the autorest.Error interface.

See the included examples for more detail. For details on the suggested use of this package by generated clients, see the Client described below.

Index

Examples

Constants

View Source
const (
	// HeaderLocation specifies the HTTP Location header.
	HeaderLocation = "Location"

	// HeaderRetryAfter specifies the HTTP Retry-After header.
	HeaderRetryAfter = "Retry-After"
)
View Source
const (
	// DefaultPollingDelay is a reasonable delay between polling requests.
	DefaultPollingDelay = 60 * time.Second

	// DefaultPollingDuration is a reasonable total polling duration.
	DefaultPollingDuration = 15 * time.Minute

	// DefaultRetryAttempts is number of attempts for retry status codes (5xx).
	DefaultRetryAttempts = 3
)
View Source
const (
	// UndefinedStatusCode is used when HTTP status code is not available for an error.
	UndefinedStatusCode = 0
)

Variables

This section is empty.

Functions

func CopyAndDecode

func CopyAndDecode(encodedAs EncodedAs, r io.Reader, v interface{}) (bytes.Buffer, error)

CopyAndDecode decodes the data from the passed io.Reader while making a copy. Having a copy is especially useful if there is a chance the data will fail to decode. encodedAs specifies the expected encoding, r provides the io.Reader to the data, and v is the decoding destination.

func DelayForBackoff

func DelayForBackoff(backoff time.Duration, attempt int, cancel <-chan struct{}) bool

DelayForBackoff invokes time.After for the supplied backoff duration raised to the power of passed attempt (i.e., an exponential backoff delay). Backoff duration is in seconds and can set to zero for no delay. The delay may be canceled by closing the passed channel. If terminated early, returns false. Note: Passing attempt 1 will result in doubling "backoff" duration. Treat this as a zero-based attempt count.

func Encode

func Encode(location string, v interface{}, sep ...string) string

Encode method encodes url path and query parameters.

func ExtractHeader

func ExtractHeader(header string, resp *http.Response) []string

ExtractHeader extracts all values of the specified header from the http.Response. It returns an empty string slice if the passed http.Response is nil or the header does not exist.

func ExtractHeaderValue

func ExtractHeaderValue(header string, resp *http.Response) string

ExtractHeaderValue extracts the first value of the specified header from the http.Response. It returns an empty string if the passed http.Response is nil or the header does not exist.

func GetLocation

func GetLocation(resp *http.Response) string

GetLocation retrieves the URL from the Location header of the passed response.

func GetRetryAfter

func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration

GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If the header is absent or is malformed, it will return the supplied default delay time.Duration.

func MapToValues

func MapToValues(m map[string]interface{}) url.Values

MapToValues method converts map[string]interface{} to url.Values.

func NewPollingRequest

func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error)

NewPollingRequest allocates and returns a new http.Request to poll for the passed response.

func Prepare

func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error)

Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators. It creates a Preparer from the decorators which it then applies to the passed http.Request.

Example

Create and prepare an http.Request in one call

r, err := Prepare(&http.Request{},
	AsGet(),
	WithBaseURL("https://microsoft.com/"),
	WithPath("a/b/c/"))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Printf("%s %s", r.Method, r.URL)
}
Output:

GET https://microsoft.com/a/b/c/

func Respond

func Respond(r *http.Response, decorators ...RespondDecorator) error

Respond accepts an http.Response and a, possibly empty, set of RespondDecorators. It creates a Responder from the decorators it then applies to the passed http.Response.

func ResponseHasStatusCode

func ResponseHasStatusCode(resp *http.Response, codes ...int) bool

ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set and false otherwise.

func Send

func Send(r *http.Request, decorators ...SendDecorator) (*http.Response, error)

Send sends, by means of the default http.Client, the passed http.Request, returning the http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which it will apply the http.Client before invoking the Do method.

Send is a convenience method and not recommended for production. Advanced users should use SendWithSender, passing and sharing their own Sender (e.g., instance of http.Client).

Send will not poll or retry requests.

func SendWithSender

func SendWithSender(s Sender, r *http.Request, decorators ...SendDecorator) (*http.Response, error)

SendWithSender sends the passed http.Request, through the provided Sender, returning the http.Response and possible error. It also accepts a, possibly empty, set of SendDecorators which it will apply the http.Client before invoking the Do method.

SendWithSender will not poll or retry requests.

Example
r := mocks.NewResponseWithStatus("202 Accepted", http.StatusAccepted)
mocks.SetAcceptedHeaders(r)

client := mocks.NewSender()
client.AppendAndRepeatResponse(r, 10)

logger := log.New(os.Stdout, "autorest: ", 0)
na := NullAuthorizer{}

req, _ := Prepare(&http.Request{},
	AsGet(),
	WithBaseURL("https://microsoft.com/a/b/c/"),
	na.WithAuthorization())

r, _ = SendWithSender(client, req,
	WithLogging(logger),
	DoErrorIfStatusCode(http.StatusAccepted),
	DoCloseIfError(),
	DoRetryForAttempts(5, time.Duration(0)))

Respond(r,
	ByClosing())
Output:

autorest: Sending GET https://microsoft.com/a/b/c/
autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted
autorest: Sending GET https://microsoft.com/a/b/c/
autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted
autorest: Sending GET https://microsoft.com/a/b/c/
autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted
autorest: Sending GET https://microsoft.com/a/b/c/
autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted
autorest: Sending GET https://microsoft.com/a/b/c/
autorest: GET https://microsoft.com/a/b/c/ received 202 Accepted

func String

func String(v interface{}, sep ...string) string

String method converts interface v to string. If interface is a list, it joins list elements using separator.

Example
m := []string{
	"string1",
	"string2",
	"string3",
}

fmt.Println(String(m, ","))
Output:

string1,string2,string3

func TeeReadCloser

func TeeReadCloser(rc io.ReadCloser, w io.Writer) io.ReadCloser

TeeReadCloser returns a ReadCloser that writes to w what it reads from rc. It utilizes io.TeeReader to copy the data read and has the same behavior when reading. Further, when it is closed, it ensures that rc is closed as well.

func Version

func Version() string

Version returns the semantic version (see http://semver.org).

Types

type Authorizer

type Authorizer interface {
	WithAuthorization() PrepareDecorator
}

Authorizer is the interface that provides a PrepareDecorator used to supply request authorization. Most often, the Authorizer decorator runs last so it has access to the full state of the formed HTTP request.

type Client

type Client struct {
	Authorizer        Authorizer
	Sender            Sender
	RequestInspector  PrepareDecorator
	ResponseInspector RespondDecorator

	// PollingDelay sets the polling frequency used in absence of a Retry-After HTTP header
	PollingDelay time.Duration

	// PollingDuration sets the maximum polling time after which an error is returned.
	PollingDuration time.Duration

	// RetryAttempts sets the default number of retry attempts for client.
	RetryAttempts int

	// RetryDuration sets the delay duration for retries.
	RetryDuration time.Duration

	// UserAgent, if not empty, will be set as the HTTP User-Agent header on all requests sent
	// through the Do method.
	UserAgent string

	Jar http.CookieJar
}

Client is the base for autorest generated clients. It provides default, "do nothing" implementations of an Authorizer, RequestInspector, and ResponseInspector. It also returns the standard, undecorated http.Client as a default Sender.

Generated clients should also use Error (see NewError and NewErrorWithError) for errors and return responses that compose with Response.

Most customization of generated clients is best achieved by supplying a custom Authorizer, custom RequestInspector, and / or custom ResponseInspector. Users may log requests, implement circuit breakers (see https://msdn.microsoft.com/en-us/library/dn589784.aspx) or otherwise influence sending the request by providing a decorated Sender.

func NewClientWithUserAgent

func NewClientWithUserAgent(ua string) Client

NewClientWithUserAgent returns an instance of a Client with the UserAgent set to the passed string.

func (Client) ByInspecting

func (c Client) ByInspecting() RespondDecorator

ByInspecting is a convenience method that passes the response to the supplied ResponseInspector, if present, or returns the ByIgnoring RespondDecorator otherwise.

func (Client) Do

func (c Client) Do(r *http.Request) (*http.Response, error)

Do implements the Sender interface by invoking the active Sender after applying authorization. If Sender is not set, it uses a new instance of http.Client. In both cases it will, if UserAgent is set, apply set the User-Agent header.

func (Client) WithAuthorization

func (c Client) WithAuthorization() PrepareDecorator

WithAuthorization is a convenience method that returns the WithAuthorization PrepareDecorator from the current Authorizer. If not Authorizer is set, it uses the NullAuthorizer.

func (Client) WithInspection

func (c Client) WithInspection() PrepareDecorator

WithInspection is a convenience method that passes the request to the supplied RequestInspector, if present, or returns the WithNothing PrepareDecorator otherwise.

type Decoder

type Decoder interface {
	Decode(v interface{}) error
}

Decoder defines the decoding method json.Decoder and xml.Decoder share

func NewDecoder

func NewDecoder(encodedAs EncodedAs, r io.Reader) Decoder

NewDecoder creates a new decoder appropriate to the passed encoding. encodedAs specifies the type of encoding and r supplies the io.Reader containing the encoded data.

type DetailedError

type DetailedError struct {
	Original error

	// PackageType is the package type of the object emitting the error. For types, the value
	// matches that produced the the '%T' format specifier of the fmt package. For other elements,
	// such as functions, it is just the package name (e.g., "autorest").
	PackageType string

	// Method is the name of the method raising the error.
	Method string

	// StatusCode is the HTTP Response StatusCode (if non-zero) that led to the error.
	StatusCode interface{}

	// Message is the error message.
	Message string

	// Service Error is the response body of failed API in bytes
	ServiceError []byte
}

DetailedError encloses a error with details of the package, method, and associated HTTP status code (if any).

func NewError

func NewError(packageType string, method string, message string, args ...interface{}) DetailedError

NewError creates a new Error conforming object from the passed packageType, method, and message. message is treated as a format string to which the optional args apply.

func NewErrorWithError

func NewErrorWithError(original error, packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError

NewErrorWithError creates a new Error conforming object from the passed packageType, method, statusCode of the given resp (UndefinedStatusCode if resp is nil), message, and original error. message is treated as a format string to which the optional args apply.

func NewErrorWithResponse

func NewErrorWithResponse(packageType string, method string, resp *http.Response, message string, args ...interface{}) DetailedError

NewErrorWithResponse creates a new Error conforming object from the passed packageType, method, statusCode of the given resp (UndefinedStatusCode if resp is nil), and message. message is treated as a format string to which the optional args apply.

func (DetailedError) Error

func (e DetailedError) Error() string

Error returns a formatted containing all available details (i.e., PackageType, Method, StatusCode, Message, and original error (if any)).

type EncodedAs

type EncodedAs string

EncodedAs is a series of constants specifying various data encodings

const (
	// EncodedAsJSON states that data is encoded as JSON
	EncodedAsJSON EncodedAs = "JSON"

	// EncodedAsXML states that data is encoded as Xml
	EncodedAsXML EncodedAs = "XML"
)

type LoggingInspector

type LoggingInspector struct {
	Logger *log.Logger
}

LoggingInspector implements request and response inspectors that log the full request and response to a supplied log.

func (LoggingInspector) ByInspecting

func (li LoggingInspector) ByInspecting() RespondDecorator

ByInspecting returns a RespondDecorator that emits the http.Response to the supplied logger. The body is restored after being emitted.

Note: Since it reads the entire Body, this decorator should not be used where body streaming is important. It is best used to trace JSON or similar body values.

func (LoggingInspector) WithInspection

func (li LoggingInspector) WithInspection() PrepareDecorator

WithInspection returns a PrepareDecorator that emits the http.Request to the supplied logger. The body is restored after being emitted.

Note: Since it reads the entire Body, this decorator should not be used where body streaming is important. It is best used to trace JSON or similar body values.

type NullAuthorizer

type NullAuthorizer struct{}

NullAuthorizer implements a default, "do nothing" Authorizer.

func (NullAuthorizer) WithAuthorization

func (na NullAuthorizer) WithAuthorization() PrepareDecorator

WithAuthorization returns a PrepareDecorator that does nothing.

type PrepareDecorator

type PrepareDecorator func(Preparer) Preparer

PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the http.Request and pass it along or, first, pass the http.Request along then affect the result.

Example

PrepareDecorators wrap and invoke a Preparer. Most often, the decorator invokes the passed Preparer and decorates the response.

path := "a/b/c/"
pd := func() PrepareDecorator {
	return func(p Preparer) Preparer {
		return PreparerFunc(func(r *http.Request) (*http.Request, error) {
			r, err := p.Prepare(r)
			if err == nil {
				if r.URL == nil {
					return r, fmt.Errorf("ERROR: URL is not set")
				}
				r.URL.Path += path
			}
			return r, err
		})
	}
}

r, _ := Prepare(&http.Request{},
	WithBaseURL("https://microsoft.com/"),
	pd())

fmt.Printf("Path is %s\n", r.URL)
Output:

Path is https://microsoft.com/a/b/c/
Example (Pre)

PrepareDecorators may also modify and then invoke the Preparer.

pd := func() PrepareDecorator {
	return func(p Preparer) Preparer {
		return PreparerFunc(func(r *http.Request) (*http.Request, error) {
			r.Header.Add(http.CanonicalHeaderKey("ContentType"), "application/json")
			return p.Prepare(r)
		})
	}
}

r, _ := Prepare(&http.Request{Header: http.Header{}},
	pd())

fmt.Printf("ContentType is %s\n", r.Header.Get("ContentType"))
Output:

ContentType is application/json

func AsContentType

func AsContentType(contentType string) PrepareDecorator

AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value is the passed contentType.

func AsDelete

func AsDelete() PrepareDecorator

AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE.

func AsFormURLEncoded

func AsFormURLEncoded() PrepareDecorator

AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is "application/x-www-form-urlencoded".

func AsGet

func AsGet() PrepareDecorator

AsGet returns a PrepareDecorator that sets the HTTP method to GET.

func AsHead

func AsHead() PrepareDecorator

AsHead returns a PrepareDecorator that sets the HTTP method to HEAD.

func AsJSON

func AsJSON() PrepareDecorator

AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is "application/json".

func AsOptions

func AsOptions() PrepareDecorator

AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS.

func AsPatch

func AsPatch() PrepareDecorator

AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH.

func AsPost

func AsPost() PrepareDecorator

AsPost returns a PrepareDecorator that sets the HTTP method to POST.

func AsPut

func AsPut() PrepareDecorator

AsPut returns a PrepareDecorator that sets the HTTP method to PUT.

func WithBaseURL

func WithBaseURL(baseURL string) PrepareDecorator

WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed from the supplied baseUrl.

Example

Create a request for a supplied base URL and path

r, err := Prepare(&http.Request{},
	WithBaseURL("https://microsoft.com/a/b/c/"))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a/b/c/
Example (Second)
_, err := Prepare(&http.Request{}, WithBaseURL(":"))
fmt.Println(err)
Output:

parse :: missing protocol scheme

func WithBearerAuthorization

func WithBearerAuthorization(token string) PrepareDecorator

WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose value is "Bearer " followed by the supplied token.

func WithBool

func WithBool(v bool) PrepareDecorator

WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request and sets the Content-Length header.

func WithEscapedPathParameters

func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator

WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The values will be escaped (aka URL encoded) before insertion into the path.

Example

Create a request from a path with escaped parameters

params := map[string]interface{}{
	"param1": "a b c",
	"param2": "d e f",
}
r, err := Prepare(&http.Request{},
	WithBaseURL("https://microsoft.com/"),
	WithEscapedPathParameters("/{param1}/b/{param2}/", params))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a+b+c/b/d+e+f/

func WithFile

func WithFile(f io.ReadCloser) PrepareDecorator

WithFile returns a PrepareDecorator that sends file in request body.

func WithFloat32

func WithFloat32(v float32) PrepareDecorator

WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the request and sets the Content-Length header.

func WithFloat64

func WithFloat64(v float64) PrepareDecorator

WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the request and sets the Content-Length header.

func WithFormData

func WithFormData(v url.Values) PrepareDecorator

WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the http.Request body.

Example

Create a request whose Body is the JSON encoding of a structure

v := url.Values{}
v.Add("name", "Rob Pike")
v.Add("age", "42")

r, err := Prepare(&http.Request{},
	WithFormData(v))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
}

b, err := ioutil.ReadAll(r.Body)
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Printf("Request Body contains %s\n", string(b))
}
Output:

Request Body contains age=42&name=Rob+Pike

func WithHeader

func WithHeader(header string, value string) PrepareDecorator

WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before adding the header.

Example

Create a request with a custom HTTP header

r, err := Prepare(&http.Request{},
	WithBaseURL("https://microsoft.com/a/b/c/"),
	WithHeader("x-foo", "bar"))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Printf("Header %s=%s\n", "x-foo", r.Header.Get("x-foo"))
}
Output:

Header x-foo=bar

func WithInt32

func WithInt32(v int32) PrepareDecorator

WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request and sets the Content-Length header.

func WithInt64

func WithInt64(v int64) PrepareDecorator

WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request and sets the Content-Length header.

func WithJSON

func WithJSON(v interface{}) PrepareDecorator

WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the request and sets the Content-Length header.

Example

Create a request whose Body is the JSON encoding of a structure

t := mocks.T{Name: "Rob Pike", Age: 42}

r, err := Prepare(&http.Request{},
	WithJSON(&t))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
}

b, err := ioutil.ReadAll(r.Body)
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Printf("Request Body contains %s\n", string(b))
}
Output:

Request Body contains {"name":"Rob Pike","age":42}

func WithMethod

func WithMethod(method string) PrepareDecorator

WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The decorator does not validate that the passed method string is a known HTTP method.

func WithMultiPartFormData

func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator

WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters into the http.Request body.

func WithNothing

func WithNothing() PrepareDecorator

WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed http.Request.

func WithPath

func WithPath(path string) PrepareDecorator

WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path is absolute (that is, it begins with a "/"), it replaces the existing path.

func WithPathParameters

func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator

WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map.

Example

Create a request from a path with parameters

params := map[string]interface{}{
	"param1": "a",
	"param2": "c",
}
r, err := Prepare(&http.Request{},
	WithBaseURL("https://microsoft.com/"),
	WithPathParameters("/{param1}/b/{param2}/", params))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a/b/c/

func WithQueryParameters

func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator

WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters given in the supplied map (i.e., key=value).

Example

Create a request with query parameters

params := map[string]interface{}{
	"q1": "value1",
	"q2": "value2",
}
r, err := Prepare(&http.Request{},
	WithBaseURL("https://microsoft.com/"),
	WithPath("/a/b/c/"),
	WithQueryParameters(params))
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a/b/c/?q1=value1&q2=value2

func WithString

func WithString(v string) PrepareDecorator

WithString returns a PrepareDecorator that encodes the passed string into the body of the request and sets the Content-Length header.

func WithUserAgent

func WithUserAgent(ua string) PrepareDecorator

WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the passed string.

type Preparer

type Preparer interface {
	Prepare(*http.Request) (*http.Request, error)
}

Preparer is the interface that wraps the Prepare method.

Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations must ensure to not share or hold per-invocation state since Preparers may be shared and re-used.

func CreatePreparer

func CreatePreparer(decorators ...PrepareDecorator) Preparer

CreatePreparer creates, decorates, and returns a Preparer. Without decorators, the returned Preparer returns the passed http.Request unmodified. Preparers are safe to share and re-use.

Example

Create a sequence of three Preparers that build up the URL path.

p := CreatePreparer(
	WithBaseURL("https://microsoft.com/"),
	WithPath("a"),
	WithPath("b"),
	WithPath("c"))
r, err := p.Prepare(&http.Request{})
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a/b/c
Example (Chain)

Create and chain separate Preparers

params := map[string]interface{}{
	"param1": "a",
	"param2": "c",
}

p := CreatePreparer(WithBaseURL("https://microsoft.com/"))
p = DecoratePreparer(p, WithPathParameters("/{param1}/b/{param2}/", params))

r, err := p.Prepare(&http.Request{})
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a/b/c/
Example (Multiple)

Create and apply separate Preparers

params := map[string]interface{}{
	"param1": "a",
	"param2": "c",
}

p1 := CreatePreparer(WithBaseURL("https://microsoft.com/"))
p2 := CreatePreparer(WithPathParameters("/{param1}/b/{param2}/", params))

r, err := p1.Prepare(&http.Request{})
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
}

r, err = p2.Prepare(r)
if err != nil {
	fmt.Printf("ERROR: %v\n", err)
} else {
	fmt.Println(r.URL)
}
Output:

https://microsoft.com/a/b/c/

func DecoratePreparer

func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer

DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it applies to the Preparer. Decorators are applied in the order received, but their affect upon the request depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a post-decorator (pass the http.Request along and alter it on return).

type PreparerFunc

type PreparerFunc func(*http.Request) (*http.Request, error)

PreparerFunc is a method that implements the Preparer interface.

func (PreparerFunc) Prepare

func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error)

Prepare implements the Preparer interface on PreparerFunc.

type RespondDecorator

type RespondDecorator func(Responder) Responder

RespondDecorator takes and possibly decorates, by wrapping, a Responder. Decorators may react to the http.Response and pass it along or, first, pass the http.Response along then react.

func ByClosing

func ByClosing() RespondDecorator

ByClosing returns a RespondDecorator that first invokes the passed Responder after which it closes the response body. Since the passed Responder is invoked prior to closing the response body, the decorator may occur anywhere within the set.

func ByClosingIfError

func ByClosingIfError() RespondDecorator

ByClosingIfError returns a RespondDecorator that first invokes the passed Responder after which it closes the response if the passed Responder returns an error and the response body exists.

func ByCopying

func ByCopying(b *bytes.Buffer) RespondDecorator

ByCopying copies the contents of the http.Response Body into the passed bytes.Buffer as the Body is read.

func ByIgnoring

func ByIgnoring() RespondDecorator

ByIgnoring returns a RespondDecorator that ignores the passed http.Response passing it unexamined to the next RespondDecorator.

func ByUnmarshallingJSON

func ByUnmarshallingJSON(v interface{}) RespondDecorator

ByUnmarshallingJSON returns a RespondDecorator that decodes a JSON document returned in the response Body into the value pointed to by v.

Example
c := `
	{
		"name" : "Rob Pike",
		"age"  : 42
	}
	`

type V struct {
	Name string `json:"name"`
	Age  int    `json:"age"`
}

v := &V{}

Respond(mocks.NewResponseWithContent(c),
	ByUnmarshallingJSON(v),
	ByClosing())

fmt.Printf("%s is %d years old\n", v.Name, v.Age)
Output:

Rob Pike is 42 years old

func ByUnmarshallingXML

func ByUnmarshallingXML(v interface{}) RespondDecorator

ByUnmarshallingXML returns a RespondDecorator that decodes a XML document returned in the response Body into the value pointed to by v.

Example
c := `<?xml version="1.0" encoding="UTF-8"?>
	<Person>
	  <Name>Rob Pike</Name>
	  <Age>42</Age>
	</Person>`

type V struct {
	Name string `xml:"Name"`
	Age  int    `xml:"Age"`
}

v := &V{}

Respond(mocks.NewResponseWithContent(c),
	ByUnmarshallingXML(v),
	ByClosing())

fmt.Printf("%s is %d years old\n", v.Name, v.Age)
Output:

Rob Pike is 42 years old

func WithErrorUnlessOK

func WithErrorUnlessOK() RespondDecorator

WithErrorUnlessOK returns a RespondDecorator that emits an error if the response StatusCode is anything other than HTTP 200.

Example
r := mocks.NewResponse()
r.Request = mocks.NewRequest()

// Respond and leave the response body open (for a subsequent responder to close)
err := Respond(r,
	WithErrorUnlessOK(),
	ByClosingIfError())

if err == nil {
	fmt.Printf("%s of %s returned HTTP 200", r.Request.Method, r.Request.URL)

	// Complete handling the response and close the body
	Respond(r,
		ByClosing())
}
Output:

GET of https://microsoft.com/a/b/c/ returned HTTP 200

func WithErrorUnlessStatusCode

func WithErrorUnlessStatusCode(codes ...int) RespondDecorator

WithErrorUnlessStatusCode returns a RespondDecorator that emits an error unless the response StatusCode is among the set passed. On error, response body is fully read into a buffer and presented in the returned error, as well as in the response body.

type Responder

type Responder interface {
	Respond(*http.Response) error
}

Responder is the interface that wraps the Respond method.

Respond accepts and reacts to an http.Response. Implementations must ensure to not share or hold state since Responders may be shared and re-used.

func CreateResponder

func CreateResponder(decorators ...RespondDecorator) Responder

CreateResponder creates, decorates, and returns a Responder. Without decorators, the returned Responder returns the passed http.Response unmodified. Responders may or may not be safe to share and re-used: It depends on the applied decorators. For example, a standard decorator that closes the response body is fine to share whereas a decorator that reads the body into a passed struct is not.

To prevent memory leaks, ensure that at least one Responder closes the response body.

func DecorateResponder

func DecorateResponder(r Responder, decorators ...RespondDecorator) Responder

DecorateResponder accepts a Responder and a, possibly empty, set of RespondDecorators, which it applies to the Responder. Decorators are applied in the order received, but their affect upon the request depends on whether they are a pre-decorator (react to the http.Response and then pass it along) or a post-decorator (pass the http.Response along and then react).

type ResponderFunc

type ResponderFunc func(*http.Response) error

ResponderFunc is a method that implements the Responder interface.

func (ResponderFunc) Respond

func (rf ResponderFunc) Respond(r *http.Response) error

Respond implements the Responder interface on ResponderFunc.

type Response

type Response struct {
	*http.Response `json:"-"`
}

Response serves as the base for all responses from generated clients. It provides access to the last http.Response.

type SendDecorator

type SendDecorator func(Sender) Sender

SendDecorator takes and possibily decorates, by wrapping, a Sender. Decorators may affect the http.Request and pass it along or, first, pass the http.Request along then react to the http.Response result.

func AfterDelay

func AfterDelay(d time.Duration) SendDecorator

AfterDelay returns a SendDecorator that delays for the passed time.Duration before invoking the Sender. The delay may be terminated by closing the optional channel on the http.Request. If canceled, no further Senders are invoked.

func AsIs

func AsIs() SendDecorator

AsIs returns a SendDecorator that invokes the passed Sender without modifying the http.Request.

func DoCloseIfError

func DoCloseIfError() SendDecorator

DoCloseIfError returns a SendDecorator that first invokes the passed Sender after which it closes the response if the passed Sender returns an error and the response body exists.

func DoErrorIfStatusCode

func DoErrorIfStatusCode(codes ...int) SendDecorator

DoErrorIfStatusCode returns a SendDecorator that emits an error if the response StatusCode is among the set passed. Since these are artificial errors, the response body may still require closing.

Example
client := mocks.NewSender()
client.AppendAndRepeatResponse(mocks.NewResponseWithStatus("204 NoContent", http.StatusNoContent), 10)

// Chain decorators to retry the request, up to five times, if the status code is 204
r, _ := SendWithSender(client, mocks.NewRequest(),
	DoErrorIfStatusCode(http.StatusNoContent),
	DoCloseIfError(),
	DoRetryForAttempts(5, time.Duration(0)))

Respond(r,
	ByClosing())

fmt.Printf("Retry stopped after %d attempts with code %s", client.Attempts(), r.Status)
Output:

Retry stopped after 5 attempts with code 204 NoContent

func DoErrorUnlessStatusCode

func DoErrorUnlessStatusCode(codes ...int) SendDecorator

DoErrorUnlessStatusCode returns a SendDecorator that emits an error unless the response StatusCode is among the set passed. Since these are artificial errors, the response body may still require closing.

func DoPollForStatusCodes

func DoPollForStatusCodes(duration time.Duration, delay time.Duration, codes ...int) SendDecorator

DoPollForStatusCodes returns a SendDecorator that polls if the http.Response contains one of the passed status codes. It expects the http.Response to contain a Location header providing the URL at which to poll (using GET) and will poll until the time passed is equal to or greater than the supplied duration. It will delay between requests for the duration specified in the RetryAfter header or, if the header is absent, the passed delay. Polling may be canceled by closing the optional channel on the http.Request.

func DoRetryForAttempts

func DoRetryForAttempts(attempts int, backoff time.Duration) SendDecorator

DoRetryForAttempts returns a SendDecorator that retries a failed request for up to the specified number of attempts, exponentially backing off between requests using the supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on the http.Request.

Example
client := mocks.NewSender()
client.SetAndRepeatError(fmt.Errorf("Faux Error"), 10)

// Retry with backoff -- ensure returned Bodies are closed
r, _ := SendWithSender(client, mocks.NewRequest(),
	DoCloseIfError(),
	DoRetryForAttempts(5, time.Duration(0)))

Respond(r,
	ByClosing())

fmt.Printf("Retry stopped after %d attempts", client.Attempts())
Output:

Retry stopped after 5 attempts

func DoRetryForDuration

func DoRetryForDuration(d time.Duration, backoff time.Duration) SendDecorator

DoRetryForDuration returns a SendDecorator that retries the request until the total time is equal to or greater than the specified duration, exponentially backing off between requests using the supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on the http.Request.

func DoRetryForStatusCodes

func DoRetryForStatusCodes(attempts int, backoff time.Duration, codes ...int) SendDecorator

DoRetryForStatusCodes returns a SendDecorator that retries for specified statusCodes for up to the specified number of attempts, exponentially backing off between requests using the supplied backoff time.Duration (which may be zero). Retrying may be canceled by closing the optional channel on the http.Request.

func WithLogging

func WithLogging(logger *log.Logger) SendDecorator

WithLogging returns a SendDecorator that implements simple before and after logging of the request.

type Sender

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

Sender is the interface that wraps the Do method to send HTTP requests.

The standard http.Client conforms to this interface.

func CreateSender

func CreateSender(decorators ...SendDecorator) Sender

CreateSender creates, decorates, and returns, as a Sender, the default http.Client.

func DecorateSender

func DecorateSender(s Sender, decorators ...SendDecorator) Sender

DecorateSender accepts a Sender and a, possibly empty, set of SendDecorators, which is applies to the Sender. Decorators are applied in the order received, but their affect upon the request depends on whether they are a pre-decorator (change the http.Request and then pass it along) or a post-decorator (pass the http.Request along and react to the results in http.Response).

type SenderFunc

type SenderFunc func(*http.Request) (*http.Response, error)

SenderFunc is a method that implements the Sender interface.

func (SenderFunc) Do

func (sf SenderFunc) Do(r *http.Request) (*http.Response, error)

Do implements the Sender interface on SenderFunc.

Directories

Path Synopsis
Package azure provides Azure-specific implementations used with AutoRest.
Package azure provides Azure-specific implementations used with AutoRest.
Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/) defined date formats: Date and DateTime.
Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/) defined date formats: Date and DateTime.
Package mocks provides mocks and helpers used in testing.
Package mocks provides mocks and helpers used in testing.
Package to provides helpers to ease working with pointer values of marshalled structures.
Package to provides helpers to ease working with pointer values of marshalled structures.
Package validation provides methods for validating parameter value using reflection.
Package validation provides methods for validating parameter value using reflection.

Jump to

Keyboard shortcuts

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