github.com/aavshr/aws-sdk-go@v1.41.3/aws/request/handlers.go (about) 1 package request 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // A Handlers provides a collection of request handlers for various 9 // stages of handling requests. 10 type Handlers struct { 11 Validate HandlerList 12 Build HandlerList 13 BuildStream HandlerList 14 Sign HandlerList 15 Send HandlerList 16 ValidateResponse HandlerList 17 Unmarshal HandlerList 18 UnmarshalStream HandlerList 19 UnmarshalMeta HandlerList 20 UnmarshalError HandlerList 21 Retry HandlerList 22 AfterRetry HandlerList 23 CompleteAttempt HandlerList 24 Complete HandlerList 25 } 26 27 // Copy returns a copy of this handler's lists. 28 func (h *Handlers) Copy() Handlers { 29 return Handlers{ 30 Validate: h.Validate.copy(), 31 Build: h.Build.copy(), 32 BuildStream: h.BuildStream.copy(), 33 Sign: h.Sign.copy(), 34 Send: h.Send.copy(), 35 ValidateResponse: h.ValidateResponse.copy(), 36 Unmarshal: h.Unmarshal.copy(), 37 UnmarshalStream: h.UnmarshalStream.copy(), 38 UnmarshalError: h.UnmarshalError.copy(), 39 UnmarshalMeta: h.UnmarshalMeta.copy(), 40 Retry: h.Retry.copy(), 41 AfterRetry: h.AfterRetry.copy(), 42 CompleteAttempt: h.CompleteAttempt.copy(), 43 Complete: h.Complete.copy(), 44 } 45 } 46 47 // Clear removes callback functions for all handlers. 48 func (h *Handlers) Clear() { 49 h.Validate.Clear() 50 h.Build.Clear() 51 h.BuildStream.Clear() 52 h.Send.Clear() 53 h.Sign.Clear() 54 h.Unmarshal.Clear() 55 h.UnmarshalStream.Clear() 56 h.UnmarshalMeta.Clear() 57 h.UnmarshalError.Clear() 58 h.ValidateResponse.Clear() 59 h.Retry.Clear() 60 h.AfterRetry.Clear() 61 h.CompleteAttempt.Clear() 62 h.Complete.Clear() 63 } 64 65 // IsEmpty returns if there are no handlers in any of the handlerlists. 66 func (h *Handlers) IsEmpty() bool { 67 if h.Validate.Len() != 0 { 68 return false 69 } 70 if h.Build.Len() != 0 { 71 return false 72 } 73 if h.BuildStream.Len() != 0 { 74 return false 75 } 76 if h.Send.Len() != 0 { 77 return false 78 } 79 if h.Sign.Len() != 0 { 80 return false 81 } 82 if h.Unmarshal.Len() != 0 { 83 return false 84 } 85 if h.UnmarshalStream.Len() != 0 { 86 return false 87 } 88 if h.UnmarshalMeta.Len() != 0 { 89 return false 90 } 91 if h.UnmarshalError.Len() != 0 { 92 return false 93 } 94 if h.ValidateResponse.Len() != 0 { 95 return false 96 } 97 if h.Retry.Len() != 0 { 98 return false 99 } 100 if h.AfterRetry.Len() != 0 { 101 return false 102 } 103 if h.CompleteAttempt.Len() != 0 { 104 return false 105 } 106 if h.Complete.Len() != 0 { 107 return false 108 } 109 110 return true 111 } 112 113 // A HandlerListRunItem represents an entry in the HandlerList which 114 // is being run. 115 type HandlerListRunItem struct { 116 Index int 117 Handler NamedHandler 118 Request *Request 119 } 120 121 // A HandlerList manages zero or more handlers in a list. 122 type HandlerList struct { 123 list []NamedHandler 124 125 // Called after each request handler in the list is called. If set 126 // and the func returns true the HandlerList will continue to iterate 127 // over the request handlers. If false is returned the HandlerList 128 // will stop iterating. 129 // 130 // Should be used if extra logic to be performed between each handler 131 // in the list. This can be used to terminate a list's iteration 132 // based on a condition such as error like, HandlerListStopOnError. 133 // Or for logging like HandlerListLogItem. 134 AfterEachFn func(item HandlerListRunItem) bool 135 } 136 137 // A NamedHandler is a struct that contains a name and function callback. 138 type NamedHandler struct { 139 Name string 140 Fn func(*Request) 141 } 142 143 // copy creates a copy of the handler list. 144 func (l *HandlerList) copy() HandlerList { 145 n := HandlerList{ 146 AfterEachFn: l.AfterEachFn, 147 } 148 if len(l.list) == 0 { 149 return n 150 } 151 152 n.list = append(make([]NamedHandler, 0, len(l.list)), l.list...) 153 return n 154 } 155 156 // Clear clears the handler list. 157 func (l *HandlerList) Clear() { 158 l.list = l.list[0:0] 159 } 160 161 // Len returns the number of handlers in the list. 162 func (l *HandlerList) Len() int { 163 return len(l.list) 164 } 165 166 // PushBack pushes handler f to the back of the handler list. 167 func (l *HandlerList) PushBack(f func(*Request)) { 168 l.PushBackNamed(NamedHandler{"__anonymous", f}) 169 } 170 171 // PushBackNamed pushes named handler f to the back of the handler list. 172 func (l *HandlerList) PushBackNamed(n NamedHandler) { 173 if cap(l.list) == 0 { 174 l.list = make([]NamedHandler, 0, 5) 175 } 176 l.list = append(l.list, n) 177 } 178 179 // PushFront pushes handler f to the front of the handler list. 180 func (l *HandlerList) PushFront(f func(*Request)) { 181 l.PushFrontNamed(NamedHandler{"__anonymous", f}) 182 } 183 184 // PushFrontNamed pushes named handler f to the front of the handler list. 185 func (l *HandlerList) PushFrontNamed(n NamedHandler) { 186 if cap(l.list) == len(l.list) { 187 // Allocating new list required 188 l.list = append([]NamedHandler{n}, l.list...) 189 } else { 190 // Enough room to prepend into list. 191 l.list = append(l.list, NamedHandler{}) 192 copy(l.list[1:], l.list) 193 l.list[0] = n 194 } 195 } 196 197 // Remove removes a NamedHandler n 198 func (l *HandlerList) Remove(n NamedHandler) { 199 l.RemoveByName(n.Name) 200 } 201 202 // RemoveByName removes a NamedHandler by name. 203 func (l *HandlerList) RemoveByName(name string) { 204 for i := 0; i < len(l.list); i++ { 205 m := l.list[i] 206 if m.Name == name { 207 // Shift array preventing creating new arrays 208 copy(l.list[i:], l.list[i+1:]) 209 l.list[len(l.list)-1] = NamedHandler{} 210 l.list = l.list[:len(l.list)-1] 211 212 // decrement list so next check to length is correct 213 i-- 214 } 215 } 216 } 217 218 // SwapNamed will swap out any existing handlers with the same name as the 219 // passed in NamedHandler returning true if handlers were swapped. False is 220 // returned otherwise. 221 func (l *HandlerList) SwapNamed(n NamedHandler) (swapped bool) { 222 for i := 0; i < len(l.list); i++ { 223 if l.list[i].Name == n.Name { 224 l.list[i].Fn = n.Fn 225 swapped = true 226 } 227 } 228 229 return swapped 230 } 231 232 // Swap will swap out all handlers matching the name passed in. The matched 233 // handlers will be swapped in. True is returned if the handlers were swapped. 234 func (l *HandlerList) Swap(name string, replace NamedHandler) bool { 235 var swapped bool 236 237 for i := 0; i < len(l.list); i++ { 238 if l.list[i].Name == name { 239 l.list[i] = replace 240 swapped = true 241 } 242 } 243 244 return swapped 245 } 246 247 // SetBackNamed will replace the named handler if it exists in the handler list. 248 // If the handler does not exist the handler will be added to the end of the list. 249 func (l *HandlerList) SetBackNamed(n NamedHandler) { 250 if !l.SwapNamed(n) { 251 l.PushBackNamed(n) 252 } 253 } 254 255 // SetFrontNamed will replace the named handler if it exists in the handler list. 256 // If the handler does not exist the handler will be added to the beginning of 257 // the list. 258 func (l *HandlerList) SetFrontNamed(n NamedHandler) { 259 if !l.SwapNamed(n) { 260 l.PushFrontNamed(n) 261 } 262 } 263 264 // Run executes all handlers in the list with a given request object. 265 func (l *HandlerList) Run(r *Request) { 266 for i, h := range l.list { 267 h.Fn(r) 268 item := HandlerListRunItem{ 269 Index: i, Handler: h, Request: r, 270 } 271 if l.AfterEachFn != nil && !l.AfterEachFn(item) { 272 return 273 } 274 } 275 } 276 277 // HandlerListLogItem logs the request handler and the state of the 278 // request's Error value. Always returns true to continue iterating 279 // request handlers in a HandlerList. 280 func HandlerListLogItem(item HandlerListRunItem) bool { 281 if item.Request.Config.Logger == nil { 282 return true 283 } 284 item.Request.Config.Logger.Log("DEBUG: RequestHandler", 285 item.Index, item.Handler.Name, item.Request.Error) 286 287 return true 288 } 289 290 // HandlerListStopOnError returns false to stop the HandlerList iterating 291 // over request handlers if Request.Error is not nil. True otherwise 292 // to continue iterating. 293 func HandlerListStopOnError(item HandlerListRunItem) bool { 294 return item.Request.Error == nil 295 } 296 297 // WithAppendUserAgent will add a string to the user agent prefixed with a 298 // single white space. 299 func WithAppendUserAgent(s string) Option { 300 return func(r *Request) { 301 r.Handlers.Build.PushBack(func(r2 *Request) { 302 AddToUserAgent(r, s) 303 }) 304 } 305 } 306 307 // MakeAddToUserAgentHandler will add the name/version pair to the User-Agent request 308 // header. If the extra parameters are provided they will be added as metadata to the 309 // name/version pair resulting in the following format. 310 // "name/version (extra0; extra1; ...)" 311 // The user agent part will be concatenated with this current request's user agent string. 312 func MakeAddToUserAgentHandler(name, version string, extra ...string) func(*Request) { 313 ua := fmt.Sprintf("%s/%s", name, version) 314 if len(extra) > 0 { 315 ua += fmt.Sprintf(" (%s)", strings.Join(extra, "; ")) 316 } 317 return func(r *Request) { 318 AddToUserAgent(r, ua) 319 } 320 } 321 322 // MakeAddToUserAgentFreeFormHandler adds the input to the User-Agent request header. 323 // The input string will be concatenated with the current request's user agent string. 324 func MakeAddToUserAgentFreeFormHandler(s string) func(*Request) { 325 return func(r *Request) { 326 AddToUserAgent(r, s) 327 } 328 } 329 330 // WithSetRequestHeaders updates the operation request's HTTP header to contain 331 // the header key value pairs provided. If the header key already exists in the 332 // request's HTTP header set, the existing value(s) will be replaced. 333 func WithSetRequestHeaders(h map[string]string) Option { 334 return withRequestHeader(h).SetRequestHeaders 335 } 336 337 type withRequestHeader map[string]string 338 339 func (h withRequestHeader) SetRequestHeaders(r *Request) { 340 for k, v := range h { 341 r.HTTPRequest.Header[k] = []string{v} 342 } 343 }