aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/aws/aws-sdk-go/aws/request
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go/aws/request')
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go19
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go11
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go225
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go24
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go58
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/request.go575
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go21
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go9
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go14
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go14
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go236
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go154
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go94
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/validation.go234
-rw-r--r--vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go287
15 files changed, 1975 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go
new file mode 100644
index 0000000..10fc8cb
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error.go
@@ -0,0 +1,19 @@
1// +build !appengine
2
3package request
4
5import (
6 "net"
7 "os"
8 "syscall"
9)
10
11func isErrConnectionReset(err error) bool {
12 if opErr, ok := err.(*net.OpError); ok {
13 if sysErr, ok := opErr.Err.(*os.SyscallError); ok {
14 return sysErr.Err == syscall.ECONNRESET
15 }
16 }
17
18 return false
19}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go
new file mode 100644
index 0000000..996196e
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/connection_reset_error_appengine.go
@@ -0,0 +1,11 @@
1// +build appengine
2
3package request
4
5import (
6 "strings"
7)
8
9func isErrConnectionReset(err error) bool {
10 return strings.Contains(err.Error(), "connection reset")
11}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
new file mode 100644
index 0000000..6c14336
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/handlers.go
@@ -0,0 +1,225 @@
1package request
2
3import (
4 "fmt"
5 "strings"
6)
7
8// A Handlers provides a collection of request handlers for various
9// stages of handling requests.
10type Handlers struct {
11 Validate HandlerList
12 Build HandlerList
13 Sign HandlerList
14 Send HandlerList
15 ValidateResponse HandlerList
16 Unmarshal HandlerList
17 UnmarshalMeta HandlerList
18 UnmarshalError HandlerList
19 Retry HandlerList
20 AfterRetry HandlerList
21 Complete HandlerList
22}
23
24// Copy returns of this handler's lists.
25func (h *Handlers) Copy() Handlers {
26 return Handlers{
27 Validate: h.Validate.copy(),
28 Build: h.Build.copy(),
29 Sign: h.Sign.copy(),
30 Send: h.Send.copy(),
31 ValidateResponse: h.ValidateResponse.copy(),
32 Unmarshal: h.Unmarshal.copy(),
33 UnmarshalError: h.UnmarshalError.copy(),
34 UnmarshalMeta: h.UnmarshalMeta.copy(),
35 Retry: h.Retry.copy(),
36 AfterRetry: h.AfterRetry.copy(),
37 Complete: h.Complete.copy(),
38 }
39}
40
41// Clear removes callback functions for all handlers
42func (h *Handlers) Clear() {
43 h.Validate.Clear()
44 h.Build.Clear()
45 h.Send.Clear()
46 h.Sign.Clear()
47 h.Unmarshal.Clear()
48 h.UnmarshalMeta.Clear()
49 h.UnmarshalError.Clear()
50 h.ValidateResponse.Clear()
51 h.Retry.Clear()
52 h.AfterRetry.Clear()
53 h.Complete.Clear()
54}
55
56// A HandlerListRunItem represents an entry in the HandlerList which
57// is being run.
58type HandlerListRunItem struct {
59 Index int
60 Handler NamedHandler
61 Request *Request
62}
63
64// A HandlerList manages zero or more handlers in a list.
65type HandlerList struct {
66 list []NamedHandler
67
68 // Called after each request handler in the list is called. If set
69 // and the func returns true the HandlerList will continue to iterate
70 // over the request handlers. If false is returned the HandlerList
71 // will stop iterating.
72 //
73 // Should be used if extra logic to be performed between each handler
74 // in the list. This can be used to terminate a list's iteration
75 // based on a condition such as error like, HandlerListStopOnError.
76 // Or for logging like HandlerListLogItem.
77 AfterEachFn func(item HandlerListRunItem) bool
78}
79
80// A NamedHandler is a struct that contains a name and function callback.
81type NamedHandler struct {
82 Name string
83 Fn func(*Request)
84}
85
86// copy creates a copy of the handler list.
87func (l *HandlerList) copy() HandlerList {
88 n := HandlerList{
89 AfterEachFn: l.AfterEachFn,
90 }
91 if len(l.list) == 0 {
92 return n
93 }
94
95 n.list = append(make([]NamedHandler, 0, len(l.list)), l.list...)
96 return n
97}
98
99// Clear clears the handler list.
100func (l *HandlerList) Clear() {
101 l.list = l.list[0:0]
102}
103
104// Len returns the number of handlers in the list.
105func (l *HandlerList) Len() int {
106 return len(l.list)
107}
108
109// PushBack pushes handler f to the back of the handler list.
110func (l *HandlerList) PushBack(f func(*Request)) {
111 l.PushBackNamed(NamedHandler{"__anonymous", f})
112}
113
114// PushBackNamed pushes named handler f to the back of the handler list.
115func (l *HandlerList) PushBackNamed(n NamedHandler) {
116 if cap(l.list) == 0 {
117 l.list = make([]NamedHandler, 0, 5)
118 }
119 l.list = append(l.list, n)
120}
121
122// PushFront pushes handler f to the front of the handler list.
123func (l *HandlerList) PushFront(f func(*Request)) {
124 l.PushFrontNamed(NamedHandler{"__anonymous", f})
125}
126
127// PushFrontNamed pushes named handler f to the front of the handler list.
128func (l *HandlerList) PushFrontNamed(n NamedHandler) {
129 if cap(l.list) == len(l.list) {
130 // Allocating new list required
131 l.list = append([]NamedHandler{n}, l.list...)
132 } else {
133 // Enough room to prepend into list.
134 l.list = append(l.list, NamedHandler{})
135 copy(l.list[1:], l.list)
136 l.list[0] = n
137 }
138}
139
140// Remove removes a NamedHandler n
141func (l *HandlerList) Remove(n NamedHandler) {
142 l.RemoveByName(n.Name)
143}
144
145// RemoveByName removes a NamedHandler by name.
146func (l *HandlerList) RemoveByName(name string) {
147 for i := 0; i < len(l.list); i++ {
148 m := l.list[i]
149 if m.Name == name {
150 // Shift array preventing creating new arrays
151 copy(l.list[i:], l.list[i+1:])
152 l.list[len(l.list)-1] = NamedHandler{}
153 l.list = l.list[:len(l.list)-1]
154
155 // decrement list so next check to length is correct
156 i--
157 }
158 }
159}
160
161// Run executes all handlers in the list with a given request object.
162func (l *HandlerList) Run(r *Request) {
163 for i, h := range l.list {
164 h.Fn(r)
165 item := HandlerListRunItem{
166 Index: i, Handler: h, Request: r,
167 }
168 if l.AfterEachFn != nil && !l.AfterEachFn(item) {
169 return
170 }
171 }
172}
173
174// HandlerListLogItem logs the request handler and the state of the
175// request's Error value. Always returns true to continue iterating
176// request handlers in a HandlerList.
177func HandlerListLogItem(item HandlerListRunItem) bool {
178 if item.Request.Config.Logger == nil {
179 return true
180 }
181 item.Request.Config.Logger.Log("DEBUG: RequestHandler",
182 item.Index, item.Handler.Name, item.Request.Error)
183
184 return true
185}
186
187// HandlerListStopOnError returns false to stop the HandlerList iterating
188// over request handlers if Request.Error is not nil. True otherwise
189// to continue iterating.
190func HandlerListStopOnError(item HandlerListRunItem) bool {
191 return item.Request.Error == nil
192}
193
194// WithAppendUserAgent will add a string to the user agent prefixed with a
195// single white space.
196func WithAppendUserAgent(s string) Option {
197 return func(r *Request) {
198 r.Handlers.Build.PushBack(func(r2 *Request) {
199 AddToUserAgent(r, s)
200 })
201 }
202}
203
204// MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request
205// header. If the extra parameters are provided they will be added as metadata to the
206// name/version pair resulting in the following format.
207// "name/version (extra0; extra1; ...)"
208// The user agent part will be concatenated with this current request's user agent string.
209func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) {
210 ua := fmt.Sprintf("%s/%s", name, version)
211 if len(extra) > 0 {
212 ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; "))
213 }
214 return func(r *Request) {
215 AddToUserAgent(r, ua)
216 }
217}
218
219// MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header.
220// The input string will be concatenated with the current request's user agent string.
221func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) {
222 return func(r *Request) {
223 AddToUserAgent(r, s)
224 }
225}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
new file mode 100644
index 0000000..79f7960
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/http_request.go
@@ -0,0 +1,24 @@
1package request
2
3import (
4 "io"
5 "net/http"
6 "net/url"
7)
8
9func copyHTTPRequest(r *http.Request, body io.ReadCloser) *http.Request {
10 req := new(http.Request)
11 *req = *r
12 req.URL = &url.URL{}
13 *req.URL = *r.URL
14 req.Body = body
15
16 req.Header = http.Header{}
17 for k, v := range r.Header {
18 for _, vv := range v {
19 req.Header.Add(k, vv)
20 }
21 }
22
23 return req
24}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
new file mode 100644
index 0000000..02f07f4
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/offset_reader.go
@@ -0,0 +1,58 @@
1package request
2
3import (
4 "io"
5 "sync"
6)
7
8// offsetReader is a thread-safe io.ReadCloser to prevent racing
9// with retrying requests
10type offsetReader struct {
11 buf io.ReadSeeker
12 lock sync.Mutex
13 closed bool
14}
15
16func newOffsetReader(buf io.ReadSeeker, offset int64) *offsetReader {
17 reader := &offsetReader{}
18 buf.Seek(offset, 0)
19
20 reader.buf = buf
21 return reader
22}
23
24// Close will close the instance of the offset reader's access to
25// the underlying io.ReadSeeker.
26func (o *offsetReader) Close() error {
27 o.lock.Lock()
28 defer o.lock.Unlock()
29 o.closed = true
30 return nil
31}
32
33// Read is a thread-safe read of the underlying io.ReadSeeker
34func (o *offsetReader) Read(p []byte) (int, error) {
35 o.lock.Lock()
36 defer o.lock.Unlock()
37
38 if o.closed {
39 return 0, io.EOF
40 }
41
42 return o.buf.Read(p)
43}
44
45// Seek is a thread-safe seeking operation.
46func (o *offsetReader) Seek(offset int64, whence int) (int64, error) {
47 o.lock.Lock()
48 defer o.lock.Unlock()
49
50 return o.buf.Seek(offset, whence)
51}
52
53// CloseAndCopy will return a new offsetReader with a copy of the old buffer
54// and close the old buffer.
55func (o *offsetReader) CloseAndCopy(offset int64) *offsetReader {
56 o.Close()
57 return newOffsetReader(o.buf, offset)
58}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go
new file mode 100644
index 0000000..4f4f112
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request.go
@@ -0,0 +1,575 @@
1package request
2
3import (
4 "bytes"
5 "fmt"
6 "io"
7 "net"
8 "net/http"
9 "net/url"
10 "reflect"
11 "strings"
12 "time"
13
14 "github.com/aws/aws-sdk-go/aws"
15 "github.com/aws/aws-sdk-go/aws/awserr"
16 "github.com/aws/aws-sdk-go/aws/client/metadata"
17)
18
19const (
20 // ErrCodeSerialization is the serialization error code that is received
21 // during protocol unmarshaling.
22 ErrCodeSerialization = "SerializationError"
23
24 // ErrCodeRead is an error that is returned during HTTP reads.
25 ErrCodeRead = "ReadError"
26
27 // ErrCodeResponseTimeout is the connection timeout error that is recieved
28 // during body reads.
29 ErrCodeResponseTimeout = "ResponseTimeout"
30
31 // CanceledErrorCode is the error code that will be returned by an
32 // API request that was canceled. Requests given a aws.Context may
33 // return this error when canceled.
34 CanceledErrorCode = "RequestCanceled"
35)
36
37// A Request is the service request to be made.
38type Request struct {
39 Config aws.Config
40 ClientInfo metadata.ClientInfo
41 Handlers Handlers
42
43 Retryer
44 Time time.Time
45 ExpireTime time.Duration
46 Operation *Operation
47 HTTPRequest *http.Request
48 HTTPResponse *http.Response
49 Body io.ReadSeeker
50 BodyStart int64 // offset from beginning of Body that the request body starts
51 Params interface{}
52 Error error
53 Data interface{}
54 RequestID string
55 RetryCount int
56 Retryable *bool
57 RetryDelay time.Duration
58 NotHoist bool
59 SignedHeaderVals http.Header
60 LastSignedAt time.Time
61 DisableFollowRedirects bool
62
63 context aws.Context
64
65 built bool
66
67 // Need to persist an intermediate body between the input Body and HTTP
68 // request body because the HTTP Client's transport can maintain a reference
69 // to the HTTP request's body after the client has returned. This value is
70 // safe to use concurrently and wrap the input Body for each HTTP request.
71 safeBody *offsetReader
72}
73
74// An Operation is the service API operation to be made.
75type Operation struct {
76 Name string
77 HTTPMethod string
78 HTTPPath string
79 *Paginator
80
81 BeforePresignFn func(r *Request) error
82}
83
84// New returns a new Request pointer for the service API
85// operation and parameters.
86//
87// Params is any value of input parameters to be the request payload.
88// Data is pointer value to an object which the request's response
89// payload will be deserialized to.
90func New(cfg aws.Config, clientInfo metadata.ClientInfo, handlers Handlers,
91 retryer Retryer, operation *Operation, params interface{}, data interface{}) *Request {
92
93 method := operation.HTTPMethod
94 if method == "" {
95 method = "POST"
96 }
97
98 httpReq, _ := http.NewRequest(method, "", nil)
99
100 var err error
101 httpReq.URL, err = url.Parse(clientInfo.Endpoint + operation.HTTPPath)
102 if err != nil {
103 httpReq.URL = &url.URL{}
104 err = awserr.New("InvalidEndpointURL", "invalid endpoint uri", err)
105 }
106
107 r := &Request{
108 Config: cfg,
109 ClientInfo: clientInfo,
110 Handlers: handlers.Copy(),
111
112 Retryer: retryer,
113 Time: time.Now(),
114 ExpireTime: 0,
115 Operation: operation,
116 HTTPRequest: httpReq,
117 Body: nil,
118 Params: params,
119 Error: err,
120 Data: data,
121 }
122 r.SetBufferBody([]byte{})
123
124 return r
125}
126
127// A Option is a functional option that can augment or modify a request when
128// using a WithContext API operation method.
129type Option func(*Request)
130
131// WithGetResponseHeader builds a request Option which will retrieve a single
132// header value from the HTTP Response. If there are multiple values for the
133// header key use WithGetResponseHeaders instead to access the http.Header
134// map directly. The passed in val pointer must be non-nil.
135//
136// This Option can be used multiple times with a single API operation.
137//
138// var id2, versionID string
139// svc.PutObjectWithContext(ctx, params,
140// request.WithGetResponseHeader("x-amz-id-2", &id2),
141// request.WithGetResponseHeader("x-amz-version-id", &versionID),
142// )
143func WithGetResponseHeader(key string, val *string) Option {
144 return func(r *Request) {
145 r.Handlers.Complete.PushBack(func(req *Request) {
146 *val = req.HTTPResponse.Header.Get(key)
147 })
148 }
149}
150
151// WithGetResponseHeaders builds a request Option which will retrieve the
152// headers from the HTTP response and assign them to the passed in headers
153// variable. The passed in headers pointer must be non-nil.
154//
155// var headers http.Header
156// svc.PutObjectWithContext(ctx, params, request.WithGetResponseHeaders(&headers))
157func WithGetResponseHeaders(headers *http.Header) Option {
158 return func(r *Request) {
159 r.Handlers.Complete.PushBack(func(req *Request) {
160 *headers = req.HTTPResponse.Header
161 })
162 }
163}
164
165// WithLogLevel is a request option that will set the request to use a specific
166// log level when the request is made.
167//
168// svc.PutObjectWithContext(ctx, params, request.WithLogLevel(aws.LogDebugWithHTTPBody)
169func WithLogLevel(l aws.LogLevelType) Option {
170 return func(r *Request) {
171 r.Config.LogLevel = aws.LogLevel(l)
172 }
173}
174
175// ApplyOptions will apply each option to the request calling them in the order
176// the were provided.
177func (r *Request) ApplyOptions(opts ...Option) {
178 for _, opt := range opts {
179 opt(r)
180 }
181}
182
183// Context will always returns a non-nil context. If Request does not have a
184// context aws.BackgroundContext will be returned.
185func (r *Request) Context() aws.Context {
186 if r.context != nil {
187 return r.context
188 }
189 return aws.BackgroundContext()
190}
191
192// SetContext adds a Context to the current request that can be used to cancel
193// a in-flight request. The Context value must not be nil, or this method will
194// panic.
195//
196// Unlike http.Request.WithContext, SetContext does not return a copy of the
197// Request. It is not safe to use use a single Request value for multiple
198// requests. A new Request should be created for each API operation request.
199//
200// Go 1.6 and below:
201// The http.Request's Cancel field will be set to the Done() value of
202// the context. This will overwrite the Cancel field's value.
203//
204// Go 1.7 and above:
205// The http.Request.WithContext will be used to set the context on the underlying
206// http.Request. This will create a shallow copy of the http.Request. The SDK
207// may create sub contexts in the future for nested requests such as retries.
208func (r *Request) SetContext(ctx aws.Context) {
209 if ctx == nil {
210 panic("context cannot be nil")
211 }
212 setRequestContext(r, ctx)
213}
214
215// WillRetry returns if the request's can be retried.
216func (r *Request) WillRetry() bool {
217 return r.Error != nil && aws.BoolValue(r.Retryable) && r.RetryCount < r.MaxRetries()
218}
219
220// ParamsFilled returns if the request's parameters have been populated
221// and the parameters are valid. False is returned if no parameters are
222// provided or invalid.
223func (r *Request) ParamsFilled() bool {
224 return r.Params != nil && reflect.ValueOf(r.Params).Elem().IsValid()
225}
226
227// DataFilled returns true if the request's data for response deserialization
228// target has been set and is a valid. False is returned if data is not
229// set, or is invalid.
230func (r *Request) DataFilled() bool {
231 return r.Data != nil && reflect.ValueOf(r.Data).Elem().IsValid()
232}
233
234// SetBufferBody will set the request's body bytes that will be sent to
235// the service API.
236func (r *Request) SetBufferBody(buf []byte) {
237 r.SetReaderBody(bytes.NewReader(buf))
238}
239
240// SetStringBody sets the body of the request to be backed by a string.
241func (r *Request) SetStringBody(s string) {
242 r.SetReaderBody(strings.NewReader(s))
243}
244
245// SetReaderBody will set the request's body reader.
246func (r *Request) SetReaderBody(reader io.ReadSeeker) {
247 r.Body = reader
248 r.ResetBody()
249}
250
251// Presign returns the request's signed URL. Error will be returned
252// if the signing fails.
253func (r *Request) Presign(expireTime time.Duration) (string, error) {
254 r.ExpireTime = expireTime
255 r.NotHoist = false
256
257 if r.Operation.BeforePresignFn != nil {
258 r = r.copy()
259 err := r.Operation.BeforePresignFn(r)
260 if err != nil {
261 return "", err
262 }
263 }
264
265 r.Sign()
266 if r.Error != nil {
267 return "", r.Error
268 }
269 return r.HTTPRequest.URL.String(), nil
270}
271
272// PresignRequest behaves just like presign, but hoists all headers and signs them.
273// Also returns the signed hash back to the user
274func (r *Request) PresignRequest(expireTime time.Duration) (string, http.Header, error) {
275 r.ExpireTime = expireTime
276 r.NotHoist = true
277 r.Sign()
278 if r.Error != nil {
279 return "", nil, r.Error
280 }
281 return r.HTTPRequest.URL.String(), r.SignedHeaderVals, nil
282}
283
284func debugLogReqError(r *Request, stage string, retrying bool, err error) {
285 if !r.Config.LogLevel.Matches(aws.LogDebugWithRequestErrors) {
286 return
287 }
288
289 retryStr := "not retrying"
290 if retrying {
291 retryStr = "will retry"
292 }
293
294 r.Config.Logger.Log(fmt.Sprintf("DEBUG: %s %s/%s failed, %s, error %v",
295 stage, r.ClientInfo.ServiceName, r.Operation.Name, retryStr, err))
296}
297
298// Build will build the request's object so it can be signed and sent
299// to the service. Build will also validate all the request's parameters.
300// Anny additional build Handlers set on this request will be run
301// in the order they were set.
302//
303// The request will only be built once. Multiple calls to build will have
304// no effect.
305//
306// If any Validate or Build errors occur the build will stop and the error
307// which occurred will be returned.
308func (r *Request) Build() error {
309 if !r.built {
310 r.Handlers.Validate.Run(r)
311 if r.Error != nil {
312 debugLogReqError(r, "Validate Request", false, r.Error)
313 return r.Error
314 }
315 r.Handlers.Build.Run(r)
316 if r.Error != nil {
317 debugLogReqError(r, "Build Request", false, r.Error)
318 return r.Error
319 }
320 r.built = true
321 }
322
323 return r.Error
324}
325
326// Sign will sign the request returning error if errors are encountered.
327//
328// Send will build the request prior to signing. All Sign Handlers will
329// be executed in the order they were set.
330func (r *Request) Sign() error {
331 r.Build()
332 if r.Error != nil {
333 debugLogReqError(r, "Build Request", false, r.Error)
334 return r.Error
335 }
336
337 r.Handlers.Sign.Run(r)
338 return r.Error
339}
340
341// ResetBody rewinds the request body backto its starting position, and
342// set's the HTTP Request body reference. When the body is read prior
343// to being sent in the HTTP request it will need to be rewound.
344func (r *Request) ResetBody() {
345 if r.safeBody != nil {
346 r.safeBody.Close()
347 }
348
349 r.safeBody = newOffsetReader(r.Body, r.BodyStart)
350
351 // Go 1.8 tightened and clarified the rules code needs to use when building
352 // requests with the http package. Go 1.8 removed the automatic detection
353 // of if the Request.Body was empty, or actually had bytes in it. The SDK
354 // always sets the Request.Body even if it is empty and should not actually
355 // be sent. This is incorrect.
356 //
357 // Go 1.8 did add a http.NoBody value that the SDK can use to tell the http
358 // client that the request really should be sent without a body. The
359 // Request.Body cannot be set to nil, which is preferable, because the
360 // field is exported and could introduce nil pointer dereferences for users
361 // of the SDK if they used that field.
362 //
363 // Related golang/go#18257
364 l, err := computeBodyLength(r.Body)
365 if err != nil {
366 r.Error = awserr.New(ErrCodeSerialization, "failed to compute request body size", err)
367 return
368 }
369
370 if l == 0 {
371 r.HTTPRequest.Body = noBodyReader
372 } else if l > 0 {
373 r.HTTPRequest.Body = r.safeBody
374 } else {
375 // Hack to prevent sending bodies for methods where the body
376 // should be ignored by the server. Sending bodies on these
377 // methods without an associated ContentLength will cause the
378 // request to socket timeout because the server does not handle
379 // Transfer-Encoding: chunked bodies for these methods.
380 //
381 // This would only happen if a aws.ReaderSeekerCloser was used with
382 // a io.Reader that was not also an io.Seeker.
383 switch r.Operation.HTTPMethod {
384 case "GET", "HEAD", "DELETE":
385 r.HTTPRequest.Body = noBodyReader
386 default:
387 r.HTTPRequest.Body = r.safeBody
388 }
389 }
390}
391
392// Attempts to compute the length of the body of the reader using the
393// io.Seeker interface. If the value is not seekable because of being
394// a ReaderSeekerCloser without an unerlying Seeker -1 will be returned.
395// If no error occurs the length of the body will be returned.
396func computeBodyLength(r io.ReadSeeker) (int64, error) {
397 seekable := true
398 // Determine if the seeker is actually seekable. ReaderSeekerCloser
399 // hides the fact that a io.Readers might not actually be seekable.
400 switch v := r.(type) {
401 case aws.ReaderSeekerCloser:
402 seekable = v.IsSeeker()
403 case *aws.ReaderSeekerCloser:
404 seekable = v.IsSeeker()
405 }
406 if !seekable {
407 return -1, nil
408 }
409
410 curOffset, err := r.Seek(0, 1)
411 if err != nil {
412 return 0, err
413 }
414
415 endOffset, err := r.Seek(0, 2)
416 if err != nil {
417 return 0, err
418 }
419
420 _, err = r.Seek(curOffset, 0)
421 if err != nil {
422 return 0, err
423 }
424
425 return endOffset - curOffset, nil
426}
427
428// GetBody will return an io.ReadSeeker of the Request's underlying
429// input body with a concurrency safe wrapper.
430func (r *Request) GetBody() io.ReadSeeker {
431 return r.safeBody
432}
433
434// Send will send the request returning error if errors are encountered.
435//
436// Send will sign the request prior to sending. All Send Handlers will
437// be executed in the order they were set.
438//
439// Canceling a request is non-deterministic. If a request has been canceled,
440// then the transport will choose, randomly, one of the state channels during
441// reads or getting the connection.
442//
443// readLoop() and getConn(req *Request, cm connectMethod)
444// https://github.com/golang/go/blob/master/src/net/http/transport.go
445//
446// Send will not close the request.Request's body.
447func (r *Request) Send() error {
448 defer func() {
449 // Regardless of success or failure of the request trigger the Complete
450 // request handlers.
451 r.Handlers.Complete.Run(r)
452 }()
453
454 for {
455 if aws.BoolValue(r.Retryable) {
456 if r.Config.LogLevel.Matches(aws.LogDebugWithRequestRetries) {
457 r.Config.Logger.Log(fmt.Sprintf("DEBUG: Retrying Request %s/%s, attempt %d",
458 r.ClientInfo.ServiceName, r.Operation.Name, r.RetryCount))
459 }
460
461 // The previous http.Request will have a reference to the r.Body
462 // and the HTTP Client's Transport may still be reading from
463 // the request's body even though the Client's Do returned.
464 r.HTTPRequest = copyHTTPRequest(r.HTTPRequest, nil)
465 r.ResetBody()
466
467 // Closing response body to ensure that no response body is leaked
468 // between retry attempts.
469 if r.HTTPResponse != nil && r.HTTPResponse.Body != nil {
470 r.HTTPResponse.Body.Close()
471 }
472 }
473
474 r.Sign()
475 if r.Error != nil {
476 return r.Error
477 }
478
479 r.Retryable = nil
480
481 r.Handlers.Send.Run(r)
482 if r.Error != nil {
483 if !shouldRetryCancel(r) {
484 return r.Error
485 }
486
487 err := r.Error
488 r.Handlers.Retry.Run(r)
489 r.Handlers.AfterRetry.Run(r)
490 if r.Error != nil {
491 debugLogReqError(r, "Send Request", false, r.Error)
492 return r.Error
493 }
494 debugLogReqError(r, "Send Request", true, err)
495 continue
496 }
497 r.Handlers.UnmarshalMeta.Run(r)
498 r.Handlers.ValidateResponse.Run(r)
499 if r.Error != nil {
500 err := r.Error
501 r.Handlers.UnmarshalError.Run(r)
502 r.Handlers.Retry.Run(r)
503 r.Handlers.AfterRetry.Run(r)
504 if r.Error != nil {
505 debugLogReqError(r, "Validate Response", false, r.Error)
506 return r.Error
507 }
508 debugLogReqError(r, "Validate Response", true, err)
509 continue
510 }
511
512 r.Handlers.Unmarshal.Run(r)
513 if r.Error != nil {
514 err := r.Error
515 r.Handlers.Retry.Run(r)
516 r.Handlers.AfterRetry.Run(r)
517 if r.Error != nil {
518 debugLogReqError(r, "Unmarshal Response", false, r.Error)
519 return r.Error
520 }
521 debugLogReqError(r, "Unmarshal Response", true, err)
522 continue
523 }
524
525 break
526 }
527
528 return nil
529}
530
531// copy will copy a request which will allow for local manipulation of the
532// request.
533func (r *Request) copy() *Request {
534 req := &Request{}
535 *req = *r
536 req.Handlers = r.Handlers.Copy()
537 op := *r.Operation
538 req.Operation = &op
539 return req
540}
541
542// AddToUserAgent adds the string to the end of the request's current user agent.
543func AddToUserAgent(r *Request, s string) {
544 curUA := r.HTTPRequest.Header.Get("User-Agent")
545 if len(curUA) > 0 {
546 s = curUA + " " + s
547 }
548 r.HTTPRequest.Header.Set("User-Agent", s)
549}
550
551func shouldRetryCancel(r *Request) bool {
552 awsErr, ok := r.Error.(awserr.Error)
553 timeoutErr := false
554 errStr := r.Error.Error()
555 if ok {
556 if awsErr.Code() == CanceledErrorCode {
557 return false
558 }
559 err := awsErr.OrigErr()
560 netErr, netOK := err.(net.Error)
561 timeoutErr = netOK && netErr.Temporary()
562 if urlErr, ok := err.(*url.Error); !timeoutErr && ok {
563 errStr = urlErr.Err.Error()
564 }
565 }
566
567 // There can be two types of canceled errors here.
568 // The first being a net.Error and the other being an error.
569 // If the request was timed out, we want to continue the retry
570 // process. Otherwise, return the canceled error.
571 return timeoutErr ||
572 (errStr != "net/http: request canceled" &&
573 errStr != "net/http: request canceled while waiting for connection")
574
575}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
new file mode 100644
index 0000000..1323af9
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_7.go
@@ -0,0 +1,21 @@
1// +build !go1.8
2
3package request
4
5import "io"
6
7// NoBody is an io.ReadCloser with no bytes. Read always returns EOF
8// and Close always returns nil. It can be used in an outgoing client
9// request to explicitly signal that a request has zero bytes.
10// An alternative, however, is to simply set Request.Body to nil.
11//
12// Copy of Go 1.8 NoBody type from net/http/http.go
13type noBody struct{}
14
15func (noBody) Read([]byte) (int, error) { return 0, io.EOF }
16func (noBody) Close() error { return nil }
17func (noBody) WriteTo(io.Writer) (int64, error) { return 0, nil }
18
19// Is an empty reader that will trigger the Go HTTP client to not include
20// and body in the HTTP request.
21var noBodyReader = noBody{}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
new file mode 100644
index 0000000..8b963f4
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_1_8.go
@@ -0,0 +1,9 @@
1// +build go1.8
2
3package request
4
5import "net/http"
6
7// Is a http.NoBody reader instructing Go HTTP client to not include
8// and body in the HTTP request.
9var noBodyReader = http.NoBody
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go
new file mode 100644
index 0000000..a7365cd
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context.go
@@ -0,0 +1,14 @@
1// +build go1.7
2
3package request
4
5import "github.com/aws/aws-sdk-go/aws"
6
7// setContext updates the Request to use the passed in context for cancellation.
8// Context will also be used for request retry delay.
9//
10// Creates shallow copy of the http.Request with the WithContext method.
11func setRequestContext(r *Request, ctx aws.Context) {
12 r.context = ctx
13 r.HTTPRequest = r.HTTPRequest.WithContext(ctx)
14}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go
new file mode 100644
index 0000000..307fa07
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_context_1_6.go
@@ -0,0 +1,14 @@
1// +build !go1.7
2
3package request
4
5import "github.com/aws/aws-sdk-go/aws"
6
7// setContext updates the Request to use the passed in context for cancellation.
8// Context will also be used for request retry delay.
9//
10// Creates shallow copy of the http.Request with the WithContext method.
11func setRequestContext(r *Request, ctx aws.Context) {
12 r.context = ctx
13 r.HTTPRequest.Cancel = ctx.Done()
14}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
new file mode 100644
index 0000000..59de673
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/request_pagination.go
@@ -0,0 +1,236 @@
1package request
2
3import (
4 "reflect"
5 "sync/atomic"
6
7 "github.com/aws/aws-sdk-go/aws"
8 "github.com/aws/aws-sdk-go/aws/awsutil"
9)
10
11// A Pagination provides paginating of SDK API operations which are paginatable.
12// Generally you should not use this type directly, but use the "Pages" API
13// operations method to automatically perform pagination for you. Such as,
14// "S3.ListObjectsPages", and "S3.ListObjectsPagesWithContext" methods.
15//
16// Pagination differs from a Paginator type in that pagination is the type that
17// does the pagination between API operations, and Paginator defines the
18// configuration that will be used per page request.
19//
20// cont := true
21// for p.Next() && cont {
22// data := p.Page().(*s3.ListObjectsOutput)
23// // process the page's data
24// }
25// return p.Err()
26//
27// See service client API operation Pages methods for examples how the SDK will
28// use the Pagination type.
29type Pagination struct {
30 // Function to return a Request value for each pagination request.
31 // Any configuration or handlers that need to be applied to the request
32 // prior to getting the next page should be done here before the request
33 // returned.
34 //
35 // NewRequest should always be built from the same API operations. It is
36 // undefined if different API operations are returned on subsequent calls.
37 NewRequest func() (*Request, error)
38
39 started bool
40 nextTokens []interface{}
41
42 err error
43 curPage interface{}
44}
45
46// HasNextPage will return true if Pagination is able to determine that the API
47// operation has additional pages. False will be returned if there are no more
48// pages remaining.
49//
50// Will always return true if Next has not been called yet.
51func (p *Pagination) HasNextPage() bool {
52 return !(p.started && len(p.nextTokens) == 0)
53}
54
55// Err returns the error Pagination encountered when retrieving the next page.
56func (p *Pagination) Err() error {
57 return p.err
58}
59
60// Page returns the current page. Page should only be called after a successful
61// call to Next. It is undefined what Page will return if Page is called after
62// Next returns false.
63func (p *Pagination) Page() interface{} {
64 return p.curPage
65}
66
67// Next will attempt to retrieve the next page for the API operation. When a page
68// is retrieved true will be returned. If the page cannot be retrieved, or there
69// are no more pages false will be returned.
70//
71// Use the Page method to retrieve the current page data. The data will need
72// to be cast to the API operation's output type.
73//
74// Use the Err method to determine if an error occurred if Page returns false.
75func (p *Pagination) Next() bool {
76 if !p.HasNextPage() {
77 return false
78 }
79
80 req, err := p.NewRequest()
81 if err != nil {
82 p.err = err
83 return false
84 }
85
86 if p.started {
87 for i, intok := range req.Operation.InputTokens {
88 awsutil.SetValueAtPath(req.Params, intok, p.nextTokens[i])
89 }
90 }
91 p.started = true
92
93 err = req.Send()
94 if err != nil {
95 p.err = err
96 return false
97 }
98
99 p.nextTokens = req.nextPageTokens()
100 p.curPage = req.Data
101
102 return true
103}
104
105// A Paginator is the configuration data that defines how an API operation
106// should be paginated. This type is used by the API service models to define
107// the generated pagination config for service APIs.
108//
109// The Pagination type is what provides iterating between pages of an API. It
110// is only used to store the token metadata the SDK should use for performing
111// pagination.
112type Paginator struct {
113 InputTokens []string
114 OutputTokens []string
115 LimitToken string
116 TruncationToken string
117}
118
119// nextPageTokens returns the tokens to use when asking for the next page of data.
120func (r *Request) nextPageTokens() []interface{} {
121 if r.Operation.Paginator == nil {
122 return nil
123 }
124 if r.Operation.TruncationToken != "" {
125 tr, _ := awsutil.ValuesAtPath(r.Data, r.Operation.TruncationToken)
126 if len(tr) == 0 {
127 return nil
128 }
129
130 switch v := tr[0].(type) {
131 case *bool:
132 if !aws.BoolValue(v) {
133 return nil
134 }
135 case bool:
136 if v == false {
137 return nil
138 }
139 }
140 }
141
142 tokens := []interface{}{}
143 tokenAdded := false
144 for _, outToken := range r.Operation.OutputTokens {
145 v, _ := awsutil.ValuesAtPath(r.Data, outToken)
146 if len(v) > 0 {
147 tokens = append(tokens, v[0])
148 tokenAdded = true
149 } else {
150 tokens = append(tokens, nil)
151 }
152 }
153 if !tokenAdded {
154 return nil
155 }
156
157 return tokens
158}
159
160// Ensure a deprecated item is only logged once instead of each time its used.
161func logDeprecatedf(logger aws.Logger, flag *int32, msg string) {
162 if logger == nil {
163 return
164 }
165 if atomic.CompareAndSwapInt32(flag, 0, 1) {
166 logger.Log(msg)
167 }
168}
169
170var (
171 logDeprecatedHasNextPage int32
172 logDeprecatedNextPage int32
173 logDeprecatedEachPage int32
174)
175
176// HasNextPage returns true if this request has more pages of data available.
177//
178// Deprecated Use Pagination type for configurable pagination of API operations
179func (r *Request) HasNextPage() bool {
180 logDeprecatedf(r.Config.Logger, &logDeprecatedHasNextPage,
181 "Request.HasNextPage deprecated. Use Pagination type for configurable pagination of API operations")
182
183 return len(r.nextPageTokens()) > 0
184}
185
186// NextPage returns a new Request that can be executed to return the next
187// page of result data. Call .Send() on this request to execute it.
188//
189// Deprecated Use Pagination type for configurable pagination of API operations
190func (r *Request) NextPage() *Request {
191 logDeprecatedf(r.Config.Logger, &logDeprecatedNextPage,
192 "Request.NextPage deprecated. Use Pagination type for configurable pagination of API operations")
193
194 tokens := r.nextPageTokens()
195 if len(tokens) == 0 {
196 return nil
197 }
198
199 data := reflect.New(reflect.TypeOf(r.Data).Elem()).Interface()
200 nr := New(r.Config, r.ClientInfo, r.Handlers, r.Retryer, r.Operation, awsutil.CopyOf(r.Params), data)
201 for i, intok := range nr.Operation.InputTokens {
202 awsutil.SetValueAtPath(nr.Params, intok, tokens[i])
203 }
204 return nr
205}
206
207// EachPage iterates over each page of a paginated request object. The fn
208// parameter should be a function with the following sample signature:
209//
210// func(page *T, lastPage bool) bool {
211// return true // return false to stop iterating
212// }
213//
214// Where "T" is the structure type matching the output structure of the given
215// operation. For example, a request object generated by
216// DynamoDB.ListTablesRequest() would expect to see dynamodb.ListTablesOutput
217// as the structure "T". The lastPage value represents whether the page is
218// the last page of data or not. The return value of this function should
219// return true to keep iterating or false to stop.
220//
221// Deprecated Use Pagination type for configurable pagination of API operations
222func (r *Request) EachPage(fn func(data interface{}, isLastPage bool) (shouldContinue bool)) error {
223 logDeprecatedf(r.Config.Logger, &logDeprecatedEachPage,
224 "Request.EachPage deprecated. Use Pagination type for configurable pagination of API operations")
225
226 for page := r; page != nil; page = page.NextPage() {
227 if err := page.Send(); err != nil {
228 return err
229 }
230 if getNextPage := fn(page.Data, !page.HasNextPage()); !getNextPage {
231 return page.Error
232 }
233 }
234
235 return nil
236}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
new file mode 100644
index 0000000..7af81de
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/retryer.go
@@ -0,0 +1,154 @@
1package request
2
3import (
4 "time"
5
6 "github.com/aws/aws-sdk-go/aws"
7 "github.com/aws/aws-sdk-go/aws/awserr"
8)
9
10// Retryer is an interface to control retry logic for a given service.
11// The default implementation used by most services is the service.DefaultRetryer
12// structure, which contains basic retry logic using exponential backoff.
13type Retryer interface {
14 RetryRules(*Request) time.Duration
15 ShouldRetry(*Request) bool
16 MaxRetries() int
17}
18
19// WithRetryer sets a config Retryer value to the given Config returning it
20// for chaining.
21func WithRetryer(cfg *aws.Config, retryer Retryer) *aws.Config {
22 cfg.Retryer = retryer
23 return cfg
24}
25
26// retryableCodes is a collection of service response codes which are retry-able
27// without any further action.
28var retryableCodes = map[string]struct{}{
29 "RequestError": {},
30 "RequestTimeout": {},
31 ErrCodeResponseTimeout: {},
32 "RequestTimeoutException": {}, // Glacier's flavor of RequestTimeout
33}
34
35var throttleCodes = map[string]struct{}{
36 "ProvisionedThroughputExceededException": {},
37 "Throttling": {},
38 "ThrottlingException": {},
39 "RequestLimitExceeded": {},
40 "RequestThrottled": {},
41 "LimitExceededException": {}, // Deleting 10+ DynamoDb tables at once
42 "TooManyRequestsException": {}, // Lambda functions
43 "PriorRequestNotComplete": {}, // Route53
44}
45
46// credsExpiredCodes is a collection of error codes which signify the credentials
47// need to be refreshed. Expired tokens require refreshing of credentials, and
48// resigning before the request can be retried.
49var credsExpiredCodes = map[string]struct{}{
50 "ExpiredToken": {},
51 "ExpiredTokenException": {},
52 "RequestExpired": {}, // EC2 Only
53}
54
55func isCodeThrottle(code string) bool {
56 _, ok := throttleCodes[code]
57 return ok
58}
59
60func isCodeRetryable(code string) bool {
61 if _, ok := retryableCodes[code]; ok {
62 return true
63 }
64
65 return isCodeExpiredCreds(code)
66}
67
68func isCodeExpiredCreds(code string) bool {
69 _, ok := credsExpiredCodes[code]
70 return ok
71}
72
73var validParentCodes = map[string]struct{}{
74 ErrCodeSerialization: struct{}{},
75 ErrCodeRead: struct{}{},
76}
77
78func isNestedErrorRetryable(parentErr awserr.Error) bool {
79 if parentErr == nil {
80 return false
81 }
82
83 if _, ok := validParentCodes[parentErr.Code()]; !ok {
84 return false
85 }
86
87 err := parentErr.OrigErr()
88 if err == nil {
89 return false
90 }
91
92 if aerr, ok := err.(awserr.Error); ok {
93 return isCodeRetryable(aerr.Code())
94 }
95
96 return isErrConnectionReset(err)
97}
98
99// IsErrorRetryable returns whether the error is retryable, based on its Code.
100// Returns false if error is nil.
101func IsErrorRetryable(err error) bool {
102 if err != nil {
103 if aerr, ok := err.(awserr.Error); ok {
104 return isCodeRetryable(aerr.Code()) || isNestedErrorRetryable(aerr)
105 }
106 }
107 return false
108}
109
110// IsErrorThrottle returns whether the error is to be throttled based on its code.
111// Returns false if error is nil.
112func IsErrorThrottle(err error) bool {
113 if err != nil {
114 if aerr, ok := err.(awserr.Error); ok {
115 return isCodeThrottle(aerr.Code())
116 }
117 }
118 return false
119}
120
121// IsErrorExpiredCreds returns whether the error code is a credential expiry error.
122// Returns false if error is nil.
123func IsErrorExpiredCreds(err error) bool {
124 if err != nil {
125 if aerr, ok := err.(awserr.Error); ok {
126 return isCodeExpiredCreds(aerr.Code())
127 }
128 }
129 return false
130}
131
132// IsErrorRetryable returns whether the error is retryable, based on its Code.
133// Returns false if the request has no Error set.
134//
135// Alias for the utility function IsErrorRetryable
136func (r *Request) IsErrorRetryable() bool {
137 return IsErrorRetryable(r.Error)
138}
139
140// IsErrorThrottle returns whether the error is to be throttled based on its code.
141// Returns false if the request has no Error set
142//
143// Alias for the utility function IsErrorThrottle
144func (r *Request) IsErrorThrottle() bool {
145 return IsErrorThrottle(r.Error)
146}
147
148// IsErrorExpired returns whether the error code is a credential expiry error.
149// Returns false if the request has no Error set.
150//
151// Alias for the utility function IsErrorExpiredCreds
152func (r *Request) IsErrorExpired() bool {
153 return IsErrorExpiredCreds(r.Error)
154}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go
new file mode 100644
index 0000000..09a44eb
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/timeout_read_closer.go
@@ -0,0 +1,94 @@
1package request
2
3import (
4 "io"
5 "time"
6
7 "github.com/aws/aws-sdk-go/aws/awserr"
8)
9
10var timeoutErr = awserr.New(
11 ErrCodeResponseTimeout,
12 "read on body has reached the timeout limit",
13 nil,
14)
15
16type readResult struct {
17 n int
18 err error
19}
20
21// timeoutReadCloser will handle body reads that take too long.
22// We will return a ErrReadTimeout error if a timeout occurs.
23type timeoutReadCloser struct {
24 reader io.ReadCloser
25 duration time.Duration
26}
27
28// Read will spin off a goroutine to call the reader's Read method. We will
29// select on the timer's channel or the read's channel. Whoever completes first
30// will be returned.
31func (r *timeoutReadCloser) Read(b []byte) (int, error) {
32 timer := time.NewTimer(r.duration)
33 c := make(chan readResult, 1)
34
35 go func() {
36 n, err := r.reader.Read(b)
37 timer.Stop()
38 c <- readResult{n: n, err: err}
39 }()
40
41 select {
42 case data := <-c:
43 return data.n, data.err
44 case <-timer.C:
45 return 0, timeoutErr
46 }
47}
48
49func (r *timeoutReadCloser) Close() error {
50 return r.reader.Close()
51}
52
53const (
54 // HandlerResponseTimeout is what we use to signify the name of the
55 // response timeout handler.
56 HandlerResponseTimeout = "ResponseTimeoutHandler"
57)
58
59// adaptToResponseTimeoutError is a handler that will replace any top level error
60// to a ErrCodeResponseTimeout, if its child is that.
61func adaptToResponseTimeoutError(req *Request) {
62 if err, ok := req.Error.(awserr.Error); ok {
63 aerr, ok := err.OrigErr().(awserr.Error)
64 if ok && aerr.Code() == ErrCodeResponseTimeout {
65 req.Error = aerr
66 }
67 }
68}
69
70// WithResponseReadTimeout is a request option that will wrap the body in a timeout read closer.
71// This will allow for per read timeouts. If a timeout occurred, we will return the
72// ErrCodeResponseTimeout.
73//
74// svc.PutObjectWithContext(ctx, params, request.WithTimeoutReadCloser(30 * time.Second)
75func WithResponseReadTimeout(duration time.Duration) Option {
76 return func(r *Request) {
77
78 var timeoutHandler = NamedHandler{
79 HandlerResponseTimeout,
80 func(req *Request) {
81 req.HTTPResponse.Body = &timeoutReadCloser{
82 reader: req.HTTPResponse.Body,
83 duration: duration,
84 }
85 }}
86
87 // remove the handler so we are not stomping over any new durations.
88 r.Handlers.Send.RemoveByName(HandlerResponseTimeout)
89 r.Handlers.Send.PushBackNamed(timeoutHandler)
90
91 r.Handlers.Unmarshal.PushBack(adaptToResponseTimeoutError)
92 r.Handlers.UnmarshalError.PushBack(adaptToResponseTimeoutError)
93 }
94}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go b/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
new file mode 100644
index 0000000..2520286
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/validation.go
@@ -0,0 +1,234 @@
1package request
2
3import (
4 "bytes"
5 "fmt"
6
7 "github.com/aws/aws-sdk-go/aws/awserr"
8)
9
10const (
11 // InvalidParameterErrCode is the error code for invalid parameters errors
12 InvalidParameterErrCode = "InvalidParameter"
13 // ParamRequiredErrCode is the error code for required parameter errors
14 ParamRequiredErrCode = "ParamRequiredError"
15 // ParamMinValueErrCode is the error code for fields with too low of a
16 // number value.
17 ParamMinValueErrCode = "ParamMinValueError"
18 // ParamMinLenErrCode is the error code for fields without enough elements.
19 ParamMinLenErrCode = "ParamMinLenError"
20)
21
22// Validator provides a way for types to perform validation logic on their
23// input values that external code can use to determine if a type's values
24// are valid.
25type Validator interface {
26 Validate() error
27}
28
29// An ErrInvalidParams provides wrapping of invalid parameter errors found when
30// validating API operation input parameters.
31type ErrInvalidParams struct {
32 // Context is the base context of the invalid parameter group.
33 Context string
34 errs []ErrInvalidParam
35}
36
37// Add adds a new invalid parameter error to the collection of invalid
38// parameters. The context of the invalid parameter will be updated to reflect
39// this collection.
40func (e *ErrInvalidParams) Add(err ErrInvalidParam) {
41 err.SetContext(e.Context)
42 e.errs = append(e.errs, err)
43}
44
45// AddNested adds the invalid parameter errors from another ErrInvalidParams
46// value into this collection. The nested errors will have their nested context
47// updated and base context to reflect the merging.
48//
49// Use for nested validations errors.
50func (e *ErrInvalidParams) AddNested(nestedCtx string, nested ErrInvalidParams) {
51 for _, err := range nested.errs {
52 err.SetContext(e.Context)
53 err.AddNestedContext(nestedCtx)
54 e.errs = append(e.errs, err)
55 }
56}
57
58// Len returns the number of invalid parameter errors
59func (e ErrInvalidParams) Len() int {
60 return len(e.errs)
61}
62
63// Code returns the code of the error
64func (e ErrInvalidParams) Code() string {
65 return InvalidParameterErrCode
66}
67
68// Message returns the message of the error
69func (e ErrInvalidParams) Message() string {
70 return fmt.Sprintf("%d validation error(s) found.", len(e.errs))
71}
72
73// Error returns the string formatted form of the invalid parameters.
74func (e ErrInvalidParams) Error() string {
75 w := &bytes.Buffer{}
76 fmt.Fprintf(w, "%s: %s\n", e.Code(), e.Message())
77
78 for _, err := range e.errs {
79 fmt.Fprintf(w, "- %s\n", err.Message())
80 }
81
82 return w.String()
83}
84
85// OrigErr returns the invalid parameters as a awserr.BatchedErrors value
86func (e ErrInvalidParams) OrigErr() error {
87 return awserr.NewBatchError(
88 InvalidParameterErrCode, e.Message(), e.OrigErrs())
89}
90
91// OrigErrs returns a slice of the invalid parameters
92func (e ErrInvalidParams) OrigErrs() []error {
93 errs := make([]error, len(e.errs))
94 for i := 0; i < len(errs); i++ {
95 errs[i] = e.errs[i]
96 }
97
98 return errs
99}
100
101// An ErrInvalidParam represents an invalid parameter error type.
102type ErrInvalidParam interface {
103 awserr.Error
104
105 // Field name the error occurred on.
106 Field() string
107
108 // SetContext updates the context of the error.
109 SetContext(string)
110
111 // AddNestedContext updates the error's context to include a nested level.
112 AddNestedContext(string)
113}
114
115type errInvalidParam struct {
116 context string
117 nestedContext string
118 field string
119 code string
120 msg string
121}
122
123// Code returns the error code for the type of invalid parameter.
124func (e *errInvalidParam) Code() string {
125 return e.code
126}
127
128// Message returns the reason the parameter was invalid, and its context.
129func (e *errInvalidParam) Message() string {
130 return fmt.Sprintf("%s, %s.", e.msg, e.Field())
131}
132
133// Error returns the string version of the invalid parameter error.
134func (e *errInvalidParam) Error() string {
135 return fmt.Sprintf("%s: %s", e.code, e.Message())
136}
137
138// OrigErr returns nil, Implemented for awserr.Error interface.
139func (e *errInvalidParam) OrigErr() error {
140 return nil
141}
142
143// Field Returns the field and context the error occurred.
144func (e *errInvalidParam) Field() string {
145 field := e.context
146 if len(field) > 0 {
147 field += "."
148 }
149 if len(e.nestedContext) > 0 {
150 field += fmt.Sprintf("%s.", e.nestedContext)
151 }
152 field += e.field
153
154 return field
155}
156
157// SetContext updates the base context of the error.
158func (e *errInvalidParam) SetContext(ctx string) {
159 e.context = ctx
160}
161
162// AddNestedContext prepends a context to the field's path.
163func (e *errInvalidParam) AddNestedContext(ctx string) {
164 if len(e.nestedContext) == 0 {
165 e.nestedContext = ctx
166 } else {
167 e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext)
168 }
169
170}
171
172// An ErrParamRequired represents an required parameter error.
173type ErrParamRequired struct {
174 errInvalidParam
175}
176
177// NewErrParamRequired creates a new required parameter error.
178func NewErrParamRequired(field string) *ErrParamRequired {
179 return &ErrParamRequired{
180 errInvalidParam{
181 code: ParamRequiredErrCode,
182 field: field,
183 msg: fmt.Sprintf("missing required field"),
184 },
185 }
186}
187
188// An ErrParamMinValue represents a minimum value parameter error.
189type ErrParamMinValue struct {
190 errInvalidParam
191 min float64
192}
193
194// NewErrParamMinValue creates a new minimum value parameter error.
195func NewErrParamMinValue(field string, min float64) *ErrParamMinValue {
196 return &ErrParamMinValue{
197 errInvalidParam: errInvalidParam{
198 code: ParamMinValueErrCode,
199 field: field,
200 msg: fmt.Sprintf("minimum field value of %v", min),
201 },
202 min: min,
203 }
204}
205
206// MinValue returns the field's require minimum value.
207//
208// float64 is returned for both int and float min values.
209func (e *ErrParamMinValue) MinValue() float64 {
210 return e.min
211}
212
213// An ErrParamMinLen represents a minimum length parameter error.
214type ErrParamMinLen struct {
215 errInvalidParam
216 min int
217}
218
219// NewErrParamMinLen creates a new minimum length parameter error.
220func NewErrParamMinLen(field string, min int) *ErrParamMinLen {
221 return &ErrParamMinLen{
222 errInvalidParam: errInvalidParam{
223 code: ParamMinValueErrCode,
224 field: field,
225 msg: fmt.Sprintf("minimum field size of %v", min),
226 },
227 min: min,
228 }
229}
230
231// MinLen returns the field's required minimum length.
232func (e *ErrParamMinLen) MinLen() int {
233 return e.min
234}
diff --git a/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
new file mode 100644
index 0000000..22d2f80
--- /dev/null
+++ b/vendor/github.com/aws/aws-sdk-go/aws/request/waiter.go
@@ -0,0 +1,287 @@
1package request
2
3import (
4 "fmt"
5 "time"
6
7 "github.com/aws/aws-sdk-go/aws"
8 "github.com/aws/aws-sdk-go/aws/awserr"
9 "github.com/aws/aws-sdk-go/aws/awsutil"
10)
11
12// WaiterResourceNotReadyErrorCode is the error code returned by a waiter when
13// the waiter's max attempts have been exhausted.
14const WaiterResourceNotReadyErrorCode = "ResourceNotReady"
15
16// A WaiterOption is a function that will update the Waiter value's fields to
17// configure the waiter.
18type WaiterOption func(*Waiter)
19
20// WithWaiterMaxAttempts returns the maximum number of times the waiter should
21// attempt to check the resource for the target state.
22func WithWaiterMaxAttempts(max int) WaiterOption {
23 return func(w *Waiter) {
24 w.MaxAttempts = max
25 }
26}
27
28// WaiterDelay will return a delay the waiter should pause between attempts to
29// check the resource state. The passed in attempt is the number of times the
30// Waiter has checked the resource state.
31//
32// Attempt is the number of attempts the Waiter has made checking the resource
33// state.
34type WaiterDelay func(attempt int) time.Duration
35
36// ConstantWaiterDelay returns a WaiterDelay that will always return a constant
37// delay the waiter should use between attempts. It ignores the number of
38// attempts made.
39func ConstantWaiterDelay(delay time.Duration) WaiterDelay {
40 return func(attempt int) time.Duration {
41 return delay
42 }
43}
44
45// WithWaiterDelay will set the Waiter to use the WaiterDelay passed in.
46func WithWaiterDelay(delayer WaiterDelay) WaiterOption {
47 return func(w *Waiter) {
48 w.Delay = delayer
49 }
50}
51
52// WithWaiterLogger returns a waiter option to set the logger a waiter
53// should use to log warnings and errors to.
54func WithWaiterLogger(logger aws.Logger) WaiterOption {
55 return func(w *Waiter) {
56 w.Logger = logger
57 }
58}
59
60// WithWaiterRequestOptions returns a waiter option setting the request
61// options for each request the waiter makes. Appends to waiter's request
62// options already set.
63func WithWaiterRequestOptions(opts ...Option) WaiterOption {
64 return func(w *Waiter) {
65 w.RequestOptions = append(w.RequestOptions, opts...)
66 }
67}
68
69// A Waiter provides the functionality to perform a blocking call which will
70// wait for a resource state to be satisfied by a service.
71//
72// This type should not be used directly. The API operations provided in the
73// service packages prefixed with "WaitUntil" should be used instead.
74type Waiter struct {
75 Name string
76 Acceptors []WaiterAcceptor
77 Logger aws.Logger
78
79 MaxAttempts int
80 Delay WaiterDelay
81
82 RequestOptions []Option
83 NewRequest func([]Option) (*Request, error)
84}
85
86// ApplyOptions updates the waiter with the list of waiter options provided.
87func (w *Waiter) ApplyOptions(opts ...WaiterOption) {
88 for _, fn := range opts {
89 fn(w)
90 }
91}
92
93// WaiterState are states the waiter uses based on WaiterAcceptor definitions
94// to identify if the resource state the waiter is waiting on has occurred.
95type WaiterState int
96
97// String returns the string representation of the waiter state.
98func (s WaiterState) String() string {
99 switch s {
100 case SuccessWaiterState:
101 return "success"
102 case FailureWaiterState:
103 return "failure"
104 case RetryWaiterState:
105 return "retry"
106 default:
107 return "unknown waiter state"
108 }
109}
110
111// States the waiter acceptors will use to identify target resource states.
112const (
113 SuccessWaiterState WaiterState = iota // waiter successful
114 FailureWaiterState // waiter failed
115 RetryWaiterState // waiter needs to be retried
116)
117
118// WaiterMatchMode is the mode that the waiter will use to match the WaiterAcceptor
119// definition's Expected attribute.
120type WaiterMatchMode int
121
122// Modes the waiter will use when inspecting API response to identify target
123// resource states.
124const (
125 PathAllWaiterMatch WaiterMatchMode = iota // match on all paths
126 PathWaiterMatch // match on specific path
127 PathAnyWaiterMatch // match on any path
128 PathListWaiterMatch // match on list of paths
129 StatusWaiterMatch // match on status code
130 ErrorWaiterMatch // match on error
131)
132
133// String returns the string representation of the waiter match mode.
134func (m WaiterMatchMode) String() string {
135 switch m {
136 case PathAllWaiterMatch:
137 return "pathAll"
138 case PathWaiterMatch:
139 return "path"
140 case PathAnyWaiterMatch:
141 return "pathAny"
142 case PathListWaiterMatch:
143 return "pathList"
144 case StatusWaiterMatch:
145 return "status"
146 case ErrorWaiterMatch:
147 return "error"
148 default:
149 return "unknown waiter match mode"
150 }
151}
152
153// WaitWithContext will make requests for the API operation using NewRequest to
154// build API requests. The request's response will be compared against the
155// Waiter's Acceptors to determine the successful state of the resource the
156// waiter is inspecting.
157//
158// The passed in context must not be nil. If it is nil a panic will occur. The
159// Context will be used to cancel the waiter's pending requests and retry delays.
160// Use aws.BackgroundContext if no context is available.
161//
162// The waiter will continue until the target state defined by the Acceptors,
163// or the max attempts expires.
164//
165// Will return the WaiterResourceNotReadyErrorCode error code if the waiter's
166// retryer ShouldRetry returns false. This normally will happen when the max
167// wait attempts expires.
168func (w Waiter) WaitWithContext(ctx aws.Context) error {
169
170 for attempt := 1; ; attempt++ {
171 req, err := w.NewRequest(w.RequestOptions)
172 if err != nil {
173 waiterLogf(w.Logger, "unable to create request %v", err)
174 return err
175 }
176 req.Handlers.Build.PushBack(MakeAddToUserAgentFreeFormHandler("Waiter"))
177 err = req.Send()
178
179 // See if any of the acceptors match the request's response, or error
180 for _, a := range w.Acceptors {
181 if matched, matchErr := a.match(w.Name, w.Logger, req, err); matched {
182 return matchErr
183 }
184 }
185
186 // The Waiter should only check the resource state MaxAttempts times
187 // This is here instead of in the for loop above to prevent delaying
188 // unnecessary when the waiter will not retry.
189 if attempt == w.MaxAttempts {
190 break
191 }
192
193 // Delay to wait before inspecting the resource again
194 delay := w.Delay(attempt)
195 if sleepFn := req.Config.SleepDelay; sleepFn != nil {
196 // Support SleepDelay for backwards compatibility and testing
197 sleepFn(delay)
198 } else if err := aws.SleepWithContext(ctx, delay); err != nil {
199 return awserr.New(CanceledErrorCode, "waiter context canceled", err)
200 }
201 }
202
203 return awserr.New(WaiterResourceNotReadyErrorCode, "exceeded wait attempts", nil)
204}
205
206// A WaiterAcceptor provides the information needed to wait for an API operation
207// to complete.
208type WaiterAcceptor struct {
209 State WaiterState
210 Matcher WaiterMatchMode
211 Argument string
212 Expected interface{}
213}
214
215// match returns if the acceptor found a match with the passed in request
216// or error. True is returned if the acceptor made a match, error is returned
217// if there was an error attempting to perform the match.
218func (a *WaiterAcceptor) match(name string, l aws.Logger, req *Request, err error) (bool, error) {
219 result := false
220 var vals []interface{}
221
222 switch a.Matcher {
223 case PathAllWaiterMatch, PathWaiterMatch:
224 // Require all matches to be equal for result to match
225 vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
226 if len(vals) == 0 {
227 break
228 }
229 result = true
230 for _, val := range vals {
231 if !awsutil.DeepEqual(val, a.Expected) {
232 result = false
233 break
234 }
235 }
236 case PathAnyWaiterMatch:
237 // Only a single match needs to equal for the result to match
238 vals, _ = awsutil.ValuesAtPath(req.Data, a.Argument)
239 for _, val := range vals {
240 if awsutil.DeepEqual(val, a.Expected) {
241 result = true
242 break
243 }
244 }
245 case PathListWaiterMatch:
246 // ignored matcher
247 case StatusWaiterMatch:
248 s := a.Expected.(int)
249 result = s == req.HTTPResponse.StatusCode
250 case ErrorWaiterMatch:
251 if aerr, ok := err.(awserr.Error); ok {
252 result = aerr.Code() == a.Expected.(string)
253 }
254 default:
255 waiterLogf(l, "WARNING: Waiter %s encountered unexpected matcher: %s",
256 name, a.Matcher)
257 }
258
259 if !result {
260 // If there was no matching result found there is nothing more to do
261 // for this response, retry the request.
262 return false, nil
263 }
264
265 switch a.State {
266 case SuccessWaiterState:
267 // waiter completed
268 return true, nil
269 case FailureWaiterState:
270 // Waiter failure state triggered
271 return true, awserr.New(WaiterResourceNotReadyErrorCode,
272 "failed waiting for successful resource state", err)
273 case RetryWaiterState:
274 // clear the error and retry the operation
275 return false, nil
276 default:
277 waiterLogf(l, "WARNING: Waiter %s encountered unexpected state: %s",
278 name, a.State)
279 return false, nil
280 }
281}
282
283func waiterLogf(logger aws.Logger, msg string, args ...interface{}) {
284 if logger != nil {
285 logger.Log(fmt.Sprintf(msg, args...))
286 }
287}