From 8f8931b9c57287f78df88131ee8ac57ffd6fb6d2 Mon Sep 17 00:00:00 2001 From: Johnny Graettinger Date: Tue, 21 Jun 2016 23:38:18 -0400 Subject: [PATCH] Add ConstructorFunc / MiddlewareFunc MiddlewareFunc defines a standard signature for a http.HandlerFunc which accepts a chained http.Handler to invoke. ConstructorFunc supplies an adapter for converting a MiddlewareFunc into a Constructor. This is most useful for building middleware with bound parameters via closures. --- chain.go | 24 ++++++++++++++++++++++++ chain_test.go | 9 ++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/chain.go b/chain.go index c75f9c9..e6d989a 100644 --- a/chain.go +++ b/chain.go @@ -8,6 +8,30 @@ import "net/http" // so in most cases you can just pass somepackage.New type Constructor func(http.Handler) http.Handler +// A MiddlewareFunc performs a middleware action, and then passes +// control to the supplied http.Handler +type MiddlewareFunc func(http.ResponseWriter, *http.Request, http.Handler) + +// ConstructorFunc adapts a MiddlewareFunc to be used as a Constructor. +// This simplifies the use of closures to construct middleware with bound +// parameters. Eg: +// func AddHeader(key, value string) Constructor { +// var h = func(w http.ResponseWriter, r *http.Request, next http.Handler) { +// w.Header().Add(key, value) +// next.ServeHTTP(w, r) +// } +// return ConstructorFunc(h) +// } +func ConstructorFunc(f MiddlewareFunc) Constructor { + return f.construct +} + +func (f MiddlewareFunc) construct(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + f(w, r, next) + }) +} + // Chain acts as a list of http.Handler constructors. // Chain is effectively immutable: // once created, it will always hold diff --git a/chain_test.go b/chain_test.go index 6f4316b..607a6e5 100644 --- a/chain_test.go +++ b/chain_test.go @@ -12,12 +12,11 @@ import ( // that writes its own "tag" into the RW and does nothing else. // Useful in checking if a chain is behaving in the right order. func tagMiddleware(tag string) Constructor { - return func(h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte(tag)) - h.ServeHTTP(w, r) - }) + var h = func(w http.ResponseWriter, r *http.Request, next http.Handler) { + w.Write([]byte(tag)) + next.ServeHTTP(w, r) } + return ConstructorFunc(h) } // Not recommended (https://golang.org/pkg/reflect/#Value.Pointer),