step_finalize.go (6478B)
1 package middleware 2 3 import "context" 4 5 // FinalizeInput provides the input parameters for the FinalizeMiddleware to 6 // consume. FinalizeMiddleware may modify the Request value before forwarding 7 // the FinalizeInput along to the next next FinalizeHandler. 8 type FinalizeInput struct { 9 Request interface{} 10 } 11 12 // FinalizeOutput provides the result returned by the next FinalizeHandler. 13 type FinalizeOutput struct { 14 Result interface{} 15 } 16 17 // FinalizeHandler provides the interface for the next handler the 18 // FinalizeMiddleware will call in the middleware chain. 19 type FinalizeHandler interface { 20 HandleFinalize(ctx context.Context, in FinalizeInput) ( 21 out FinalizeOutput, metadata Metadata, err error, 22 ) 23 } 24 25 // FinalizeMiddleware provides the interface for middleware specific to the 26 // serialize step. Delegates to the next FinalizeHandler for further 27 // processing. 28 type FinalizeMiddleware interface { 29 // ID returns a unique ID for the middleware in the FinalizeStep. The step does not 30 // allow duplicate IDs. 31 ID() string 32 33 // HandleFinalize invokes the middleware behavior which must delegate to the next handler 34 // for the middleware chain to continue. The method must return a result or 35 // error to its caller. 36 HandleFinalize(ctx context.Context, in FinalizeInput, next FinalizeHandler) ( 37 out FinalizeOutput, metadata Metadata, err error, 38 ) 39 } 40 41 // FinalizeMiddlewareFunc returns a FinalizeMiddleware with the unique ID 42 // provided, and the func to be invoked. 43 func FinalizeMiddlewareFunc(id string, fn func(context.Context, FinalizeInput, FinalizeHandler) (FinalizeOutput, Metadata, error)) FinalizeMiddleware { 44 return finalizeMiddlewareFunc{ 45 id: id, 46 fn: fn, 47 } 48 } 49 50 type finalizeMiddlewareFunc struct { 51 // Unique ID for the middleware. 52 id string 53 54 // Middleware function to be called. 55 fn func(context.Context, FinalizeInput, FinalizeHandler) ( 56 FinalizeOutput, Metadata, error, 57 ) 58 } 59 60 // ID returns the unique ID for the middleware. 61 func (s finalizeMiddlewareFunc) ID() string { return s.id } 62 63 // HandleFinalize invokes the middleware Fn. 64 func (s finalizeMiddlewareFunc) HandleFinalize(ctx context.Context, in FinalizeInput, next FinalizeHandler) ( 65 out FinalizeOutput, metadata Metadata, err error, 66 ) { 67 return s.fn(ctx, in, next) 68 } 69 70 var _ FinalizeMiddleware = (finalizeMiddlewareFunc{}) 71 72 // FinalizeStep provides the ordered grouping of FinalizeMiddleware to be 73 // invoked on a handler. 74 type FinalizeStep struct { 75 ids *orderedIDs 76 } 77 78 // NewFinalizeStep returns a FinalizeStep ready to have middleware for 79 // initialization added to it. 80 func NewFinalizeStep() *FinalizeStep { 81 return &FinalizeStep{ 82 ids: newOrderedIDs(), 83 } 84 } 85 86 var _ Middleware = (*FinalizeStep)(nil) 87 88 // ID returns the unique id of the step as a middleware. 89 func (s *FinalizeStep) ID() string { 90 return "Finalize stack step" 91 } 92 93 // HandleMiddleware invokes the middleware by decorating the next handler 94 // provided. Returns the result of the middleware and handler being invoked. 95 // 96 // Implements Middleware interface. 97 func (s *FinalizeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) ( 98 out interface{}, metadata Metadata, err error, 99 ) { 100 order := s.ids.GetOrder() 101 102 var h FinalizeHandler = finalizeWrapHandler{Next: next} 103 for i := len(order) - 1; i >= 0; i-- { 104 h = decoratedFinalizeHandler{ 105 Next: h, 106 With: order[i].(FinalizeMiddleware), 107 } 108 } 109 110 sIn := FinalizeInput{ 111 Request: in, 112 } 113 114 res, metadata, err := h.HandleFinalize(ctx, sIn) 115 return res.Result, metadata, err 116 } 117 118 // Get retrieves the middleware identified by id. If the middleware is not present, returns false. 119 func (s *FinalizeStep) Get(id string) (FinalizeMiddleware, bool) { 120 get, ok := s.ids.Get(id) 121 if !ok { 122 return nil, false 123 } 124 return get.(FinalizeMiddleware), ok 125 } 126 127 // Add injects the middleware to the relative position of the middleware group. 128 // Returns an error if the middleware already exists. 129 func (s *FinalizeStep) Add(m FinalizeMiddleware, pos RelativePosition) error { 130 return s.ids.Add(m, pos) 131 } 132 133 // Insert injects the middleware relative to an existing middleware ID. 134 // Returns error if the original middleware does not exist, or the middleware 135 // being added already exists. 136 func (s *FinalizeStep) Insert(m FinalizeMiddleware, relativeTo string, pos RelativePosition) error { 137 return s.ids.Insert(m, relativeTo, pos) 138 } 139 140 // Swap removes the middleware by id, replacing it with the new middleware. 141 // Returns the middleware removed, or error if the middleware to be removed 142 // doesn't exist. 143 func (s *FinalizeStep) Swap(id string, m FinalizeMiddleware) (FinalizeMiddleware, error) { 144 removed, err := s.ids.Swap(id, m) 145 if err != nil { 146 return nil, err 147 } 148 149 return removed.(FinalizeMiddleware), nil 150 } 151 152 // Remove removes the middleware by id. Returns error if the middleware 153 // doesn't exist. 154 func (s *FinalizeStep) Remove(id string) (FinalizeMiddleware, error) { 155 removed, err := s.ids.Remove(id) 156 if err != nil { 157 return nil, err 158 } 159 160 return removed.(FinalizeMiddleware), nil 161 } 162 163 // List returns a list of the middleware in the step. 164 func (s *FinalizeStep) List() []string { 165 return s.ids.List() 166 } 167 168 // Clear removes all middleware in the step. 169 func (s *FinalizeStep) Clear() { 170 s.ids.Clear() 171 } 172 173 type finalizeWrapHandler struct { 174 Next Handler 175 } 176 177 var _ FinalizeHandler = (*finalizeWrapHandler)(nil) 178 179 // HandleFinalize implements FinalizeHandler, converts types and delegates to underlying 180 // generic handler. 181 func (w finalizeWrapHandler) HandleFinalize(ctx context.Context, in FinalizeInput) ( 182 out FinalizeOutput, metadata Metadata, err error, 183 ) { 184 res, metadata, err := w.Next.Handle(ctx, in.Request) 185 return FinalizeOutput{ 186 Result: res, 187 }, metadata, err 188 } 189 190 type decoratedFinalizeHandler struct { 191 Next FinalizeHandler 192 With FinalizeMiddleware 193 } 194 195 var _ FinalizeHandler = (*decoratedFinalizeHandler)(nil) 196 197 func (h decoratedFinalizeHandler) HandleFinalize(ctx context.Context, in FinalizeInput) ( 198 out FinalizeOutput, metadata Metadata, err error, 199 ) { 200 return h.With.HandleFinalize(ctx, in, h.Next) 201 } 202 203 // FinalizeHandlerFunc provides a wrapper around a function to be used as a finalize middleware handler. 204 type FinalizeHandlerFunc func(context.Context, FinalizeInput) (FinalizeOutput, Metadata, error) 205 206 // HandleFinalize invokes the wrapped function with the given arguments. 207 func (f FinalizeHandlerFunc) HandleFinalize(ctx context.Context, in FinalizeInput) (FinalizeOutput, Metadata, error) { 208 return f(ctx, in) 209 } 210 211 var _ FinalizeHandler = FinalizeHandlerFunc(nil)