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

const (
	// DefaultPollingDelay is the default delay between polling requests (only used if the
	// http.Request lacks a well-formed Retry-After header).
	DefaultPollingDelay = 60 * time.Second

	// DefaultPollingDuration is the default total polling duration.
	DefaultPollingDuration = 15 * time.Minute
)

Variables

var (
	// DefaultClient is the base from which generated clients should create a Client instance. Users
	// can then established widely used Client defaults by replacing or modifying the DefaultClient
	// before instantiating a generated client.
	DefaultClient = Client{PollingMode: PollUntilDuration, PollingDuration: DefaultPollingDuration}
)

Functions

func DelayForBackoff

func DelayForBackoff(backoff time.Duration, attempt int)

DelayForBackoff invokes time.Sleep for the supplied backoff duration raised to the power of passed attempt (i.e., an exponential backoff delay). Backoff may be zero.

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 GetPollingDelay

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

GetPollingDelay extracts the polling 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 GetPollingLocation

func GetPollingLocation(resp *http.Response) string

GetPollingLocation retrieves the polling URL from the Location header of the passed response.

func NewPollingRequest

func NewPollingRequest(resp *http.Response, authorizer Authorizer) (*http.Request, error)

NewPollingRequest allocates and returns a new http.Request to poll for the passed response. If it successfully creates the request, it will also close the body of the passed response, otherwise the body remains open.

func PollForAttempts

func PollForAttempts(s Sender, req *http.Request, defaultDelay time.Duration, attempts int, codes ...int) (*http.Response, error)

PollForAttempts will retry the passed http.Request until it receives an HTTP status code outside the passed set or has made the specified number of attempts. The set of status codes defaults to HTTP 202 Accepted.

func PollForDuration

func PollForDuration(s Sender, req *http.Request, defaultDelay time.Duration, total time.Duration, codes ...int) (*http.Response, error)

PollForDuration will retry the passed http.Request until it receives an HTTP status code outside the passed set or the total time meets or exceeds the specified duration. The set of status codes defaults to HTTP 202 Accepted.

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

Code:

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)
}
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 ResponseRequiresPolling

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

ResponseRequiresPolling returns true if the passed http.Response requires polling follow-up request (as determined by the status code being in the passed set, which defaults to HTTP 202 Accepted).

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

Code:

client := mocks.NewSender()
client.EmitStatus("202 Accepted", http.StatusAccepted)

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())
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 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

	PollingMode     PollingMode
	PollingAttempts int
	PollingDuration 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
}

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. Lastly, it supports basic request polling, limited to a maximum number of attempts or a specified duration.

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 the DefaultClient 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. 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) DoNotPoll

func (c Client) DoNotPoll() bool

DoNotPoll returns true if the client should not poll, false otherwise.

func (Client) IsPollingAllowed

func (c Client) IsPollingAllowed(resp *http.Response, codes ...int) error

IsPollingAllowed returns an error if the client allows polling and the passed http.Response requires it, otherwise it returns nil.

func (Client) PollAsNeeded

func (c Client) PollAsNeeded(resp *http.Response, codes ...int) (*http.Response, error)

PollAsNeeded is a convenience method that will poll if the passed http.Response requires it.

func (Client) PollForAttempts

func (c Client) PollForAttempts() bool

PollForAttempts returns true if the PollingMode is set to ForAttempts, false otherwise.

func (Client) PollForDuration

func (c Client) PollForDuration() bool

PollForDuration return true if the PollingMode is set to ForDuration, false otherwise.

func (Client) Send

func (c Client) Send(req *http.Request, codes ...int) (*http.Response, error)

Send sends the passed http.Request after applying authorization. It will poll if the client allows polling and the http.Response status code requires it. It will close the http.Response Body if the request returns an error.

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 Error

type Error interface {
	error

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

	// Method should return the name of the method raising the error.
	Method() string

	// Message should return the error message.
	Message() string

	// String should return a formatted containing all available details (i.e., PackageType, Method,
	// Message, and original error (if any)).
	String() string

	// Original should return the original error, if any, and nil otherwise.
	Original() error
}

Error describes the methods implemented by autorest errors.

func NewError

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

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, message string, args ...interface{}) Error

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

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 PollingMode

type PollingMode string

PollingMode sets how, if at all, clients composed with Client will poll.

const (
	// PollUntilAttempts polling mode polls until reaching a maximum number of attempts.
	PollUntilAttempts PollingMode = "poll-until-attempts"

	// PollUntilDuration polling mode polls until a specified time.Duration has passed.
	PollUntilDuration PollingMode = "poll-until-duration"

	// DoNotPoll disables polling.
	DoNotPoll PollingMode = "not-at-all"
)

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.

Code:

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)
Path is https://microsoft.com/a/b/c/
Example (Pre)

PrepareDecorators may also modify and then invoke the Preparer.

Code:

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

Code:

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)
}
https://microsoft.com/a/b/c/

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 WithEscapedPathParameters

func WithEscapedPathParameters(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

Code:

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

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

Code:

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

Code:

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"))
}
Header x-foo=bar

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

Code:

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))
}
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 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(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

Code:

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

Code:

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)
}
https://microsoft.com/a/b/c/?q1=value1&q2=value2

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.

Code:

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)
}
https://microsoft.com/a/b/c
Example (Chain)

Create and chain separate Preparers

Code:

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

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

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

Create and apply separate Preparers

Code:

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

p1 := CreatePreparer(WithBaseURL("https://microsoft.com/"), WithPath("/{param1}/b/{param2}/"))
p2 := CreatePreparer(WithPathParameters(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)
}
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 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

Code:

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)
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

Code:

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())
}
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. Since these are artificial errors, the response body may still require closing.

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.

func (Response) GetPollingDelay

func (r Response) GetPollingDelay(defaultDelay time.Duration) time.Duration

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

func (Response) GetPollingLocation

func (r Response) GetPollingLocation() string

GetPollingLocation retrieves the polling URL from the Location header of the 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.

func AfterRetryDelay

func AfterRetryDelay(defaultDelay time.Duration, codes ...int) SendDecorator

AfterRetryDelay returns a SendDecorator that delays for the number of seconds specified in the Retry-After header of the prior response when polling is required.

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

Code:

client := mocks.NewSender()
client.EmitStatus("204 NoContent", http.StatusNoContent)

// 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)
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 DoRetryForAttempts

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

DoRetryForAttempts returns a SendDecorator that retries the request for up to the specified number of attempts, exponentially backing off between requests using the supplied backoff time.Duration (which may be zero).

Example

Code:

client := mocks.NewSender()
client.EmitErrors(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())
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).

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
azure Package azure provides Azure-specific implementations used with AutoRest.
azure/example
date Package date provides time.Time derivatives that conform to the Swagger.io (https://swagger.io/) defined date formats: Date and DateTime.
mocks Package mocks provides mocks and helpers used in testing.
to Package to provides helpers to ease working with pointer values of marshalled structures.
MODULE adal
MODULE azure/auth
MODULE azure/cli
MODULE date
MODULE mocks
MODULE to
MODULE validation