package awslambda import ( "context" "github.com/go-kit/kit/endpoint" "github.com/go-kit/kit/transport" "github.com/go-kit/log" ) // Handler wraps an endpoint. type Handler struct { e endpoint.Endpoint dec DecodeRequestFunc enc EncodeResponseFunc before []HandlerRequestFunc after []HandlerResponseFunc errorEncoder ErrorEncoder finalizer []HandlerFinalizerFunc errorHandler transport.ErrorHandler } // NewHandler constructs a new handler, which implements // the AWS lambda.Handler interface. func NewHandler( e endpoint.Endpoint, dec DecodeRequestFunc, enc EncodeResponseFunc, options ...HandlerOption, ) *Handler { h := &Handler{ e: e, dec: dec, enc: enc, errorEncoder: DefaultErrorEncoder, errorHandler: transport.NewLogErrorHandler(log.NewNopLogger()), } for _, option := range options { option(h) } return h } // HandlerOption sets an optional parameter for handlers. type HandlerOption func(*Handler) // HandlerBefore functions are executed on the payload byte, // before the request is decoded. func HandlerBefore(before ...HandlerRequestFunc) HandlerOption { return func(h *Handler) { h.before = append(h.before, before...) } } // HandlerAfter functions are only executed after invoking the endpoint // but prior to returning a response. func HandlerAfter(after ...HandlerResponseFunc) HandlerOption { return func(h *Handler) { h.after = append(h.after, after...) } } // HandlerErrorLogger is used to log non-terminal errors. // By default, no errors are logged. // Deprecated: Use HandlerErrorHandler instead. func HandlerErrorLogger(logger log.Logger) HandlerOption { return func(h *Handler) { h.errorHandler = transport.NewLogErrorHandler(logger) } } // HandlerErrorHandler is used to handle non-terminal errors. // By default, non-terminal errors are ignored. func HandlerErrorHandler(errorHandler transport.ErrorHandler) HandlerOption { return func(h *Handler) { h.errorHandler = errorHandler } } // HandlerErrorEncoder is used to encode errors. func HandlerErrorEncoder(ee ErrorEncoder) HandlerOption { return func(h *Handler) { h.errorEncoder = ee } } // HandlerFinalizer sets finalizer which are called at the end of // request. By default no finalizer is registered. func HandlerFinalizer(f ...HandlerFinalizerFunc) HandlerOption { return func(h *Handler) { h.finalizer = append(h.finalizer, f...) } } // DefaultErrorEncoder defines the default behavior of encoding an error response, // where it returns nil, and the error itself. func DefaultErrorEncoder(ctx context.Context, err error) ([]byte, error) { return nil, err } // Invoke represents implementation of the AWS lambda.Handler interface. func (h *Handler) Invoke( ctx context.Context, payload []byte, ) (resp []byte, err error) { if len(h.finalizer) > 0 { defer func() { for _, f := range h.finalizer { f(ctx, resp, err) } }() } for _, f := range h.before { ctx = f(ctx, payload) } request, err := h.dec(ctx, payload) if err != nil { h.errorHandler.Handle(ctx, err) return h.errorEncoder(ctx, err) } response, err := h.e(ctx, request) if err != nil { h.errorHandler.Handle(ctx, err) return h.errorEncoder(ctx, err) } for _, f := range h.after { ctx = f(ctx, response) } if resp, err = h.enc(ctx, response); err != nil { h.errorHandler.Handle(ctx, err) return h.errorEncoder(ctx, err) } return resp, err }