diff --git a/internal/middleware/middleware.go b/internal/middleware/middleware.go new file mode 100644 index 0000000..044c1ba --- /dev/null +++ b/internal/middleware/middleware.go @@ -0,0 +1,44 @@ +package middleware + +import "net/http" + +type ( + // Interceptor intercepts an HTTP handler invocation, it is passed both + // response writer and request which after interception can be passed + // onto the handler function. + Interceptor func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) + + // HandlerFunc builds on top of http.HandlerFunc, and exposes API to + // intercept with Interceptor. This allows building complex long chains + // without complicated struct manipulation. + HandlerFunc http.HandlerFunc + + // Chain is a collection of interceptors that will be invoked in there + // index order. + Chain []Interceptor + + // Skipper is a requests checker for middleware configurations. true + // return force middleware to skip any actions with current request. + Skipper func(r *http.Request) bool +) + +var DefaultSkipper Skipper = func(_ *http.Request) bool { return false } + +// Intercept returns back a continuation that will call install middleware to +// intercept the continuation call. +func (hf HandlerFunc) Intercept(i Interceptor) HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + i(w, r, http.HandlerFunc(hf)) + } +} + +// Handler allows hooking multiple middleware in single call. +func (c Chain) Handler(hf http.HandlerFunc) http.Handler { + current := HandlerFunc(hf) + + for i := len(c) - 1; i >= 0; i-- { + current = current.Intercept(c[i]) + } + + return http.HandlerFunc(current) +}