package ircv3 import ( "context" ) type Handler interface { Handle(ctx context.Context, w MessageWriter, m *Message) } type HandlerFunc func(ctx context.Context, w MessageWriter, m *Message) func (h HandlerFunc) Handle(ctx context.Context, w MessageWriter, m *Message) { h(ctx, w, m) } type MessageWriter interface { WriteMessage(msg *Message) error } type Middleware func(next Handler) Handler type Middlewares []func(Handler) Handler // Chain returns a Middlewares type from a slice of middleware handlers. func Chain(middlewares ...func(Handler) Handler) Middlewares { return Middlewares(middlewares) } // Handler builds and returns a http.Handler from the chain of middlewares, // with `h http.Handler` as the final handler. func (mws Middlewares) Handler(h Handler) Handler { return &ChainHandler{h, chain(mws, h), mws} } // HandlerFunc builds and returns a http.Handler from the chain of middlewares, // with `h http.Handler` as the final handler. func (mws Middlewares) HandlerFunc(h HandlerFunc) Handler { return &ChainHandler{h, chain(mws, h), mws} } // ChainHandler is a http.Handler with support for handler composition and // execution. type ChainHandler struct { Endpoint Handler chain Handler Middlewares Middlewares } func (c *ChainHandler) Handle(ctx context.Context, w MessageWriter, m *Message) { c.chain.Handle(ctx, w, m) } // chain builds a http.Handler composed of an inline middleware stack and endpoint // handler in the order they are passed. func chain(middlewares []func(Handler) Handler, endpoint Handler) Handler { // Return ahead of time if there aren't any middlewares for the chain if len(middlewares) == 0 { return endpoint } // Wrap the end handler with the middleware chain h := middlewares[len(middlewares)-1](endpoint) for i := len(middlewares) - 2; i >= 0; i-- { h = middlewares[i](h) } return h }