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  }