Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / Azure / go-autorest / autorest / preparer.go
1 package autorest
2
3 // Copyright 2017 Microsoft Corporation
4 //
5 //  Licensed under the Apache License, Version 2.0 (the "License");
6 //  you may not use this file except in compliance with the License.
7 //  You may obtain a copy of the License at
8 //
9 //      http://www.apache.org/licenses/LICENSE-2.0
10 //
11 //  Unless required by applicable law or agreed to in writing, software
12 //  distributed under the License is distributed on an "AS IS" BASIS,
13 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 //  See the License for the specific language governing permissions and
15 //  limitations under the License.
16
17 import (
18         "bytes"
19         "encoding/json"
20         "fmt"
21         "io"
22         "io/ioutil"
23         "mime/multipart"
24         "net/http"
25         "net/url"
26         "strings"
27 )
28
29 const (
30         mimeTypeJSON        = "application/json"
31         mimeTypeOctetStream = "application/octet-stream"
32         mimeTypeFormPost    = "application/x-www-form-urlencoded"
33
34         headerAuthorization = "Authorization"
35         headerContentType   = "Content-Type"
36         headerUserAgent     = "User-Agent"
37 )
38
39 // Preparer is the interface that wraps the Prepare method.
40 //
41 // Prepare accepts and possibly modifies an http.Request (e.g., adding Headers). Implementations
42 // must ensure to not share or hold per-invocation state since Preparers may be shared and re-used.
43 type Preparer interface {
44         Prepare(*http.Request) (*http.Request, error)
45 }
46
47 // PreparerFunc is a method that implements the Preparer interface.
48 type PreparerFunc func(*http.Request) (*http.Request, error)
49
50 // Prepare implements the Preparer interface on PreparerFunc.
51 func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) {
52         return pf(r)
53 }
54
55 // PrepareDecorator takes and possibly decorates, by wrapping, a Preparer. Decorators may affect the
56 // http.Request and pass it along or, first, pass the http.Request along then affect the result.
57 type PrepareDecorator func(Preparer) Preparer
58
59 // CreatePreparer creates, decorates, and returns a Preparer.
60 // Without decorators, the returned Preparer returns the passed http.Request unmodified.
61 // Preparers are safe to share and re-use.
62 func CreatePreparer(decorators ...PrepareDecorator) Preparer {
63         return DecoratePreparer(
64                 Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })),
65                 decorators...)
66 }
67
68 // DecoratePreparer accepts a Preparer and a, possibly empty, set of PrepareDecorators, which it
69 // applies to the Preparer. Decorators are applied in the order received, but their affect upon the
70 // request depends on whether they are a pre-decorator (change the http.Request and then pass it
71 // along) or a post-decorator (pass the http.Request along and alter it on return).
72 func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer {
73         for _, decorate := range decorators {
74                 p = decorate(p)
75         }
76         return p
77 }
78
79 // Prepare accepts an http.Request and a, possibly empty, set of PrepareDecorators.
80 // It creates a Preparer from the decorators which it then applies to the passed http.Request.
81 func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) {
82         if r == nil {
83                 return nil, NewError("autorest", "Prepare", "Invoked without an http.Request")
84         }
85         return CreatePreparer(decorators...).Prepare(r)
86 }
87
88 // WithNothing returns a "do nothing" PrepareDecorator that makes no changes to the passed
89 // http.Request.
90 func WithNothing() PrepareDecorator {
91         return func(p Preparer) Preparer {
92                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
93                         return p.Prepare(r)
94                 })
95         }
96 }
97
98 // WithHeader returns a PrepareDecorator that sets the specified HTTP header of the http.Request to
99 // the passed value. It canonicalizes the passed header name (via http.CanonicalHeaderKey) before
100 // adding the header.
101 func WithHeader(header string, value string) PrepareDecorator {
102         return func(p Preparer) Preparer {
103                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
104                         r, err := p.Prepare(r)
105                         if err == nil {
106                                 if r.Header == nil {
107                                         r.Header = make(http.Header)
108                                 }
109                                 r.Header.Set(http.CanonicalHeaderKey(header), value)
110                         }
111                         return r, err
112                 })
113         }
114 }
115
116 // WithHeaders returns a PrepareDecorator that sets the specified HTTP headers of the http.Request to
117 // the passed value. It canonicalizes the passed headers name (via http.CanonicalHeaderKey) before
118 // adding them.
119 func WithHeaders(headers map[string]interface{}) PrepareDecorator {
120         h := ensureValueStrings(headers)
121         return func(p Preparer) Preparer {
122                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
123                         r, err := p.Prepare(r)
124                         if err == nil {
125                                 if r.Header == nil {
126                                         r.Header = make(http.Header)
127                                 }
128
129                                 for name, value := range h {
130                                         r.Header.Set(http.CanonicalHeaderKey(name), value)
131                                 }
132                         }
133                         return r, err
134                 })
135         }
136 }
137
138 // WithBearerAuthorization returns a PrepareDecorator that adds an HTTP Authorization header whose
139 // value is "Bearer " followed by the supplied token.
140 func WithBearerAuthorization(token string) PrepareDecorator {
141         return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token))
142 }
143
144 // AsContentType returns a PrepareDecorator that adds an HTTP Content-Type header whose value
145 // is the passed contentType.
146 func AsContentType(contentType string) PrepareDecorator {
147         return WithHeader(headerContentType, contentType)
148 }
149
150 // WithUserAgent returns a PrepareDecorator that adds an HTTP User-Agent header whose value is the
151 // passed string.
152 func WithUserAgent(ua string) PrepareDecorator {
153         return WithHeader(headerUserAgent, ua)
154 }
155
156 // AsFormURLEncoded returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
157 // "application/x-www-form-urlencoded".
158 func AsFormURLEncoded() PrepareDecorator {
159         return AsContentType(mimeTypeFormPost)
160 }
161
162 // AsJSON returns a PrepareDecorator that adds an HTTP Content-Type header whose value is
163 // "application/json".
164 func AsJSON() PrepareDecorator {
165         return AsContentType(mimeTypeJSON)
166 }
167
168 // AsOctetStream returns a PrepareDecorator that adds the "application/octet-stream" Content-Type header.
169 func AsOctetStream() PrepareDecorator {
170         return AsContentType(mimeTypeOctetStream)
171 }
172
173 // WithMethod returns a PrepareDecorator that sets the HTTP method of the passed request. The
174 // decorator does not validate that the passed method string is a known HTTP method.
175 func WithMethod(method string) PrepareDecorator {
176         return func(p Preparer) Preparer {
177                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
178                         r.Method = method
179                         return p.Prepare(r)
180                 })
181         }
182 }
183
184 // AsDelete returns a PrepareDecorator that sets the HTTP method to DELETE.
185 func AsDelete() PrepareDecorator { return WithMethod("DELETE") }
186
187 // AsGet returns a PrepareDecorator that sets the HTTP method to GET.
188 func AsGet() PrepareDecorator { return WithMethod("GET") }
189
190 // AsHead returns a PrepareDecorator that sets the HTTP method to HEAD.
191 func AsHead() PrepareDecorator { return WithMethod("HEAD") }
192
193 // AsOptions returns a PrepareDecorator that sets the HTTP method to OPTIONS.
194 func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") }
195
196 // AsPatch returns a PrepareDecorator that sets the HTTP method to PATCH.
197 func AsPatch() PrepareDecorator { return WithMethod("PATCH") }
198
199 // AsPost returns a PrepareDecorator that sets the HTTP method to POST.
200 func AsPost() PrepareDecorator { return WithMethod("POST") }
201
202 // AsPut returns a PrepareDecorator that sets the HTTP method to PUT.
203 func AsPut() PrepareDecorator { return WithMethod("PUT") }
204
205 // WithBaseURL returns a PrepareDecorator that populates the http.Request with a url.URL constructed
206 // from the supplied baseUrl.
207 func WithBaseURL(baseURL string) PrepareDecorator {
208         return func(p Preparer) Preparer {
209                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
210                         r, err := p.Prepare(r)
211                         if err == nil {
212                                 var u *url.URL
213                                 if u, err = url.Parse(baseURL); err != nil {
214                                         return r, err
215                                 }
216                                 if u.Scheme == "" {
217                                         err = fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
218                                 }
219                                 if err == nil {
220                                         r.URL = u
221                                 }
222                         }
223                         return r, err
224                 })
225         }
226 }
227
228 // WithCustomBaseURL returns a PrepareDecorator that replaces brace-enclosed keys within the
229 // request base URL (i.e., http.Request.URL) with the corresponding values from the passed map.
230 func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator {
231         parameters := ensureValueStrings(urlParameters)
232         for key, value := range parameters {
233                 baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1)
234         }
235         return WithBaseURL(baseURL)
236 }
237
238 // WithFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) into the
239 // http.Request body.
240 func WithFormData(v url.Values) PrepareDecorator {
241         return func(p Preparer) Preparer {
242                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
243                         r, err := p.Prepare(r)
244                         if err == nil {
245                                 s := v.Encode()
246
247                                 if r.Header == nil {
248                                         r.Header = make(http.Header)
249                                 }
250                                 r.Header.Set(http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost)
251                                 r.ContentLength = int64(len(s))
252                                 r.Body = ioutil.NopCloser(strings.NewReader(s))
253                         }
254                         return r, err
255                 })
256         }
257 }
258
259 // WithMultiPartFormData returns a PrepareDecoratore that "URL encodes" (e.g., bar=baz&foo=quux) form parameters
260 // into the http.Request body.
261 func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator {
262         return func(p Preparer) Preparer {
263                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
264                         r, err := p.Prepare(r)
265                         if err == nil {
266                                 var body bytes.Buffer
267                                 writer := multipart.NewWriter(&body)
268                                 for key, value := range formDataParameters {
269                                         if rc, ok := value.(io.ReadCloser); ok {
270                                                 var fd io.Writer
271                                                 if fd, err = writer.CreateFormFile(key, key); err != nil {
272                                                         return r, err
273                                                 }
274                                                 if _, err = io.Copy(fd, rc); err != nil {
275                                                         return r, err
276                                                 }
277                                         } else {
278                                                 if err = writer.WriteField(key, ensureValueString(value)); err != nil {
279                                                         return r, err
280                                                 }
281                                         }
282                                 }
283                                 if err = writer.Close(); err != nil {
284                                         return r, err
285                                 }
286                                 if r.Header == nil {
287                                         r.Header = make(http.Header)
288                                 }
289                                 r.Header.Set(http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
290                                 r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
291                                 r.ContentLength = int64(body.Len())
292                                 return r, err
293                         }
294                         return r, err
295                 })
296         }
297 }
298
299 // WithFile returns a PrepareDecorator that sends file in request body.
300 func WithFile(f io.ReadCloser) PrepareDecorator {
301         return func(p Preparer) Preparer {
302                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
303                         r, err := p.Prepare(r)
304                         if err == nil {
305                                 b, err := ioutil.ReadAll(f)
306                                 if err != nil {
307                                         return r, err
308                                 }
309                                 r.Body = ioutil.NopCloser(bytes.NewReader(b))
310                                 r.ContentLength = int64(len(b))
311                         }
312                         return r, err
313                 })
314         }
315 }
316
317 // WithBool returns a PrepareDecorator that encodes the passed bool into the body of the request
318 // and sets the Content-Length header.
319 func WithBool(v bool) PrepareDecorator {
320         return WithString(fmt.Sprintf("%v", v))
321 }
322
323 // WithFloat32 returns a PrepareDecorator that encodes the passed float32 into the body of the
324 // request and sets the Content-Length header.
325 func WithFloat32(v float32) PrepareDecorator {
326         return WithString(fmt.Sprintf("%v", v))
327 }
328
329 // WithFloat64 returns a PrepareDecorator that encodes the passed float64 into the body of the
330 // request and sets the Content-Length header.
331 func WithFloat64(v float64) PrepareDecorator {
332         return WithString(fmt.Sprintf("%v", v))
333 }
334
335 // WithInt32 returns a PrepareDecorator that encodes the passed int32 into the body of the request
336 // and sets the Content-Length header.
337 func WithInt32(v int32) PrepareDecorator {
338         return WithString(fmt.Sprintf("%v", v))
339 }
340
341 // WithInt64 returns a PrepareDecorator that encodes the passed int64 into the body of the request
342 // and sets the Content-Length header.
343 func WithInt64(v int64) PrepareDecorator {
344         return WithString(fmt.Sprintf("%v", v))
345 }
346
347 // WithString returns a PrepareDecorator that encodes the passed string into the body of the request
348 // and sets the Content-Length header.
349 func WithString(v string) PrepareDecorator {
350         return func(p Preparer) Preparer {
351                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
352                         r, err := p.Prepare(r)
353                         if err == nil {
354                                 r.ContentLength = int64(len(v))
355                                 r.Body = ioutil.NopCloser(strings.NewReader(v))
356                         }
357                         return r, err
358                 })
359         }
360 }
361
362 // WithJSON returns a PrepareDecorator that encodes the data passed as JSON into the body of the
363 // request and sets the Content-Length header.
364 func WithJSON(v interface{}) PrepareDecorator {
365         return func(p Preparer) Preparer {
366                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
367                         r, err := p.Prepare(r)
368                         if err == nil {
369                                 b, err := json.Marshal(v)
370                                 if err == nil {
371                                         r.ContentLength = int64(len(b))
372                                         r.Body = ioutil.NopCloser(bytes.NewReader(b))
373                                 }
374                         }
375                         return r, err
376                 })
377         }
378 }
379
380 // WithPath returns a PrepareDecorator that adds the supplied path to the request URL. If the path
381 // is absolute (that is, it begins with a "/"), it replaces the existing path.
382 func WithPath(path string) PrepareDecorator {
383         return func(p Preparer) Preparer {
384                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
385                         r, err := p.Prepare(r)
386                         if err == nil {
387                                 if r.URL == nil {
388                                         return r, NewError("autorest", "WithPath", "Invoked with a nil URL")
389                                 }
390                                 if r.URL, err = parseURL(r.URL, path); err != nil {
391                                         return r, err
392                                 }
393                         }
394                         return r, err
395                 })
396         }
397 }
398
399 // WithEscapedPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
400 // request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map. The
401 // values will be escaped (aka URL encoded) before insertion into the path.
402 func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
403         parameters := escapeValueStrings(ensureValueStrings(pathParameters))
404         return func(p Preparer) Preparer {
405                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
406                         r, err := p.Prepare(r)
407                         if err == nil {
408                                 if r.URL == nil {
409                                         return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL")
410                                 }
411                                 for key, value := range parameters {
412                                         path = strings.Replace(path, "{"+key+"}", value, -1)
413                                 }
414                                 if r.URL, err = parseURL(r.URL, path); err != nil {
415                                         return r, err
416                                 }
417                         }
418                         return r, err
419                 })
420         }
421 }
422
423 // WithPathParameters returns a PrepareDecorator that replaces brace-enclosed keys within the
424 // request path (i.e., http.Request.URL.Path) with the corresponding values from the passed map.
425 func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
426         parameters := ensureValueStrings(pathParameters)
427         return func(p Preparer) Preparer {
428                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
429                         r, err := p.Prepare(r)
430                         if err == nil {
431                                 if r.URL == nil {
432                                         return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL")
433                                 }
434                                 for key, value := range parameters {
435                                         path = strings.Replace(path, "{"+key+"}", value, -1)
436                                 }
437
438                                 if r.URL, err = parseURL(r.URL, path); err != nil {
439                                         return r, err
440                                 }
441                         }
442                         return r, err
443                 })
444         }
445 }
446
447 func parseURL(u *url.URL, path string) (*url.URL, error) {
448         p := strings.TrimRight(u.String(), "/")
449         if !strings.HasPrefix(path, "/") {
450                 path = "/" + path
451         }
452         return url.Parse(p + path)
453 }
454
455 // WithQueryParameters returns a PrepareDecorators that encodes and applies the query parameters
456 // given in the supplied map (i.e., key=value).
457 func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator {
458         parameters := ensureValueStrings(queryParameters)
459         return func(p Preparer) Preparer {
460                 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
461                         r, err := p.Prepare(r)
462                         if err == nil {
463                                 if r.URL == nil {
464                                         return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL")
465                                 }
466
467                                 v := r.URL.Query()
468                                 for key, value := range parameters {
469                                         d, err := url.QueryUnescape(value)
470                                         if err != nil {
471                                                 return r, err
472                                         }
473                                         v.Add(key, d)
474                                 }
475                                 r.URL.RawQuery = v.Encode()
476                         }
477                         return r, err
478                 })
479         }
480 }