diff options
Diffstat (limited to 'vendor/github.com/alexedwards')
| -rw-r--r-- | vendor/github.com/alexedwards/stack/LICENSE | 20 | ||||
| -rw-r--r-- | vendor/github.com/alexedwards/stack/context.go | 55 | ||||
| -rw-r--r-- | vendor/github.com/alexedwards/stack/stack.go | 94 |
3 files changed, 169 insertions, 0 deletions
diff --git a/vendor/github.com/alexedwards/stack/LICENSE b/vendor/github.com/alexedwards/stack/LICENSE new file mode 100644 index 0000000..f25a33b --- /dev/null +++ b/vendor/github.com/alexedwards/stack/LICENSE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2014 Alex Edwards + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/alexedwards/stack/context.go b/vendor/github.com/alexedwards/stack/context.go new file mode 100644 index 0000000..07afe21 --- /dev/null +++ b/vendor/github.com/alexedwards/stack/context.go @@ -0,0 +1,55 @@ +package stack + +import ( + "sync" +) + +type Context struct { + mu sync.RWMutex + m map[string]interface{} +} + +func NewContext() *Context { + m := make(map[string]interface{}) + return &Context{m: m} +} + +func (c *Context) Get(key string) interface{} { + if !c.Exists(key) { + return nil + } + c.mu.RLock() + defer c.mu.RUnlock() + return c.m[key] +} + +func (c *Context) Put(key string, val interface{}) *Context { + c.mu.Lock() + defer c.mu.Unlock() + c.m[key] = val + return c +} + +func (c *Context) Delete(key string) *Context { + c.mu.Lock() + defer c.mu.Unlock() + delete(c.m, key) + return c +} + +func (c *Context) Exists(key string) bool { + c.mu.RLock() + defer c.mu.RUnlock() + _, ok := c.m[key] + return ok +} + +func (c *Context) copy() *Context { + nc := NewContext() + c.mu.RLock() + defer c.mu.RUnlock() + for k, v := range c.m { + nc.m[k] = v + } + return nc +} diff --git a/vendor/github.com/alexedwards/stack/stack.go b/vendor/github.com/alexedwards/stack/stack.go new file mode 100644 index 0000000..47c42b2 --- /dev/null +++ b/vendor/github.com/alexedwards/stack/stack.go @@ -0,0 +1,94 @@ +package stack + +import "net/http" + +type chainHandler func(*Context) http.Handler +type chainMiddleware func(*Context, http.Handler) http.Handler + +type Chain struct { + mws []chainMiddleware + h chainHandler +} + +func New(mws ...chainMiddleware) Chain { + return Chain{mws: mws} +} + +func (c Chain) Append(mws ...chainMiddleware) Chain { + newMws := make([]chainMiddleware, len(c.mws)+len(mws)) + copy(newMws[:len(c.mws)], c.mws) + copy(newMws[len(c.mws):], mws) + c.mws = newMws + return c +} + +func (c Chain) Then(chf func(ctx *Context, w http.ResponseWriter, r *http.Request)) HandlerChain { + c.h = adaptContextHandlerFunc(chf) + return newHandlerChain(c) +} + +func (c Chain) ThenHandler(h http.Handler) HandlerChain { + c.h = adaptHandler(h) + return newHandlerChain(c) +} + +func (c Chain) ThenHandlerFunc(fn func(http.ResponseWriter, *http.Request)) HandlerChain { + c.h = adaptHandlerFunc(fn) + return newHandlerChain(c) +} + +type HandlerChain struct { + context *Context + Chain +} + +func newHandlerChain(c Chain) HandlerChain { + return HandlerChain{context: NewContext(), Chain: c} +} + +func (hc HandlerChain) ServeHTTP(w http.ResponseWriter, r *http.Request) { + // Always take a copy of context (i.e. pointing to a brand new memory location) + ctx := hc.context.copy() + + final := hc.h(ctx) + for i := len(hc.mws) - 1; i >= 0; i-- { + final = hc.mws[i](ctx, final) + } + final.ServeHTTP(w, r) +} + +func Inject(hc HandlerChain, key string, val interface{}) HandlerChain { + hc.context = hc.context.copy().Put(key, val) + return hc +} + +// Adapt third party middleware with the signature +// func(http.Handler) http.Handler into chainMiddleware +func Adapt(fn func(http.Handler) http.Handler) chainMiddleware { + return func(ctx *Context, h http.Handler) http.Handler { + return fn(h) + } +} + +// Adapt http.Handler into a chainHandler +func adaptHandler(h http.Handler) chainHandler { + return func(ctx *Context) http.Handler { + return h + } +} + +// Adapt a function with the signature +// func(http.ResponseWriter, *http.Request) into a chainHandler +func adaptHandlerFunc(fn func(w http.ResponseWriter, r *http.Request)) chainHandler { + return adaptHandler(http.HandlerFunc(fn)) +} + +// Adapt a function with the signature +// func(Context, http.ResponseWriter, *http.Request) into a chainHandler +func adaptContextHandlerFunc(fn func(ctx *Context, w http.ResponseWriter, r *http.Request)) chainHandler { + return func(ctx *Context) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fn(ctx, w, r) + }) + } +} |
