1 package autorest
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import (
18 "bytes"
19 "context"
20 "encoding/json"
21 "encoding/xml"
22 "fmt"
23 "io"
24 "io/ioutil"
25 "mime/multipart"
26 "net/http"
27 "net/url"
28 "strings"
29 )
30
31 const (
32 mimeTypeJSON = "application/json"
33 mimeTypeOctetStream = "application/octet-stream"
34 mimeTypeFormPost = "application/x-www-form-urlencoded"
35
36 headerAuthorization = "Authorization"
37 headerAuxAuthorization = "x-ms-authorization-auxiliary"
38 headerContentType = "Content-Type"
39 headerUserAgent = "User-Agent"
40 )
41
42
43 type ctxPrepareDecorators struct{}
44
45
46
47 func WithPrepareDecorators(ctx context.Context, prepareDecorator []PrepareDecorator) context.Context {
48 if len(prepareDecorator) == 0 {
49 return ctx
50 }
51 return context.WithValue(ctx, ctxPrepareDecorators{}, prepareDecorator)
52 }
53
54
55 func GetPrepareDecorators(ctx context.Context, defaultPrepareDecorators ...PrepareDecorator) []PrepareDecorator {
56 inCtx := ctx.Value(ctxPrepareDecorators{})
57 if pd, ok := inCtx.([]PrepareDecorator); ok {
58 return pd
59 }
60 return defaultPrepareDecorators
61 }
62
63
64
65
66
67 type Preparer interface {
68 Prepare(*http.Request) (*http.Request, error)
69 }
70
71
72 type PreparerFunc func(*http.Request) (*http.Request, error)
73
74
75 func (pf PreparerFunc) Prepare(r *http.Request) (*http.Request, error) {
76 return pf(r)
77 }
78
79
80
81 type PrepareDecorator func(Preparer) Preparer
82
83
84
85
86 func CreatePreparer(decorators ...PrepareDecorator) Preparer {
87 return DecoratePreparer(
88 Preparer(PreparerFunc(func(r *http.Request) (*http.Request, error) { return r, nil })),
89 decorators...)
90 }
91
92
93
94
95
96 func DecoratePreparer(p Preparer, decorators ...PrepareDecorator) Preparer {
97 for _, decorate := range decorators {
98 p = decorate(p)
99 }
100 return p
101 }
102
103
104
105 func Prepare(r *http.Request, decorators ...PrepareDecorator) (*http.Request, error) {
106 if r == nil {
107 return nil, NewError("autorest", "Prepare", "Invoked without an http.Request")
108 }
109 return CreatePreparer(decorators...).Prepare(r)
110 }
111
112
113
114 func WithNothing() PrepareDecorator {
115 return func(p Preparer) Preparer {
116 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
117 return p.Prepare(r)
118 })
119 }
120 }
121
122
123
124
125 func WithHeader(header string, value string) PrepareDecorator {
126 return func(p Preparer) Preparer {
127 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
128 r, err := p.Prepare(r)
129 if err == nil {
130 setHeader(r, http.CanonicalHeaderKey(header), value)
131 }
132 return r, err
133 })
134 }
135 }
136
137
138
139
140 func WithHeaders(headers map[string]interface{}) PrepareDecorator {
141 h := ensureValueStrings(headers)
142 return func(p Preparer) Preparer {
143 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
144 r, err := p.Prepare(r)
145 if err == nil {
146 if r.Header == nil {
147 r.Header = make(http.Header)
148 }
149
150 for name, value := range h {
151 r.Header.Set(http.CanonicalHeaderKey(name), value)
152 }
153 }
154 return r, err
155 })
156 }
157 }
158
159
160
161 func WithBearerAuthorization(token string) PrepareDecorator {
162 return WithHeader(headerAuthorization, fmt.Sprintf("Bearer %s", token))
163 }
164
165
166
167 func AsContentType(contentType string) PrepareDecorator {
168 return WithHeader(headerContentType, contentType)
169 }
170
171
172
173 func WithUserAgent(ua string) PrepareDecorator {
174 return WithHeader(headerUserAgent, ua)
175 }
176
177
178
179 func AsFormURLEncoded() PrepareDecorator {
180 return AsContentType(mimeTypeFormPost)
181 }
182
183
184
185 func AsJSON() PrepareDecorator {
186 return AsContentType(mimeTypeJSON)
187 }
188
189
190 func AsOctetStream() PrepareDecorator {
191 return AsContentType(mimeTypeOctetStream)
192 }
193
194
195
196 func WithMethod(method string) PrepareDecorator {
197 return func(p Preparer) Preparer {
198 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
199 r.Method = method
200 return p.Prepare(r)
201 })
202 }
203 }
204
205
206 func AsDelete() PrepareDecorator { return WithMethod("DELETE") }
207
208
209 func AsGet() PrepareDecorator { return WithMethod("GET") }
210
211
212 func AsHead() PrepareDecorator { return WithMethod("HEAD") }
213
214
215 func AsMerge() PrepareDecorator { return WithMethod("MERGE") }
216
217
218 func AsOptions() PrepareDecorator { return WithMethod("OPTIONS") }
219
220
221 func AsPatch() PrepareDecorator { return WithMethod("PATCH") }
222
223
224 func AsPost() PrepareDecorator { return WithMethod("POST") }
225
226
227 func AsPut() PrepareDecorator { return WithMethod("PUT") }
228
229
230
231 func WithBaseURL(baseURL string) PrepareDecorator {
232 return func(p Preparer) Preparer {
233 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
234 r, err := p.Prepare(r)
235 if err == nil {
236 var u *url.URL
237 if u, err = url.Parse(baseURL); err != nil {
238 return r, err
239 }
240 if u.Scheme == "" {
241 return r, fmt.Errorf("autorest: No scheme detected in URL %s", baseURL)
242 }
243 if u.RawQuery != "" {
244
245 u.RawQuery = strings.Replace(u.RawQuery, ";", "%3B", -1)
246 q, err := url.ParseQuery(u.RawQuery)
247 if err != nil {
248 return r, err
249 }
250 u.RawQuery = q.Encode()
251 }
252 r.URL = u
253 }
254 return r, err
255 })
256 }
257 }
258
259
260
261 func WithBytes(input *[]byte) 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 if input == nil {
267 return r, fmt.Errorf("Input Bytes was nil")
268 }
269
270 r.ContentLength = int64(len(*input))
271 r.Body = ioutil.NopCloser(bytes.NewReader(*input))
272 }
273 return r, err
274 })
275 }
276 }
277
278
279
280 func WithCustomBaseURL(baseURL string, urlParameters map[string]interface{}) PrepareDecorator {
281 parameters := ensureValueStrings(urlParameters)
282 for key, value := range parameters {
283 baseURL = strings.Replace(baseURL, "{"+key+"}", value, -1)
284 }
285 return WithBaseURL(baseURL)
286 }
287
288
289
290 func WithFormData(v url.Values) PrepareDecorator {
291 return func(p Preparer) Preparer {
292 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
293 r, err := p.Prepare(r)
294 if err == nil {
295 s := v.Encode()
296
297 setHeader(r, http.CanonicalHeaderKey(headerContentType), mimeTypeFormPost)
298 r.ContentLength = int64(len(s))
299 r.Body = ioutil.NopCloser(strings.NewReader(s))
300 }
301 return r, err
302 })
303 }
304 }
305
306
307
308 func WithMultiPartFormData(formDataParameters map[string]interface{}) PrepareDecorator {
309 return func(p Preparer) Preparer {
310 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
311 r, err := p.Prepare(r)
312 if err == nil {
313 var body bytes.Buffer
314 writer := multipart.NewWriter(&body)
315 for key, value := range formDataParameters {
316 if rc, ok := value.(io.ReadCloser); ok {
317 var fd io.Writer
318 if fd, err = writer.CreateFormFile(key, key); err != nil {
319 return r, err
320 }
321 if _, err = io.Copy(fd, rc); err != nil {
322 return r, err
323 }
324 } else {
325 if err = writer.WriteField(key, ensureValueString(value)); err != nil {
326 return r, err
327 }
328 }
329 }
330 if err = writer.Close(); err != nil {
331 return r, err
332 }
333 setHeader(r, http.CanonicalHeaderKey(headerContentType), writer.FormDataContentType())
334 r.Body = ioutil.NopCloser(bytes.NewReader(body.Bytes()))
335 r.ContentLength = int64(body.Len())
336 return r, err
337 }
338 return r, err
339 })
340 }
341 }
342
343
344 func WithFile(f io.ReadCloser) PrepareDecorator {
345 return func(p Preparer) Preparer {
346 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
347 r, err := p.Prepare(r)
348 if err == nil {
349 b, err := ioutil.ReadAll(f)
350 if err != nil {
351 return r, err
352 }
353 r.Body = ioutil.NopCloser(bytes.NewReader(b))
354 r.ContentLength = int64(len(b))
355 }
356 return r, err
357 })
358 }
359 }
360
361
362
363 func WithBool(v bool) PrepareDecorator {
364 return WithString(fmt.Sprintf("%v", v))
365 }
366
367
368
369 func WithFloat32(v float32) PrepareDecorator {
370 return WithString(fmt.Sprintf("%v", v))
371 }
372
373
374
375 func WithFloat64(v float64) PrepareDecorator {
376 return WithString(fmt.Sprintf("%v", v))
377 }
378
379
380
381 func WithInt32(v int32) PrepareDecorator {
382 return WithString(fmt.Sprintf("%v", v))
383 }
384
385
386
387 func WithInt64(v int64) PrepareDecorator {
388 return WithString(fmt.Sprintf("%v", v))
389 }
390
391
392
393 func WithString(v string) PrepareDecorator {
394 return func(p Preparer) Preparer {
395 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
396 r, err := p.Prepare(r)
397 if err == nil {
398 r.ContentLength = int64(len(v))
399 r.Body = ioutil.NopCloser(strings.NewReader(v))
400 }
401 return r, err
402 })
403 }
404 }
405
406
407
408 func WithJSON(v interface{}) PrepareDecorator {
409 return func(p Preparer) Preparer {
410 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
411 r, err := p.Prepare(r)
412 if err == nil {
413 b, err := json.Marshal(v)
414 if err == nil {
415 r.ContentLength = int64(len(b))
416 r.Body = ioutil.NopCloser(bytes.NewReader(b))
417 }
418 }
419 return r, err
420 })
421 }
422 }
423
424
425
426 func WithXML(v interface{}) PrepareDecorator {
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 b, err := xml.Marshal(v)
432 if err == nil {
433
434 withHeader := xml.Header + string(b)
435 bytesWithHeader := []byte(withHeader)
436
437 r.ContentLength = int64(len(bytesWithHeader))
438 setHeader(r, headerContentLength, fmt.Sprintf("%d", len(bytesWithHeader)))
439 r.Body = ioutil.NopCloser(bytes.NewReader(bytesWithHeader))
440 }
441 }
442 return r, err
443 })
444 }
445 }
446
447
448
449 func WithPath(path string) PrepareDecorator {
450 return func(p Preparer) Preparer {
451 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
452 r, err := p.Prepare(r)
453 if err == nil {
454 if r.URL == nil {
455 return r, NewError("autorest", "WithPath", "Invoked with a nil URL")
456 }
457 if r.URL, err = parseURL(r.URL, path); err != nil {
458 return r, err
459 }
460 }
461 return r, err
462 })
463 }
464 }
465
466
467
468
469 func WithEscapedPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
470 parameters := escapeValueStrings(ensureValueStrings(pathParameters))
471 return func(p Preparer) Preparer {
472 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
473 r, err := p.Prepare(r)
474 if err == nil {
475 if r.URL == nil {
476 return r, NewError("autorest", "WithEscapedPathParameters", "Invoked with a nil URL")
477 }
478 for key, value := range parameters {
479 path = strings.Replace(path, "{"+key+"}", value, -1)
480 }
481 if r.URL, err = parseURL(r.URL, path); err != nil {
482 return r, err
483 }
484 }
485 return r, err
486 })
487 }
488 }
489
490
491
492 func WithPathParameters(path string, pathParameters map[string]interface{}) PrepareDecorator {
493 parameters := ensureValueStrings(pathParameters)
494 return func(p Preparer) Preparer {
495 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
496 r, err := p.Prepare(r)
497 if err == nil {
498 if r.URL == nil {
499 return r, NewError("autorest", "WithPathParameters", "Invoked with a nil URL")
500 }
501 for key, value := range parameters {
502 path = strings.Replace(path, "{"+key+"}", value, -1)
503 }
504
505 if r.URL, err = parseURL(r.URL, path); err != nil {
506 return r, err
507 }
508 }
509 return r, err
510 })
511 }
512 }
513
514 func parseURL(u *url.URL, path string) (*url.URL, error) {
515 p := strings.TrimRight(u.String(), "/")
516 if !strings.HasPrefix(path, "/") {
517 path = "/" + path
518 }
519 return url.Parse(p + path)
520 }
521
522
523
524 func WithQueryParameters(queryParameters map[string]interface{}) PrepareDecorator {
525 parameters := MapToValues(queryParameters)
526 return func(p Preparer) Preparer {
527 return PreparerFunc(func(r *http.Request) (*http.Request, error) {
528 r, err := p.Prepare(r)
529 if err == nil {
530 if r.URL == nil {
531 return r, NewError("autorest", "WithQueryParameters", "Invoked with a nil URL")
532 }
533 v := r.URL.Query()
534 for key, value := range parameters {
535 for i := range value {
536 d, err := url.QueryUnescape(value[i])
537 if err != nil {
538 return r, err
539 }
540 value[i] = d
541 }
542 v[key] = value
543 }
544 r.URL.RawQuery = v.Encode()
545 }
546 return r, err
547 })
548 }
549 }
550
View as plain text