Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / github.com / Azure / go-autorest / autorest / autorest.go
1 /*
2 Package autorest implements an HTTP request pipeline suitable for use across multiple go-routines
3 and provides the shared routines relied on by AutoRest (see https://github.com/Azure/autorest/)
4 generated Go code.
5
6 The package breaks sending and responding to HTTP requests into three phases: Preparing, Sending,
7 and Responding. A typical pattern is:
8
9   req, err := Prepare(&http.Request{},
10     token.WithAuthorization())
11
12   resp, err := Send(req,
13     WithLogging(logger),
14     DoErrorIfStatusCode(http.StatusInternalServerError),
15     DoCloseIfError(),
16     DoRetryForAttempts(5, time.Second))
17
18   err = Respond(resp,
19     ByDiscardingBody(),
20     ByClosing())
21
22 Each phase relies on decorators to modify and / or manage processing. Decorators may first modify
23 and then pass the data along, pass the data first and then modify the result, or wrap themselves
24 around passing the data (such as a logger might do). Decorators run in the order provided. For
25 example, the following:
26
27   req, err := Prepare(&http.Request{},
28     WithBaseURL("https://microsoft.com/"),
29     WithPath("a"),
30     WithPath("b"),
31     WithPath("c"))
32
33 will set the URL to:
34
35   https://microsoft.com/a/b/c
36
37 Preparers and Responders may be shared and re-used (assuming the underlying decorators support
38 sharing and re-use). Performant use is obtained by creating one or more Preparers and Responders
39 shared among multiple go-routines, and a single Sender shared among multiple sending go-routines,
40 all bound together by means of input / output channels.
41
42 Decorators hold their passed state within a closure (such as the path components in the example
43 above). Be careful to share Preparers and Responders only in a context where such held state
44 applies. For example, it may not make sense to share a Preparer that applies a query string from a
45 fixed set of values. Similarly, sharing a Responder that reads the response body into a passed
46 struct (e.g., ByUnmarshallingJson) is likely incorrect.
47
48 Lastly, the Swagger specification (https://swagger.io) that drives AutoRest
49 (https://github.com/Azure/autorest/) precisely defines two date forms: date and date-time. The
50 github.com/Azure/go-autorest/autorest/date package provides time.Time derivations to ensure
51 correct parsing and formatting.
52
53 Errors raised by autorest objects and methods will conform to the autorest.Error interface.
54
55 See the included examples for more detail. For details on the suggested use of this package by
56 generated clients, see the Client described below.
57 */
58 package autorest
59
60 // Copyright 2017 Microsoft Corporation
61 //
62 //  Licensed under the Apache License, Version 2.0 (the "License");
63 //  you may not use this file except in compliance with the License.
64 //  You may obtain a copy of the License at
65 //
66 //      http://www.apache.org/licenses/LICENSE-2.0
67 //
68 //  Unless required by applicable law or agreed to in writing, software
69 //  distributed under the License is distributed on an "AS IS" BASIS,
70 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71 //  See the License for the specific language governing permissions and
72 //  limitations under the License.
73
74 import (
75         "context"
76         "net/http"
77         "time"
78 )
79
80 const (
81         // HeaderLocation specifies the HTTP Location header.
82         HeaderLocation = "Location"
83
84         // HeaderRetryAfter specifies the HTTP Retry-After header.
85         HeaderRetryAfter = "Retry-After"
86 )
87
88 // ResponseHasStatusCode returns true if the status code in the HTTP Response is in the passed set
89 // and false otherwise.
90 func ResponseHasStatusCode(resp *http.Response, codes ...int) bool {
91         if resp == nil {
92                 return false
93         }
94         return containsInt(codes, resp.StatusCode)
95 }
96
97 // GetLocation retrieves the URL from the Location header of the passed response.
98 func GetLocation(resp *http.Response) string {
99         return resp.Header.Get(HeaderLocation)
100 }
101
102 // GetRetryAfter extracts the retry delay from the Retry-After header of the passed response. If
103 // the header is absent or is malformed, it will return the supplied default delay time.Duration.
104 func GetRetryAfter(resp *http.Response, defaultDelay time.Duration) time.Duration {
105         retry := resp.Header.Get(HeaderRetryAfter)
106         if retry == "" {
107                 return defaultDelay
108         }
109
110         d, err := time.ParseDuration(retry + "s")
111         if err != nil {
112                 return defaultDelay
113         }
114
115         return d
116 }
117
118 // NewPollingRequest allocates and returns a new http.Request to poll for the passed response.
119 func NewPollingRequest(resp *http.Response, cancel <-chan struct{}) (*http.Request, error) {
120         location := GetLocation(resp)
121         if location == "" {
122                 return nil, NewErrorWithResponse("autorest", "NewPollingRequest", resp, "Location header missing from response that requires polling")
123         }
124
125         req, err := Prepare(&http.Request{Cancel: cancel},
126                 AsGet(),
127                 WithBaseURL(location))
128         if err != nil {
129                 return nil, NewErrorWithError(err, "autorest", "NewPollingRequest", nil, "Failure creating poll request to %s", location)
130         }
131
132         return req, nil
133 }
134
135 // NewPollingRequestWithContext allocates and returns a new http.Request with the specified context to poll for the passed response.
136 func NewPollingRequestWithContext(ctx context.Context, resp *http.Response) (*http.Request, error) {
137         location := GetLocation(resp)
138         if location == "" {
139                 return nil, NewErrorWithResponse("autorest", "NewPollingRequestWithContext", resp, "Location header missing from response that requires polling")
140         }
141
142         req, err := Prepare((&http.Request{}).WithContext(ctx),
143                 AsGet(),
144                 WithBaseURL(location))
145         if err != nil {
146                 return nil, NewErrorWithError(err, "autorest", "NewPollingRequestWithContext", nil, "Failure creating poll request to %s", location)
147         }
148
149         return req, nil
150 }