package middleware import ( "fmt" "net/http" "slices" ) type Middleware interface { Client(r *http.Request) error Handler(http.Handler) http.Handler } type BaseMiddleware struct{} func (BaseMiddleware) Client(*http.Request) error { return nil } func (BaseMiddleware) Handler(h http.Handler) http.Handler { return h } type MiddlewareBuilder struct { middlewares []Middleware } func (b *MiddlewareBuilder) Use(middleware Middleware) *MiddlewareBuilder { b.middlewares = append(b.middlewares, middleware) return b } type middlewareProxy struct { middlewares []Middleware } func (p *middlewareProxy) Client(r *http.Request) error { for _, m := range p.middlewares { if err := m.Client(r); err != nil { return fmt.Errorf("%T: %w", m, err) } } return nil } func (p *middlewareProxy) Handler(h http.Handler) http.Handler { for _, f := range slices.Backward(p.middlewares) { h = f.Handler(h) } return h } func (b *MiddlewareBuilder) Prepare() Middleware { return &middlewareProxy{ middlewares: append([]Middleware(nil), b.middlewares...), } }