middleware.go (2120B)
1 package middleware 2 3 import ( 4 "context" 5 ) 6 7 // Handler provides the interface for performing the logic to obtain an output, 8 // or error for the given input. 9 type Handler interface { 10 // Handle performs logic to obtain an output for the given input. Handler 11 // should be decorated with middleware to perform input specific behavior. 12 Handle(ctx context.Context, input interface{}) ( 13 output interface{}, metadata Metadata, err error, 14 ) 15 } 16 17 // HandlerFunc provides a wrapper around a function pointer to be used as a 18 // middleware handler. 19 type HandlerFunc func(ctx context.Context, input interface{}) ( 20 output interface{}, metadata Metadata, err error, 21 ) 22 23 // Handle invokes the underlying function, returning the result. 24 func (fn HandlerFunc) Handle(ctx context.Context, input interface{}) ( 25 output interface{}, metadata Metadata, err error, 26 ) { 27 return fn(ctx, input) 28 } 29 30 // Middleware provides the interface to call handlers in a chain. 31 type Middleware interface { 32 // ID provides a unique identifier for the middleware. 33 ID() string 34 35 // Performs the middleware's handling of the input, returning the output, 36 // or error. The middleware can invoke the next Handler if handling should 37 // continue. 38 HandleMiddleware(ctx context.Context, input interface{}, next Handler) ( 39 output interface{}, metadata Metadata, err error, 40 ) 41 } 42 43 // decoratedHandler wraps a middleware in order to to call the next handler in 44 // the chain. 45 type decoratedHandler struct { 46 // The next handler to be called. 47 Next Handler 48 49 // The current middleware decorating the handler. 50 With Middleware 51 } 52 53 // Handle implements the Handler interface to handle a operation invocation. 54 func (m decoratedHandler) Handle(ctx context.Context, input interface{}) ( 55 output interface{}, metadata Metadata, err error, 56 ) { 57 return m.With.HandleMiddleware(ctx, input, m.Next) 58 } 59 60 // DecorateHandler decorates a handler with a middleware. Wrapping the handler 61 // with the middleware. 62 func DecorateHandler(h Handler, with ...Middleware) Handler { 63 for i := len(with) - 1; i >= 0; i-- { 64 h = decoratedHandler{ 65 Next: h, 66 With: with[i], 67 } 68 } 69 70 return h 71 }