aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/alexedwards
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/alexedwards')
-rw-r--r--vendor/github.com/alexedwards/stack/LICENSE20
-rw-r--r--vendor/github.com/alexedwards/stack/context.go55
-rw-r--r--vendor/github.com/alexedwards/stack/stack.go94
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)
+ })
+ }
+}