aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Hanley <felix@userspace.com.au>2016-12-05 08:16:58 +0000
committerFelix Hanley <felix@userspace.com.au>2016-12-05 08:16:58 +0000
commitb049991a46a2f619344bd6e915745703864d0134 (patch)
treeec1d3897a7b69c7c63a3774d4c42dfbb8cb46432
parente1c3d6f7db06d592538f1162b2b6b9f1b6efa330 (diff)
downloadgo-dict2rest-b049991a46a2f619344bd6e915745703864d0134.tar.gz
go-dict2rest-b049991a46a2f619344bd6e915745703864d0134.tar.bz2
Clean up source structure and update vendor versionsHEADmaster
-rw-r--r--Makefile15
-rw-r--r--buffer.go (renamed from src/dict2rest/buffer.go)0
-rw-r--r--deflate.go (renamed from src/dict2rest/deflate.go)0
-rw-r--r--dict.go (renamed from src/dict2rest/dict.go)0
-rwxr-xr-xdict_test.go22
-rw-r--r--gzip.go (renamed from src/dict2rest/gzip.go)0
-rw-r--r--handlers.go (renamed from src/dict2rest/handlers.go)0
-rw-r--r--logger.go (renamed from src/dict2rest/logger.go)0
-rw-r--r--main.go (renamed from src/dict2rest/main.go)0
-rw-r--r--src/vendor/github.com/alexedwards/stack/.travis.yml8
-rw-r--r--src/vendor/github.com/alexedwards/stack/README.md187
-rw-r--r--src/vendor/github.com/alexedwards/stack/context_test.go48
-rw-r--r--src/vendor/github.com/alexedwards/stack/stack_test.go126
-rw-r--r--src/vendor/github.com/julienschmidt/httprouter/.travis.yml9
-rw-r--r--src/vendor/github.com/julienschmidt/httprouter/README.md286
-rw-r--r--src/vendor/github.com/julienschmidt/httprouter/path_test.go92
-rw-r--r--src/vendor/github.com/julienschmidt/httprouter/router_test.go420
-rw-r--r--src/vendor/github.com/julienschmidt/httprouter/tree_test.go635
-rw-r--r--src/vendor/github.com/justinas/alice/.travis.yml11
-rw-r--r--src/vendor/github.com/justinas/alice/README.md92
-rw-r--r--src/vendor/github.com/justinas/alice/chain_test.go144
-rw-r--r--src/vendor/github.com/rs/cors/.travis.yml4
-rw-r--r--src/vendor/github.com/rs/cors/README.md99
-rw-r--r--src/vendor/github.com/rs/cors/bench_test.go88
-rw-r--r--src/vendor/github.com/rs/cors/cors_test.go371
-rw-r--r--src/vendor/github.com/rs/cors/utils_test.go70
-rw-r--r--src/vendor/github.com/rs/xhandler/.travis.yml7
-rw-r--r--src/vendor/github.com/rs/xhandler/README.md134
-rw-r--r--src/vendor/github.com/rs/xhandler/chain_example_test.go52
-rw-r--r--src/vendor/github.com/rs/xhandler/chain_test.go112
-rw-r--r--src/vendor/github.com/rs/xhandler/middleware_test.go88
-rw-r--r--src/vendor/github.com/rs/xhandler/xhandler_example_test.go67
-rw-r--r--src/vendor/github.com/rs/xhandler/xhandler_test.go61
-rw-r--r--src/vendor/github.com/rs/xhandler/xmux/README.md1
-rw-r--r--src/vendor/github.com/stretchr/graceful/.gitignore23
-rw-r--r--src/vendor/github.com/stretchr/graceful/README.md137
-rw-r--r--src/vendor/github.com/stretchr/graceful/graceful_test.go439
-rw-r--r--src/vendor/golang.org/x/net/context/context_test.go575
-rw-r--r--src/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go19
-rw-r--r--src/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go23
-rw-r--r--src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go176
-rw-r--r--src/vendor/golang.org/x/net/context/withtimeout_test.go26
-rw-r--r--src/vendor/golang.org/x/net/netutil/listen.go48
-rw-r--r--src/vendor/golang.org/x/net/netutil/listen_test.go101
-rw-r--r--vendor/github.com/alexedwards/stack/LICENSE (renamed from src/vendor/github.com/alexedwards/stack/LICENSE)0
-rw-r--r--vendor/github.com/alexedwards/stack/context.go (renamed from src/vendor/github.com/alexedwards/stack/context.go)0
-rw-r--r--vendor/github.com/alexedwards/stack/stack.go (renamed from src/vendor/github.com/alexedwards/stack/stack.go)0
-rw-r--r--vendor/github.com/codegangsta/inject/LICENSE20
-rw-r--r--vendor/github.com/codegangsta/inject/inject.go187
-rw-r--r--vendor/github.com/codegangsta/negroni/LICENSE21
-rw-r--r--vendor/github.com/codegangsta/negroni/doc.go25
-rw-r--r--vendor/github.com/codegangsta/negroni/logger.go35
-rw-r--r--vendor/github.com/codegangsta/negroni/negroni.go133
-rw-r--r--vendor/github.com/codegangsta/negroni/recovery.go65
-rw-r--r--vendor/github.com/codegangsta/negroni/response_writer.go113
-rw-r--r--vendor/github.com/codegangsta/negroni/static.go88
-rw-r--r--vendor/github.com/go-martini/martini/LICENSE20
-rw-r--r--vendor/github.com/go-martini/martini/env.go31
-rw-r--r--vendor/github.com/go-martini/martini/go_version.go7
-rw-r--r--vendor/github.com/go-martini/martini/logger.go29
-rw-r--r--vendor/github.com/go-martini/martini/martini.go189
-rw-r--r--vendor/github.com/go-martini/martini/recovery.go144
-rw-r--r--vendor/github.com/go-martini/martini/response_writer.go107
-rw-r--r--vendor/github.com/go-martini/martini/return_handler.go43
-rw-r--r--vendor/github.com/go-martini/martini/router.go425
-rw-r--r--vendor/github.com/go-martini/martini/static.go135
-rw-r--r--vendor/github.com/julienschmidt/httprouter/LICENSE (renamed from src/vendor/github.com/julienschmidt/httprouter/LICENSE)0
-rw-r--r--vendor/github.com/julienschmidt/httprouter/path.go (renamed from src/vendor/github.com/julienschmidt/httprouter/path.go)0
-rw-r--r--vendor/github.com/julienschmidt/httprouter/router.go (renamed from src/vendor/github.com/julienschmidt/httprouter/router.go)70
-rw-r--r--vendor/github.com/julienschmidt/httprouter/tree.go (renamed from src/vendor/github.com/julienschmidt/httprouter/tree.go)163
-rw-r--r--vendor/github.com/justinas/alice/LICENSE (renamed from src/vendor/github.com/justinas/alice/LICENSE)0
-rw-r--r--vendor/github.com/justinas/alice/chain.go (renamed from src/vendor/github.com/justinas/alice/chain.go)29
-rw-r--r--vendor/github.com/martini-contrib/render/LICENSE20
-rw-r--r--vendor/github.com/martini-contrib/render/render.go386
-rw-r--r--vendor/github.com/oxtoacart/bpool/LICENSE202
-rw-r--r--vendor/github.com/oxtoacart/bpool/bpool.go6
-rw-r--r--vendor/github.com/oxtoacart/bpool/bufferpool.go40
-rw-r--r--vendor/github.com/oxtoacart/bpool/bytepool.go45
-rw-r--r--vendor/github.com/oxtoacart/bpool/sizedbufferpool.go60
-rw-r--r--vendor/github.com/rs/cors/LICENSE (renamed from src/vendor/github.com/rs/cors/LICENSE)0
-rw-r--r--vendor/github.com/rs/cors/cors.go (renamed from src/vendor/github.com/rs/cors/cors.go)6
-rw-r--r--vendor/github.com/rs/cors/examples/alice/server.go (renamed from src/vendor/github.com/rs/cors/examples/alice/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/default/server.go (renamed from src/vendor/github.com/rs/cors/examples/default/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/goji/server.go (renamed from src/vendor/github.com/rs/cors/examples/goji/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/martini/server.go (renamed from src/vendor/github.com/rs/cors/examples/martini/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/negroni/server.go (renamed from src/vendor/github.com/rs/cors/examples/negroni/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/nethttp/server.go (renamed from src/vendor/github.com/rs/cors/examples/nethttp/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/openbar/server.go (renamed from src/vendor/github.com/rs/cors/examples/openbar/server.go)0
-rw-r--r--vendor/github.com/rs/cors/examples/xhandler/server.go (renamed from src/vendor/github.com/rs/cors/examples/xhandler/server.go)0
-rw-r--r--vendor/github.com/rs/cors/utils.go (renamed from src/vendor/github.com/rs/cors/utils.go)4
-rw-r--r--vendor/github.com/rs/xhandler/LICENSE (renamed from src/vendor/github.com/rs/xhandler/LICENSE)0
-rw-r--r--vendor/github.com/rs/xhandler/chain.go (renamed from src/vendor/github.com/rs/xhandler/chain.go)48
-rw-r--r--vendor/github.com/rs/xhandler/middleware.go (renamed from src/vendor/github.com/rs/xhandler/middleware.go)6
-rw-r--r--vendor/github.com/rs/xhandler/xhandler.go (renamed from src/vendor/github.com/rs/xhandler/xhandler.go)4
-rw-r--r--vendor/github.com/stretchr/graceful/LICENSE (renamed from src/vendor/github.com/stretchr/graceful/LICENSE)0
-rw-r--r--vendor/github.com/stretchr/graceful/graceful.go484
-rw-r--r--vendor/github.com/stretchr/graceful/keepalive_listener.go32
-rw-r--r--vendor/github.com/stretchr/graceful/limit_listen.go77
-rw-r--r--vendor/github.com/stretchr/graceful/signal.go17
-rw-r--r--vendor/github.com/stretchr/graceful/signal_appengine.go13
-rw-r--r--vendor/github.com/stretchr/graceful/tests/main.go (renamed from src/vendor/github.com/stretchr/graceful/tests/main.go)4
-rw-r--r--vendor/github.com/urfave/negroni/LICENSE21
-rw-r--r--vendor/github.com/urfave/negroni/doc.go25
-rw-r--r--vendor/github.com/urfave/negroni/logger.go35
-rw-r--r--vendor/github.com/urfave/negroni/negroni.go133
-rw-r--r--vendor/github.com/urfave/negroni/recovery.go65
-rw-r--r--vendor/github.com/urfave/negroni/response_writer.go113
-rw-r--r--vendor/github.com/urfave/negroni/static.go88
-rw-r--r--vendor/github.com/zenazn/goji/LICENSE20
-rw-r--r--vendor/github.com/zenazn/goji/bind/bind.go155
-rw-r--r--vendor/github.com/zenazn/goji/bind/einhorn.go91
-rw-r--r--vendor/github.com/zenazn/goji/bind/einhorn_stub.go12
-rw-r--r--vendor/github.com/zenazn/goji/bind/systemd.go36
-rw-r--r--vendor/github.com/zenazn/goji/bind/systemd_stub.go6
-rw-r--r--vendor/github.com/zenazn/goji/default.go102
-rw-r--r--vendor/github.com/zenazn/goji/example/main.go177
-rw-r--r--vendor/github.com/zenazn/goji/example/middleware.go47
-rw-r--r--vendor/github.com/zenazn/goji/example/models.go49
-rw-r--r--vendor/github.com/zenazn/goji/goji.go36
-rw-r--r--vendor/github.com/zenazn/goji/graceful/clone.go11
-rw-r--r--vendor/github.com/zenazn/goji/graceful/clone16.go34
-rw-r--r--vendor/github.com/zenazn/goji/graceful/einhorn.go21
-rw-r--r--vendor/github.com/zenazn/goji/graceful/graceful.go62
-rw-r--r--vendor/github.com/zenazn/goji/graceful/listener/conn.go151
-rw-r--r--vendor/github.com/zenazn/goji/graceful/listener/listener.go178
-rw-r--r--vendor/github.com/zenazn/goji/graceful/listener/shard.go98
-rw-r--r--vendor/github.com/zenazn/goji/graceful/middleware.go103
-rw-r--r--vendor/github.com/zenazn/goji/graceful/serve.go33
-rw-r--r--vendor/github.com/zenazn/goji/graceful/serve13.go76
-rw-r--r--vendor/github.com/zenazn/goji/graceful/server.go108
-rw-r--r--vendor/github.com/zenazn/goji/graceful/signal.go197
-rw-r--r--vendor/github.com/zenazn/goji/serve.go64
-rw-r--r--vendor/github.com/zenazn/goji/serve_appengine.go23
-rw-r--r--vendor/github.com/zenazn/goji/web/atomic.go18
-rw-r--r--vendor/github.com/zenazn/goji/web/atomic_appengine.go14
-rw-r--r--vendor/github.com/zenazn/goji/web/bytecode_compiler.go265
-rw-r--r--vendor/github.com/zenazn/goji/web/bytecode_runner.go83
-rw-r--r--vendor/github.com/zenazn/goji/web/chanpool.go31
-rw-r--r--vendor/github.com/zenazn/goji/web/cpool.go23
-rw-r--r--vendor/github.com/zenazn/goji/web/func_equal.go32
-rw-r--r--vendor/github.com/zenazn/goji/web/handler.go42
-rw-r--r--vendor/github.com/zenazn/goji/web/match.go66
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware.go154
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/envinit.go27
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/logger.go92
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/middleware.go4
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/nocache.go55
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/options.go97
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/realip.go51
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/recoverer.go44
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/request_id.go88
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/subrouter.go65
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/terminal.go60
-rw-r--r--vendor/github.com/zenazn/goji/web/middleware/urlquery.go24
-rw-r--r--vendor/github.com/zenazn/goji/web/mutil/mutil.go3
-rw-r--r--vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go139
-rw-r--r--vendor/github.com/zenazn/goji/web/mux.go213
-rw-r--r--vendor/github.com/zenazn/goji/web/pattern.go58
-rw-r--r--vendor/github.com/zenazn/goji/web/regexp_pattern.go149
-rw-r--r--vendor/github.com/zenazn/goji/web/router.go154
-rw-r--r--vendor/github.com/zenazn/goji/web/string_pattern.go137
-rw-r--r--vendor/github.com/zenazn/goji/web/web.go112
-rw-r--r--vendor/golang.org/x/net/context/LICENSE27
-rw-r--r--vendor/golang.org/x/net/context/context.go156
-rw-r--r--vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go74
-rw-r--r--vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go (renamed from src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go)17
-rw-r--r--vendor/golang.org/x/net/context/go17.go72
-rw-r--r--vendor/golang.org/x/net/context/pre_go17.go (renamed from src/vendor/golang.org/x/net/context/context.go)175
-rw-r--r--vendor/golang.org/x/net/dict/LICENSE27
-rw-r--r--vendor/golang.org/x/net/dict/dict.go (renamed from src/vendor/golang.org/x/net/dict/dict.go)2
-rw-r--r--vendor/gopkg.in/tylerb/graceful.v1/LICENSE21
-rw-r--r--vendor/gopkg.in/tylerb/graceful.v1/graceful.go (renamed from src/vendor/github.com/stretchr/graceful/graceful.go)210
-rw-r--r--vendor/gopkg.in/tylerb/graceful.v1/keepalive_listener.go32
-rw-r--r--vendor/gopkg.in/tylerb/graceful.v1/limit_listen.go77
-rw-r--r--vendor/gopkg.in/tylerb/graceful.v1/tests/main.go40
-rw-r--r--vendor/manifest135
176 files changed, 8997 insertions, 5087 deletions
diff --git a/Makefile b/Makefile
deleted file mode 100644
index ad2a373..0000000
--- a/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-
-GOPATH := ${PWD}
-export GOPATH
-
-default: build
-
-build: dict2rest
-
-dict2rest:
- go install dict2rest
-
-clean:
- rm bin/*
-
-.PHONY: build dict2rest clean
diff --git a/src/dict2rest/buffer.go b/buffer.go
index e31bebd..e31bebd 100644
--- a/src/dict2rest/buffer.go
+++ b/buffer.go
diff --git a/src/dict2rest/deflate.go b/deflate.go
index 3bd0ed8..3bd0ed8 100644
--- a/src/dict2rest/deflate.go
+++ b/deflate.go
diff --git a/src/dict2rest/dict.go b/dict.go
index fa9690e..fa9690e 100644
--- a/src/dict2rest/dict.go
+++ b/dict.go
diff --git a/dict_test.go b/dict_test.go
new file mode 100755
index 0000000..fae0898
--- /dev/null
+++ b/dict_test.go
@@ -0,0 +1,22 @@
+package main
+
+import "testing"
+
+type mockResponseWriter struct{}
+
+func (m *mockResponseWriter) Header() (h http.Header) {
+ return http.Header{}
+}
+
+func (m *mockResponseWriter) Write(p []byte) (n int, err error) {
+ return len(p), nil
+}
+
+func (m *mockResponseWriter) WriteString(s string) (n int, err error) {
+ return len(s), nil
+}
+
+func (m *mockResponseWriter) WriteHeader(int) {}
+
+func testGetDictClient(t *testing.T) {
+}
diff --git a/src/dict2rest/gzip.go b/gzip.go
index c3bb5ed..c3bb5ed 100644
--- a/src/dict2rest/gzip.go
+++ b/gzip.go
diff --git a/src/dict2rest/handlers.go b/handlers.go
index 024a8d6..024a8d6 100644
--- a/src/dict2rest/handlers.go
+++ b/handlers.go
diff --git a/src/dict2rest/logger.go b/logger.go
index 709666b..709666b 100644
--- a/src/dict2rest/logger.go
+++ b/logger.go
diff --git a/src/dict2rest/main.go b/main.go
index 94e1ac2..94e1ac2 100644
--- a/src/dict2rest/main.go
+++ b/main.go
diff --git a/src/vendor/github.com/alexedwards/stack/.travis.yml b/src/vendor/github.com/alexedwards/stack/.travis.yml
deleted file mode 100644
index 70eed36..0000000
--- a/src/vendor/github.com/alexedwards/stack/.travis.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-sudo: false
-language: go
-go:
- - 1.1
- - 1.2
- - 1.3
- - 1.4
- - tip \ No newline at end of file
diff --git a/src/vendor/github.com/alexedwards/stack/README.md b/src/vendor/github.com/alexedwards/stack/README.md
deleted file mode 100644
index ba689f6..0000000
--- a/src/vendor/github.com/alexedwards/stack/README.md
+++ /dev/null
@@ -1,187 +0,0 @@
-# Stack <br> [![Build Status](https://travis-ci.org/alexedwards/stack.svg?branch=master)](https://travis-ci.org/alexedwards/stack) [![Coverage](http://gocover.io/_badge/github.com/alexedwards/stack?0)](http://gocover.io/github.com/alexedwards/stack) [![GoDoc](http://godoc.org/github.com/alexedwards/stack?status.png)](http://godoc.org/github.com/alexedwards/stack)
-
-Stack provides an easy way to chain your HTTP middleware and handlers together and to pass request-scoped context between them. It's essentially a context-aware version of [Alice](https://github.com/justinas/alice).
-
-[Skip to the example &rsaquo;](#example)
-
-### Usage
-
-#### Making a chain
-
-Middleware chains are constructed with [`stack.New()`](http://godoc.org/github.com/alexedwards/stack#New):
-
-```go
-stack.New(middlewareOne, middlewareTwo, middlewareThree)
-```
-
-You can also store middleware chains as variables, and then [`Append()`](http://godoc.org/github.com/alexedwards/stack#Chain.Append) to them:
-
-```go
-stdStack := stack.New(middlewareOne, middlewareTwo)
-extStack := stdStack.Append(middlewareThree, middlewareFour)
-```
-
-Your middleware should have the signature `func(*stack.Context, http.Handler) http.Handler`. For example:
-
-```go
-func middlewareOne(ctx *stack.Context, next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // do something middleware-ish, accessing ctx
- next.ServeHTTP(w, r)
- })
-}
-```
-
-You can also use middleware with the signature `func(http.Handler) http.Handler` by adapting it with [`stack.Adapt()`](http://godoc.org/github.com/alexedwards/stack#Adapt). For example, if you had the middleware:
-
-```go
-func middlewareTwo(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // do something else middleware-ish
- next.ServeHTTP(w, r)
- })
-}
-```
-
-You can add it to a chain like this:
-
-```go
-stack.New(middlewareOne, stack.Adapt(middlewareTwo), middlewareThree)
-```
-
-See the [codes samples](#code-samples) for real-life use of third-party middleware with Stack.
-
-#### Adding an application handler
-
-Application handlers should have the signature `func(*stack.Context, http.ResponseWriter, *http.Request)`. You add them to the end of a middleware chain with the [`Then()`](http://godoc.org/github.com/alexedwards/stack#Chain.Then) method.
-
-So an application handler like this:
-
-```go
-func appHandler(ctx *stack.Context, w http.ResponseWriter, r *http.Request) {
- // do something handler-ish, accessing ctx
-}
-```
-
-Is added to the end of a middleware chain like this:
-
-```go
-stack.New(middlewareOne, middlewareTwo).Then(appHandler)
-```
-
-For convenience [`ThenHandler()`](http://godoc.org/github.com/alexedwards/stack#Chain.ThenHandler) and [`ThenHandlerFunc()`](http://godoc.org/github.com/alexedwards/stack#Chain.ThenHandlerFunc) methods are also provided. These allow you to finish a chain with a standard `http.Handler` or `http.HandlerFunc` respectively.
-
-For example, you could use a standard `http.FileServer` as the application handler:
-
-```go
-fs := http.FileServer(http.Dir("./static/"))
-http.Handle("/", stack.New(middlewareOne, middlewareTwo).ThenHandler(fs))
-```
-
-Once a chain is 'closed' with any of these methods it is converted into a [`HandlerChain`](http://godoc.org/github.com/alexedwards/stack#HandlerChain) object which satisfies the `http.Handler` interface, and can be used with the `http.DefaultServeMux` and many other routers.
-
-#### Using context
-
-Request-scoped data (or *context*) can be passed through the chain by storing it in `stack.Context`. This is implemented as a pointer to a `map[string]interface{}` and scoped to the goroutine executing the current HTTP request. Operations on `stack.Context` are protected by a mutex, so if you need to pass the context pointer to another goroutine (say for logging or completing a background process) it is safe for concurrent use.
-
-Data is added with [`Context.Put()`](http://godoc.org/github.com/alexedwards/stack#Context.Put). The first parameter is a string (which acts as a key) and the second is the value you need to store. For example:
-
-```go
-func middlewareOne(ctx *stack.Context, next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ctx.Put("token", "c9e452805dee5044ba520198628abcaa")
- next.ServeHTTP(w, r)
- })
-}
-```
-
-You retrieve data with [`Context.Get()`](http://godoc.org/github.com/alexedwards/stack#Context.Get). Remember to type assert the returned value into the type you're expecting.
-
-```go
-func appHandler(ctx *stack.Context, w http.ResponseWriter, r *http.Request) {
- token, ok := ctx.Get("token").(string)
- if !ok {
- http.Error(w, http.StatusText(500), 500)
- return
- }
- fmt.Fprintf(w, "Token is: %s", token)
-}
-```
-
-Note that `Context.Get()` will return `nil` if a key does not exist. If you need to tell the difference between a key having a `nil` value and it explicitly not existing, please check with [`Context.Exists()`](http://godoc.org/github.com/alexedwards/stack#Context.Exists).
-
-Keys (and their values) can be deleted with [`Context.Delete()`](http://godoc.org/github.com/alexedwards/stack#Context.Delete).
-
-#### Injecting context
-
-It's possible to inject values into `stack.Context` during a request cycle but *before* the chain starts to be executed. This is useful if you need to inject parameters from a router into the context.
-
-The [`Inject()`](http://godoc.org/github.com/alexedwards/stack#Inject) function returns a new copy of the chain containing the injected context. You should make sure that you use this new copy &ndash; not the original &ndash; for subsequent processing.
-
-Here's an example of a wrapper for injecting [httprouter](https://github.com/julienschmidt/httprouter) params into the context:
-
-```go
-func InjectParams(hc stack.HandlerChain) httprouter.Handle {
- return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
- newHandlerChain := stack.Inject(hc, "params", ps)
- newHandlerChain.ServeHTTP(w, r)
- }
-}
-```
-
-A full example is available in the [code samples](#code-samples).
-
-### Example
-
-```go
-package main
-
-import (
- "net/http"
- "github.com/alexedwards/stack"
- "fmt"
-)
-
-func main() {
- stk := stack.New(token, stack.Adapt(language))
-
- http.Handle("/", stk.Then(final))
-
- http.ListenAndServe(":3000", nil)
-}
-
-func token(ctx *stack.Context, next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ctx.Put("token", "c9e452805dee5044ba520198628abcaa")
- next.ServeHTTP(w, r)
- })
-}
-
-func language(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Language", "en-gb")
- next.ServeHTTP(w, r)
- })
-}
-
-func final(ctx *stack.Context, w http.ResponseWriter, r *http.Request) {
- token, ok := ctx.Get("token").(string)
- if !ok {
- http.Error(w, http.StatusText(500), 500)
- return
- }
- fmt.Fprintf(w, "Token is: %s", token)
-}
-```
-
-### Code samples
-
-* [Integrating with httprouter](https://gist.github.com/alexedwards/4d20c505f389597c3360)
-* *More to follow*
-
-### TODO
-
-- Add more code samples (using 3rd party middleware)
-- Make a `chain.Merge()` method
-- Mirror master in v1 branch (and mention gopkg.in in README)
-- Add benchmarks
diff --git a/src/vendor/github.com/alexedwards/stack/context_test.go b/src/vendor/github.com/alexedwards/stack/context_test.go
deleted file mode 100644
index 469200e..0000000
--- a/src/vendor/github.com/alexedwards/stack/context_test.go
+++ /dev/null
@@ -1,48 +0,0 @@
-package stack
-
-import "testing"
-
-func TestGet(t *testing.T) {
- ctx := NewContext()
- ctx.m["flip"] = "flop"
- ctx.m["bish"] = nil
-
- val := ctx.Get("flip")
- assertEquals(t, "flop", val)
-
- val = ctx.Get("bish")
- assertEquals(t, nil, val)
-}
-
-func TestPut(t *testing.T) {
- ctx := NewContext()
-
- ctx.Put("bish", "bash")
- assertEquals(t, "bash", ctx.m["bish"])
-}
-
-func TestDelete(t *testing.T) {
- ctx := NewContext()
- ctx.m["flip"] = "flop"
-
- ctx.Delete("flip")
- assertEquals(t, nil, ctx.m["flip"])
-}
-
-func TestCopy(t *testing.T) {
- ctx := NewContext()
- ctx.m["flip"] = "flop"
-
- ctx2 := ctx.copy()
- ctx2.m["bish"] = "bash"
- assertEquals(t, nil, ctx.m["bish"])
- assertEquals(t, "bash", ctx2.m["bish"])
-}
-
-func TestExists(t *testing.T) {
- ctx := NewContext()
- ctx.m["flip"] = "flop"
-
- assertEquals(t, true, ctx.Exists("flip"))
- assertEquals(t, false, ctx.Exists("bash"))
-}
diff --git a/src/vendor/github.com/alexedwards/stack/stack_test.go b/src/vendor/github.com/alexedwards/stack/stack_test.go
deleted file mode 100644
index 28aa0ae..0000000
--- a/src/vendor/github.com/alexedwards/stack/stack_test.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package stack
-
-import (
- "fmt"
- "io/ioutil"
- "log"
- "net/http"
- "net/http/httptest"
- "testing"
-)
-
-func assertEquals(t *testing.T, e interface{}, o interface{}) {
- if e != o {
- t.Errorf("\n...expected = %v\n...obtained = %v", e, o)
- }
-}
-
-func serveAndRequest(h http.Handler) string {
- ts := httptest.NewServer(h)
- defer ts.Close()
- res, err := http.Get(ts.URL)
- if err != nil {
- log.Fatal(err)
- }
- resBody, err := ioutil.ReadAll(res.Body)
- res.Body.Close()
- if err != nil {
- log.Fatal(err)
- }
- return string(resBody)
-}
-
-func bishMiddleware(ctx *Context, next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ctx.Put("bish", "bash")
- fmt.Fprintf(w, "bishMiddleware>")
- next.ServeHTTP(w, r)
- })
-}
-
-func flipMiddleware(ctx *Context, next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "flipMiddleware>")
- next.ServeHTTP(w, r)
- })
-}
-
-func wobbleMiddleware(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprintf(w, "wobbleMiddleware>")
- next.ServeHTTP(w, r)
- })
-}
-
-func bishHandler(ctx *Context, w http.ResponseWriter, r *http.Request) {
- val := ctx.Get("bish")
- fmt.Fprintf(w, "bishHandler [bish=%v]", val)
-}
-
-func flipHandler(ctx *Context, w http.ResponseWriter, r *http.Request) {
- valb := ctx.Get("bish")
- valf := ctx.Get("flip")
- fmt.Fprintf(w, "flipHandler [bish=%v,flip=%v]", valb, valf)
-}
-
-func TestNew(t *testing.T) {
- st := New(bishMiddleware, flipMiddleware).Then(bishHandler)
- res := serveAndRequest(st)
- assertEquals(t, "bishMiddleware>flipMiddleware>bishHandler [bish=bash]", res)
-}
-
-func TestAppend(t *testing.T) {
- st := New(bishMiddleware).Append(flipMiddleware, flipMiddleware).Then(bishHandler)
- res := serveAndRequest(st)
- assertEquals(t, "bishMiddleware>flipMiddleware>flipMiddleware>bishHandler [bish=bash]", res)
-}
-
-func TestAppendDoesNotMutate(t *testing.T) {
- st1 := New(bishMiddleware, flipMiddleware)
- st2 := st1.Append(flipMiddleware, flipMiddleware)
- res := serveAndRequest(st1.Then(bishHandler))
- assertEquals(t, "bishMiddleware>flipMiddleware>bishHandler [bish=bash]", res)
- res = serveAndRequest(st2.Then(bishHandler))
- assertEquals(t, "bishMiddleware>flipMiddleware>flipMiddleware>flipMiddleware>bishHandler [bish=bash]", res)
-}
-
-func TestThen(t *testing.T) {
- chf := func(ctx *Context, w http.ResponseWriter, r *http.Request) {
- fmt.Fprint(w, "An anonymous ContextHandlerFunc")
- }
- st := New().Then(chf)
- res := serveAndRequest(st)
- assertEquals(t, "An anonymous ContextHandlerFunc", res)
-}
-
-func TestThenHandler(t *testing.T) {
- st := New().ThenHandler(http.NotFoundHandler())
- res := serveAndRequest(st)
- assertEquals(t, "404 page not found\n", res)
-}
-
-func TestThenHandlerFunc(t *testing.T) {
- hf := func(w http.ResponseWriter, r *http.Request) {
- fmt.Fprint(w, "An anonymous HandlerFunc")
- }
- st := New().ThenHandlerFunc(hf)
- res := serveAndRequest(st)
- assertEquals(t, "An anonymous HandlerFunc", res)
-}
-
-func TestMixedMiddleware(t *testing.T) {
- st := New(bishMiddleware, Adapt(wobbleMiddleware), flipMiddleware).Then(bishHandler)
- res := serveAndRequest(st)
- assertEquals(t, "bishMiddleware>wobbleMiddleware>flipMiddleware>bishHandler [bish=bash]", res)
-}
-
-func TestInject(t *testing.T) {
- st := New(flipMiddleware).Then(flipHandler)
- st2 := Inject(st, "bish", "boop")
-
- res := serveAndRequest(st2)
- assertEquals(t, "flipMiddleware>flipHandler [bish=boop,flip=<nil>]", res)
-
- res = serveAndRequest(st)
- assertEquals(t, "flipMiddleware>flipHandler [bish=<nil>,flip=<nil>]", res)
-}
diff --git a/src/vendor/github.com/julienschmidt/httprouter/.travis.yml b/src/vendor/github.com/julienschmidt/httprouter/.travis.yml
deleted file mode 100644
index 9a3c1a8..0000000
--- a/src/vendor/github.com/julienschmidt/httprouter/.travis.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-sudo: false
-language: go
-go:
- - 1.1
- - 1.2
- - 1.3
- - 1.4
- - 1.5
- - tip
diff --git a/src/vendor/github.com/julienschmidt/httprouter/README.md b/src/vendor/github.com/julienschmidt/httprouter/README.md
deleted file mode 100644
index 7b467f5..0000000
--- a/src/vendor/github.com/julienschmidt/httprouter/README.md
+++ /dev/null
@@ -1,286 +0,0 @@
-# HttpRouter [![Build Status](https://travis-ci.org/julienschmidt/httprouter.svg?branch=master)](https://travis-ci.org/julienschmidt/httprouter) [![Coverage](http://gocover.io/_badge/github.com/julienschmidt/httprouter?0)](http://gocover.io/github.com/julienschmidt/httprouter) [![GoDoc](https://godoc.org/github.com/julienschmidt/httprouter?status.svg)](http://godoc.org/github.com/julienschmidt/httprouter)
-
-HttpRouter is a lightweight high performance HTTP request router (also called *multiplexer* or just *mux* for short) for [Go](https://golang.org/).
-
-In contrast to the [default mux][http.ServeMux] of Go's `net/http` package, this router supports variables in the routing pattern and matches against the request method. It also scales better.
-
-The router is optimized for high performance and a small memory footprint. It scales well even with very long paths and a large number of routes. A compressing dynamic trie (radix tree) structure is used for efficient matching.
-
-## Features
-
-**Only explicit matches:** With other routers, like [`http.ServeMux`][http.ServeMux], a requested URL path could match multiple patterns. Therefore they have some awkward pattern priority rules, like *longest match* or *first registered, first matched*. By design of this router, a request can only match exactly one or no route. As a result, there are also no unintended matches, which makes it great for SEO and improves the user experience.
-
-**Stop caring about trailing slashes:** Choose the URL style you like, the router automatically redirects the client if a trailing slash is missing or if there is one extra. Of course it only does so, if the new path has a handler. If you don't like it, you can [turn off this behavior](https://godoc.org/github.com/julienschmidt/httprouter#Router.RedirectTrailingSlash).
-
-**Path auto-correction:** Besides detecting the missing or additional trailing slash at no extra cost, the router can also fix wrong cases and remove superfluous path elements (like `../` or `//`). Is [CAPTAIN CAPS LOCK](http://www.urbandictionary.com/define.php?term=Captain+Caps+Lock) one of your users? HttpRouter can help him by making a case-insensitive look-up and redirecting him to the correct URL.
-
-**Parameters in your routing pattern:** Stop parsing the requested URL path, just give the path segment a name and the router delivers the dynamic value to you. Because of the design of the router, path parameters are very cheap.
-
-**Zero Garbage:** The matching and dispatching process generates zero bytes of garbage. In fact, the only heap allocations that are made, is by building the slice of the key-value pairs for path parameters. If the request path contains no parameters, not a single heap allocation is necessary.
-
-**Best Performance:** [Benchmarks speak for themselves][benchmark]. See below for technical details of the implementation.
-
-**No more server crashes:** You can set a [Panic handler][Router.PanicHandler] to deal with panics occurring during handling a HTTP request. The router then recovers and lets the `PanicHandler` log what happened and deliver a nice error page.
-
-Of course you can also set **custom [`NotFound`][Router.NotFound] and [`MethodNotAllowed`](https://godoc.org/github.com/julienschmidt/httprouter#Router.MethodNotAllowed) handlers** and [**serve static files**][Router.ServeFiles].
-
-## Usage
-
-This is just a quick introduction, view the [GoDoc](http://godoc.org/github.com/julienschmidt/httprouter) for details.
-
-Let's start with a trivial example:
-
-```go
-package main
-
-import (
- "fmt"
- "github.com/julienschmidt/httprouter"
- "net/http"
- "log"
-)
-
-func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
- fmt.Fprint(w, "Welcome!\n")
-}
-
-func Hello(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
- fmt.Fprintf(w, "hello, %s!\n", ps.ByName("name"))
-}
-
-func main() {
- router := httprouter.New()
- router.GET("/", Index)
- router.GET("/hello/:name", Hello)
-
- log.Fatal(http.ListenAndServe(":8080", router))
-}
-```
-
-### Named parameters
-
-As you can see, `:name` is a *named parameter*. The values are accessible via `httprouter.Params`, which is just a slice of `httprouter.Param`s. You can get the value of a parameter either by its index in the slice, or by using the `ByName(name)` method: `:name` can be retrived by `ByName("name")`.
-
-Named parameters only match a single path segment:
-
-```
-Pattern: /user/:user
-
- /user/gordon match
- /user/you match
- /user/gordon/profile no match
- /user/ no match
-```
-
-**Note:** Since this router has only explicit matches, you can not register static routes and parameters for the same path segment. For example you can not register the patterns `/user/new` and `/user/:user` for the same request method at the same time. The routing of different request methods is independent from each other.
-
-### Catch-All parameters
-
-The second type are *catch-all* parameters and have the form `*name`. Like the name suggests, they match everything. Therefore they must always be at the **end** of the pattern:
-
-```
-Pattern: /src/*filepath
-
- /src/ match
- /src/somefile.go match
- /src/subdir/somefile.go match
-```
-
-## How does it work?
-
-The router relies on a tree structure which makes heavy use of *common prefixes*, it is basically a *compact* [*prefix tree*](https://en.wikipedia.org/wiki/Trie) (or just [*Radix tree*](https://en.wikipedia.org/wiki/Radix_tree)). Nodes with a common prefix also share a common parent. Here is a short example what the routing tree for the `GET` request method could look like:
-
-```
-Priority Path Handle
-9 \ *<1>
-3 ├s nil
-2 |├earch\ *<2>
-1 |â””upport\ *<3>
-2 ├blog\ *<4>
-1 | â””:post nil
-1 | â””\ *<5>
-2 ├about-us\ *<6>
-1 | â””team\ *<7>
-1 â””contact\ *<8>
-```
-
-Every `*<num>` represents the memory address of a handler function (a pointer). If you follow a path trough the tree from the root to the leaf, you get the complete route path, e.g `\blog\:post\`, where `:post` is just a placeholder ([*parameter*](#named-parameters)) for an actual post name. Unlike hash-maps, a tree structure also allows us to use dynamic parts like the `:post` parameter, since we actually match against the routing patterns instead of just comparing hashes. [As benchmarks show][benchmark], this works very well and efficient.
-
-Since URL paths have a hierarchical structure and make use only of a limited set of characters (byte values), it is very likely that there are a lot of common prefixes. This allows us to easily reduce the routing into ever smaller problems. Moreover the router manages a separate tree for every request method. For one thing it is more space efficient than holding a method->handle map in every single node, for another thing is also allows us to greatly reduce the routing problem before even starting the look-up in the prefix-tree.
-
-For even better scalability, the child nodes on each tree level are ordered by priority, where the priority is just the number of handles registered in sub nodes (children, grandchildren, and so on..). This helps in two ways:
-
-1. Nodes which are part of the most routing paths are evaluated first. This helps to make as much routes as possible to be reachable as fast as possible.
-2. It is some sort of cost compensation. The longest reachable path (highest cost) can always be evaluated first. The following scheme visualizes the tree structure. Nodes are evaluated from top to bottom and from left to right.
-
-```
-├------------
-├---------
-├-----
-├----
-├--
-├--
-â””-
-```
-
-## Why doesn't this work with `http.Handler`?
-
-**It does!** The router itself implements the `http.Handler` interface. Moreover the router provides convenient [adapters for `http.Handler`][Router.Handler]s and [`http.HandlerFunc`][Router.HandlerFunc]s which allows them to be used as a [`httprouter.Handle`][Router.Handle] when registering a route. The only disadvantage is, that no parameter values can be retrieved when a `http.Handler` or `http.HandlerFunc` is used, since there is no efficient way to pass the values with the existing function parameters. Therefore [`httprouter.Handle`][Router.Handle] has a third function parameter.
-
-Just try it out for yourself, the usage of HttpRouter is very straightforward. The package is compact and minimalistic, but also probably one of the easiest routers to set up.
-
-## Where can I find Middleware *X*?
-
-This package just provides a very efficient request router with a few extra features. The router is just a [`http.Handler`][http.Handler], you can chain any http.Handler compatible middleware before the router, for example the [Gorilla handlers](http://www.gorillatoolkit.org/pkg/handlers). Or you could [just write your own](https://justinas.org/writing-http-middleware-in-go/), it's very easy!
-
-Alternatively, you could try [a web framework based on HttpRouter](#web-frameworks-based-on-httprouter).
-
-### Multi-domain / Sub-domains
-
-Here is a quick example: Does your server serve multiple domains / hosts?
-You want to use sub-domains?
-Define a router per host!
-
-```go
-// We need an object that implements the http.Handler interface.
-// Therefore we need a type for which we implement the ServeHTTP method.
-// We just use a map here, in which we map host names (with port) to http.Handlers
-type HostSwitch map[string]http.Handler
-
-// Implement the ServerHTTP method on our new type
-func (hs HostSwitch) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- // Check if a http.Handler is registered for the given host.
- // If yes, use it to handle the request.
- if handler := hs[r.Host]; handler != nil {
- handler.ServeHTTP(w, r)
- } else {
- // Handle host names for wich no handler is registered
- http.Error(w, "Forbidden", 403) // Or Redirect?
- }
-}
-
-func main() {
- // Initialize a router as usual
- router := httprouter.New()
- router.GET("/", Index)
- router.GET("/hello/:name", Hello)
-
- // Make a new HostSwitch and insert the router (our http handler)
- // for example.com and port 12345
- hs := make(HostSwitch)
- hs["example.com:12345"] = router
-
- // Use the HostSwitch to listen and serve on port 12345
- log.Fatal(http.ListenAndServe(":12345", hs))
-}
-```
-
-### Basic Authentication
-
-Another quick example: Basic Authentication (RFC 2617) for handles:
-
-```go
-package main
-
-import (
- "bytes"
- "encoding/base64"
- "fmt"
- "github.com/julienschmidt/httprouter"
- "net/http"
- "log"
- "strings"
-)
-
-func BasicAuth(h httprouter.Handle, user, pass []byte) httprouter.Handle {
- return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
- const basicAuthPrefix string = "Basic "
-
- // Get the Basic Authentication credentials
- auth := r.Header.Get("Authorization")
- if strings.HasPrefix(auth, basicAuthPrefix) {
- // Check credentials
- payload, err := base64.StdEncoding.DecodeString(auth[len(basicAuthPrefix):])
- if err == nil {
- pair := bytes.SplitN(payload, []byte(":"), 2)
- if len(pair) == 2 &&
- bytes.Equal(pair[0], user) &&
- bytes.Equal(pair[1], pass) {
-
- // Delegate request to the given handle
- h(w, r, ps)
- return
- }
- }
- }
-
- // Request Basic Authentication otherwise
- w.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
- http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
- }
-}
-
-func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
- fmt.Fprint(w, "Not protected!\n")
-}
-
-func Protected(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
- fmt.Fprint(w, "Protected!\n")
-}
-
-func main() {
- user := []byte("gordon")
- pass := []byte("secret!")
-
- router := httprouter.New()
- router.GET("/", Index)
- router.GET("/protected/", BasicAuth(Protected, user, pass))
-
- log.Fatal(http.ListenAndServe(":8080", router))
-}
-```
-
-## Chaining with the NotFound handler
-
-**NOTE: It might be required to set [`Router.HandleMethodNotAllowed`][Router.HandleMethodNotAllowed] to `false` to avoid problems.**
-
-You can use another [`http.Handler`][http.Handler], for example another router, to handle requests which could not be matched by this router by using the [`Router.NotFound`][Router.NotFound] handler. This allows chaining.
-
-### Static files
-
-The `NotFound` handler can for example be used to serve static files from the root path `/` (like an `index.html` file along with other assets):
-
-```go
-// Serve static files from the ./public directory
-router.NotFound = http.FileServer(http.Dir("public"))
-```
-
-But this approach sidesteps the strict core rules of this router to avoid routing problems. A cleaner approach is to use a distinct sub-path for serving files, like `/static/*filepath` or `/files/*filepath`.
-
-## Web Frameworks based on HttpRouter
-
-If the HttpRouter is a bit too minimalistic for you, you might try one of the following more high-level 3rd-party web frameworks building upon the HttpRouter package:
-
-* [Ace](https://github.com/plimble/ace): Blazing fast Go Web Framework
-* [api2go](https://github.com/manyminds/api2go): A JSON API Implementation for Go
-* [Gin](https://github.com/gin-gonic/gin): Features a martini-like API with much better performance
-* [Goat](https://github.com/bahlo/goat): A minimalistic REST API server in Go
-* [Hikaru](https://github.com/najeira/hikaru): Supports standalone and Google AppEngine
-* [Hitch](https://github.com/nbio/hitch): Hitch ties httprouter, [httpcontext](https://github.com/nbio/httpcontext), and middleware up in a bow
-* [httpway](https://github.com/corneldamian/httpway): Simple middleware extension with context for httprouter and a server with gracefully shutdown support
-* [kami](https://github.com/guregu/kami): A tiny web framework using x/net/context
-* [Medeina](https://github.com/imdario/medeina): Inspired by Ruby's Roda and Cuba
-* [Neko](https://github.com/rocwong/neko): A lightweight web application framework for Golang
-* [Roxanna](https://github.com/iamthemuffinman/Roxanna): An amalgamation of httprouter, better logging, and hot reload
-* [siesta](https://github.com/VividCortex/siesta): Composable HTTP handlers with contexts
-
-[benchmark]: <https://github.com/julienschmidt/go-http-routing-benchmark>
-[http.Handler]: <https://golang.org/pkg/net/http/#Handler
-[http.ServeMux]: <https://golang.org/pkg/net/http/#ServeMux>
-[Router.Handle]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.Handle>
-[Router.HandleMethodNotAllowed]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.HandleMethodNotAllowed>
-[Router.Handler]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.Handler>
-[Router.HandlerFunc]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.HandlerFunc>
-[Router.NotFound]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.NotFound>
-[Router.PanicHandler]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.PanicHandler>
-[Router.ServeFiles]: <https://godoc.org/github.com/julienschmidt/httprouter#Router.ServeFiles>
diff --git a/src/vendor/github.com/julienschmidt/httprouter/path_test.go b/src/vendor/github.com/julienschmidt/httprouter/path_test.go
deleted file mode 100644
index c4ceda5..0000000
--- a/src/vendor/github.com/julienschmidt/httprouter/path_test.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 Julien Schmidt. All rights reserved.
-// Based on the path package, Copyright 2009 The Go Authors.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-
-package httprouter
-
-import (
- "runtime"
- "testing"
-)
-
-var cleanTests = []struct {
- path, result string
-}{
- // Already clean
- {"/", "/"},
- {"/abc", "/abc"},
- {"/a/b/c", "/a/b/c"},
- {"/abc/", "/abc/"},
- {"/a/b/c/", "/a/b/c/"},
-
- // missing root
- {"", "/"},
- {"abc", "/abc"},
- {"abc/def", "/abc/def"},
- {"a/b/c", "/a/b/c"},
-
- // Remove doubled slash
- {"//", "/"},
- {"/abc//", "/abc/"},
- {"/abc/def//", "/abc/def/"},
- {"/a/b/c//", "/a/b/c/"},
- {"/abc//def//ghi", "/abc/def/ghi"},
- {"//abc", "/abc"},
- {"///abc", "/abc"},
- {"//abc//", "/abc/"},
-
- // Remove . elements
- {".", "/"},
- {"./", "/"},
- {"/abc/./def", "/abc/def"},
- {"/./abc/def", "/abc/def"},
- {"/abc/.", "/abc/"},
-
- // Remove .. elements
- {"..", "/"},
- {"../", "/"},
- {"../../", "/"},
- {"../..", "/"},
- {"../../abc", "/abc"},
- {"/abc/def/ghi/../jkl", "/abc/def/jkl"},
- {"/abc/def/../ghi/../jkl", "/abc/jkl"},
- {"/abc/def/..", "/abc"},
- {"/abc/def/../..", "/"},
- {"/abc/def/../../..", "/"},
- {"/abc/def/../../..", "/"},
- {"/abc/def/../../../ghi/jkl/../../../mno", "/mno"},
-
- // Combinations
- {"abc/./../def", "/def"},
- {"abc//./../def", "/def"},
- {"abc/../../././../def", "/def"},
-}
-
-func TestPathClean(t *testing.T) {
- for _, test := range cleanTests {
- if s := CleanPath(test.path); s != test.result {
- t.Errorf("CleanPath(%q) = %q, want %q", test.path, s, test.result)
- }
- if s := CleanPath(test.result); s != test.result {
- t.Errorf("CleanPath(%q) = %q, want %q", test.result, s, test.result)
- }
- }
-}
-
-func TestPathCleanMallocs(t *testing.T) {
- if testing.Short() {
- t.Skip("skipping malloc count in short mode")
- }
- if runtime.GOMAXPROCS(0) > 1 {
- t.Log("skipping AllocsPerRun checks; GOMAXPROCS>1")
- return
- }
-
- for _, test := range cleanTests {
- allocs := testing.AllocsPerRun(100, func() { CleanPath(test.result) })
- if allocs > 0 {
- t.Errorf("CleanPath(%q): %v allocs, want zero", test.result, allocs)
- }
- }
-}
diff --git a/src/vendor/github.com/julienschmidt/httprouter/router_test.go b/src/vendor/github.com/julienschmidt/httprouter/router_test.go
deleted file mode 100644
index e3141bd..0000000
--- a/src/vendor/github.com/julienschmidt/httprouter/router_test.go
+++ /dev/null
@@ -1,420 +0,0 @@
-// Copyright 2013 Julien Schmidt. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-
-package httprouter
-
-import (
- "errors"
- "fmt"
- "net/http"
- "net/http/httptest"
- "reflect"
- "testing"
-)
-
-type mockResponseWriter struct{}
-
-func (m *mockResponseWriter) Header() (h http.Header) {
- return http.Header{}
-}
-
-func (m *mockResponseWriter) Write(p []byte) (n int, err error) {
- return len(p), nil
-}
-
-func (m *mockResponseWriter) WriteString(s string) (n int, err error) {
- return len(s), nil
-}
-
-func (m *mockResponseWriter) WriteHeader(int) {}
-
-func TestParams(t *testing.T) {
- ps := Params{
- Param{"param1", "value1"},
- Param{"param2", "value2"},
- Param{"param3", "value3"},
- }
- for i := range ps {
- if val := ps.ByName(ps[i].Key); val != ps[i].Value {
- t.Errorf("Wrong value for %s: Got %s; Want %s", ps[i].Key, val, ps[i].Value)
- }
- }
- if val := ps.ByName("noKey"); val != "" {
- t.Errorf("Expected empty string for not found key; got: %s", val)
- }
-}
-
-func TestRouter(t *testing.T) {
- router := New()
-
- routed := false
- router.Handle("GET", "/user/:name", func(w http.ResponseWriter, r *http.Request, ps Params) {
- routed = true
- want := Params{Param{"name", "gopher"}}
- if !reflect.DeepEqual(ps, want) {
- t.Fatalf("wrong wildcard values: want %v, got %v", want, ps)
- }
- })
-
- w := new(mockResponseWriter)
-
- req, _ := http.NewRequest("GET", "/user/gopher", nil)
- router.ServeHTTP(w, req)
-
- if !routed {
- t.Fatal("routing failed")
- }
-}
-
-type handlerStruct struct {
- handeled *bool
-}
-
-func (h handlerStruct) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- *h.handeled = true
-}
-
-func TestRouterAPI(t *testing.T) {
- var get, head, options, post, put, patch, delete, handler, handlerFunc bool
-
- httpHandler := handlerStruct{&handler}
-
- router := New()
- router.GET("/GET", func(w http.ResponseWriter, r *http.Request, _ Params) {
- get = true
- })
- router.HEAD("/GET", func(w http.ResponseWriter, r *http.Request, _ Params) {
- head = true
- })
- router.OPTIONS("/GET", func(w http.ResponseWriter, r *http.Request, _ Params) {
- options = true
- })
- router.POST("/POST", func(w http.ResponseWriter, r *http.Request, _ Params) {
- post = true
- })
- router.PUT("/PUT", func(w http.ResponseWriter, r *http.Request, _ Params) {
- put = true
- })
- router.PATCH("/PATCH", func(w http.ResponseWriter, r *http.Request, _ Params) {
- patch = true
- })
- router.DELETE("/DELETE", func(w http.ResponseWriter, r *http.Request, _ Params) {
- delete = true
- })
- router.Handler("GET", "/Handler", httpHandler)
- router.HandlerFunc("GET", "/HandlerFunc", func(w http.ResponseWriter, r *http.Request) {
- handlerFunc = true
- })
-
- w := new(mockResponseWriter)
-
- r, _ := http.NewRequest("GET", "/GET", nil)
- router.ServeHTTP(w, r)
- if !get {
- t.Error("routing GET failed")
- }
-
- r, _ = http.NewRequest("HEAD", "/GET", nil)
- router.ServeHTTP(w, r)
- if !head {
- t.Error("routing HEAD failed")
- }
-
- r, _ = http.NewRequest("OPTIONS", "/GET", nil)
- router.ServeHTTP(w, r)
- if !options {
- t.Error("routing OPTIONS failed")
- }
-
- r, _ = http.NewRequest("POST", "/POST", nil)
- router.ServeHTTP(w, r)
- if !post {
- t.Error("routing POST failed")
- }
-
- r, _ = http.NewRequest("PUT", "/PUT", nil)
- router.ServeHTTP(w, r)
- if !put {
- t.Error("routing PUT failed")
- }
-
- r, _ = http.NewRequest("PATCH", "/PATCH", nil)
- router.ServeHTTP(w, r)
- if !patch {
- t.Error("routing PATCH failed")
- }
-
- r, _ = http.NewRequest("DELETE", "/DELETE", nil)
- router.ServeHTTP(w, r)
- if !delete {
- t.Error("routing DELETE failed")
- }
-
- r, _ = http.NewRequest("GET", "/Handler", nil)
- router.ServeHTTP(w, r)
- if !handler {
- t.Error("routing Handler failed")
- }
-
- r, _ = http.NewRequest("GET", "/HandlerFunc", nil)
- router.ServeHTTP(w, r)
- if !handlerFunc {
- t.Error("routing HandlerFunc failed")
- }
-}
-
-func TestRouterRoot(t *testing.T) {
- router := New()
- recv := catchPanic(func() {
- router.GET("noSlashRoot", nil)
- })
- if recv == nil {
- t.Fatal("registering path not beginning with '/' did not panic")
- }
-}
-
-func TestRouterChaining(t *testing.T) {
- router1 := New()
- router2 := New()
- router1.NotFound = router2
-
- fooHit := false
- router1.POST("/foo", func(w http.ResponseWriter, req *http.Request, _ Params) {
- fooHit = true
- w.WriteHeader(http.StatusOK)
- })
-
- barHit := false
- router2.POST("/bar", func(w http.ResponseWriter, req *http.Request, _ Params) {
- barHit = true
- w.WriteHeader(http.StatusOK)
- })
-
- r, _ := http.NewRequest("POST", "/foo", nil)
- w := httptest.NewRecorder()
- router1.ServeHTTP(w, r)
- if !(w.Code == http.StatusOK && fooHit) {
- t.Errorf("Regular routing failed with router chaining.")
- t.FailNow()
- }
-
- r, _ = http.NewRequest("POST", "/bar", nil)
- w = httptest.NewRecorder()
- router1.ServeHTTP(w, r)
- if !(w.Code == http.StatusOK && barHit) {
- t.Errorf("Chained routing failed with router chaining.")
- t.FailNow()
- }
-
- r, _ = http.NewRequest("POST", "/qax", nil)
- w = httptest.NewRecorder()
- router1.ServeHTTP(w, r)
- if !(w.Code == http.StatusNotFound) {
- t.Errorf("NotFound behavior failed with router chaining.")
- t.FailNow()
- }
-}
-
-func TestRouterNotAllowed(t *testing.T) {
- handlerFunc := func(_ http.ResponseWriter, _ *http.Request, _ Params) {}
-
- router := New()
- router.POST("/path", handlerFunc)
-
- // Test not allowed
- r, _ := http.NewRequest("GET", "/path", nil)
- w := httptest.NewRecorder()
- router.ServeHTTP(w, r)
- if !(w.Code == http.StatusMethodNotAllowed) {
- t.Errorf("NotAllowed handling failed: Code=%d, Header=%v", w.Code, w.Header())
- }
-
- w = httptest.NewRecorder()
- responseText := "custom method"
- router.MethodNotAllowed = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
- w.WriteHeader(http.StatusTeapot)
- w.Write([]byte(responseText))
- })
- router.ServeHTTP(w, r)
- if got := w.Body.String(); !(got == responseText) {
- t.Errorf("unexpected response got %q want %q", got, responseText)
- }
- if w.Code != http.StatusTeapot {
- t.Errorf("unexpected response code %d want %d", w.Code, http.StatusTeapot)
- }
-}
-
-func TestRouterNotFound(t *testing.T) {
- handlerFunc := func(_ http.ResponseWriter, _ *http.Request, _ Params) {}
-
- router := New()
- router.GET("/path", handlerFunc)
- router.GET("/dir/", handlerFunc)
- router.GET("/", handlerFunc)
-
- testRoutes := []struct {
- route string
- code int
- header string
- }{
- {"/path/", 301, "map[Location:[/path]]"}, // TSR -/
- {"/dir", 301, "map[Location:[/dir/]]"}, // TSR +/
- {"", 301, "map[Location:[/]]"}, // TSR +/
- {"/PATH", 301, "map[Location:[/path]]"}, // Fixed Case
- {"/DIR/", 301, "map[Location:[/dir/]]"}, // Fixed Case
- {"/PATH/", 301, "map[Location:[/path]]"}, // Fixed Case -/
- {"/DIR", 301, "map[Location:[/dir/]]"}, // Fixed Case +/
- {"/../path", 301, "map[Location:[/path]]"}, // CleanPath
- {"/nope", 404, ""}, // NotFound
- }
- for _, tr := range testRoutes {
- r, _ := http.NewRequest("GET", tr.route, nil)
- w := httptest.NewRecorder()
- router.ServeHTTP(w, r)
- if !(w.Code == tr.code && (w.Code == 404 || fmt.Sprint(w.Header()) == tr.header)) {
- t.Errorf("NotFound handling route %s failed: Code=%d, Header=%v", tr.route, w.Code, w.Header())
- }
- }
-
- // Test custom not found handler
- var notFound bool
- router.NotFound = http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
- rw.WriteHeader(404)
- notFound = true
- })
- r, _ := http.NewRequest("GET", "/nope", nil)
- w := httptest.NewRecorder()
- router.ServeHTTP(w, r)
- if !(w.Code == 404 && notFound == true) {
- t.Errorf("Custom NotFound handler failed: Code=%d, Header=%v", w.Code, w.Header())
- }
-
- // Test other method than GET (want 307 instead of 301)
- router.PATCH("/path", handlerFunc)
- r, _ = http.NewRequest("PATCH", "/path/", nil)
- w = httptest.NewRecorder()
- router.ServeHTTP(w, r)
- if !(w.Code == 307 && fmt.Sprint(w.Header()) == "map[Location:[/path]]") {
- t.Errorf("Custom NotFound handler failed: Code=%d, Header=%v", w.Code, w.Header())
- }
-
- // Test special case where no node for the prefix "/" exists
- router = New()
- router.GET("/a", handlerFunc)
- r, _ = http.NewRequest("GET", "/", nil)
- w = httptest.NewRecorder()
- router.ServeHTTP(w, r)
- if !(w.Code == 404) {
- t.Errorf("NotFound handling route / failed: Code=%d", w.Code)
- }
-}
-
-func TestRouterPanicHandler(t *testing.T) {
- router := New()
- panicHandled := false
-
- router.PanicHandler = func(rw http.ResponseWriter, r *http.Request, p interface{}) {
- panicHandled = true
- }
-
- router.Handle("PUT", "/user/:name", func(_ http.ResponseWriter, _ *http.Request, _ Params) {
- panic("oops!")
- })
-
- w := new(mockResponseWriter)
- req, _ := http.NewRequest("PUT", "/user/gopher", nil)
-
- defer func() {
- if rcv := recover(); rcv != nil {
- t.Fatal("handling panic failed")
- }
- }()
-
- router.ServeHTTP(w, req)
-
- if !panicHandled {
- t.Fatal("simulating failed")
- }
-}
-
-func TestRouterLookup(t *testing.T) {
- routed := false
- wantHandle := func(_ http.ResponseWriter, _ *http.Request, _ Params) {
- routed = true
- }
- wantParams := Params{Param{"name", "gopher"}}
-
- router := New()
-
- // try empty router first
- handle, _, tsr := router.Lookup("GET", "/nope")
- if handle != nil {
- t.Fatalf("Got handle for unregistered pattern: %v", handle)
- }
- if tsr {
- t.Error("Got wrong TSR recommendation!")
- }
-
- // insert route and try again
- router.GET("/user/:name", wantHandle)
-
- handle, params, tsr := router.Lookup("GET", "/user/gopher")
- if handle == nil {
- t.Fatal("Got no handle!")
- } else {
- handle(nil, nil, nil)
- if !routed {
- t.Fatal("Routing failed!")
- }
- }
-
- if !reflect.DeepEqual(params, wantParams) {
- t.Fatalf("Wrong parameter values: want %v, got %v", wantParams, params)
- }
-
- handle, _, tsr = router.Lookup("GET", "/user/gopher/")
- if handle != nil {
- t.Fatalf("Got handle for unregistered pattern: %v", handle)
- }
- if !tsr {
- t.Error("Got no TSR recommendation!")
- }
-
- handle, _, tsr = router.Lookup("GET", "/nope")
- if handle != nil {
- t.Fatalf("Got handle for unregistered pattern: %v", handle)
- }
- if tsr {
- t.Error("Got wrong TSR recommendation!")
- }
-}
-
-type mockFileSystem struct {
- opened bool
-}
-
-func (mfs *mockFileSystem) Open(name string) (http.File, error) {
- mfs.opened = true
- return nil, errors.New("this is just a mock")
-}
-
-func TestRouterServeFiles(t *testing.T) {
- router := New()
- mfs := &mockFileSystem{}
-
- recv := catchPanic(func() {
- router.ServeFiles("/noFilepath", mfs)
- })
- if recv == nil {
- t.Fatal("registering path not ending with '*filepath' did not panic")
- }
-
- router.ServeFiles("/*filepath", mfs)
- w := new(mockResponseWriter)
- r, _ := http.NewRequest("GET", "/favicon.ico", nil)
- router.ServeHTTP(w, r)
- if !mfs.opened {
- t.Error("serving file failed")
- }
-}
diff --git a/src/vendor/github.com/julienschmidt/httprouter/tree_test.go b/src/vendor/github.com/julienschmidt/httprouter/tree_test.go
deleted file mode 100644
index 46d3299..0000000
--- a/src/vendor/github.com/julienschmidt/httprouter/tree_test.go
+++ /dev/null
@@ -1,635 +0,0 @@
-// Copyright 2013 Julien Schmidt. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be found
-// in the LICENSE file.
-
-package httprouter
-
-import (
- "fmt"
- "net/http"
- "reflect"
- "strings"
- "testing"
-)
-
-func printChildren(n *node, prefix string) {
- fmt.Printf(" %02d:%02d %s%s[%d] %v %t %d \r\n", n.priority, n.maxParams, prefix, n.path, len(n.children), n.handle, n.wildChild, n.nType)
- for l := len(n.path); l > 0; l-- {
- prefix += " "
- }
- for _, child := range n.children {
- printChildren(child, prefix)
- }
-}
-
-// Used as a workaround since we can't compare functions or their adresses
-var fakeHandlerValue string
-
-func fakeHandler(val string) Handle {
- return func(http.ResponseWriter, *http.Request, Params) {
- fakeHandlerValue = val
- }
-}
-
-type testRequests []struct {
- path string
- nilHandler bool
- route string
- ps Params
-}
-
-func checkRequests(t *testing.T, tree *node, requests testRequests) {
- for _, request := range requests {
- handler, ps, _ := tree.getValue(request.path)
-
- if handler == nil {
- if !request.nilHandler {
- t.Errorf("handle mismatch for route '%s': Expected non-nil handle", request.path)
- }
- } else if request.nilHandler {
- t.Errorf("handle mismatch for route '%s': Expected nil handle", request.path)
- } else {
- handler(nil, nil, nil)
- if fakeHandlerValue != request.route {
- t.Errorf("handle mismatch for route '%s': Wrong handle (%s != %s)", request.path, fakeHandlerValue, request.route)
- }
- }
-
- if !reflect.DeepEqual(ps, request.ps) {
- t.Errorf("Params mismatch for route '%s'", request.path)
- }
- }
-}
-
-func checkPriorities(t *testing.T, n *node) uint32 {
- var prio uint32
- for i := range n.children {
- prio += checkPriorities(t, n.children[i])
- }
-
- if n.handle != nil {
- prio++
- }
-
- if n.priority != prio {
- t.Errorf(
- "priority mismatch for node '%s': is %d, should be %d",
- n.path, n.priority, prio,
- )
- }
-
- return prio
-}
-
-func checkMaxParams(t *testing.T, n *node) uint8 {
- var maxParams uint8
- for i := range n.children {
- params := checkMaxParams(t, n.children[i])
- if params > maxParams {
- maxParams = params
- }
- }
- if n.nType > root && !n.wildChild {
- maxParams++
- }
-
- if n.maxParams != maxParams {
- t.Errorf(
- "maxParams mismatch for node '%s': is %d, should be %d",
- n.path, n.maxParams, maxParams,
- )
- }
-
- return maxParams
-}
-
-func TestCountParams(t *testing.T) {
- if countParams("/path/:param1/static/*catch-all") != 2 {
- t.Fail()
- }
- if countParams(strings.Repeat("/:param", 256)) != 255 {
- t.Fail()
- }
-}
-
-func TestTreeAddAndGet(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/hi",
- "/contact",
- "/co",
- "/c",
- "/a",
- "/ab",
- "/doc/",
- "/doc/go_faq.html",
- "/doc/go1.html",
- "/α",
- "/β",
- }
- for _, route := range routes {
- tree.addRoute(route, fakeHandler(route))
- }
-
- //printChildren(tree, "")
-
- checkRequests(t, tree, testRequests{
- {"/a", false, "/a", nil},
- {"/", true, "", nil},
- {"/hi", false, "/hi", nil},
- {"/contact", false, "/contact", nil},
- {"/co", false, "/co", nil},
- {"/con", true, "", nil}, // key mismatch
- {"/cona", true, "", nil}, // key mismatch
- {"/no", true, "", nil}, // no matching child
- {"/ab", false, "/ab", nil},
- {"/α", false, "/α", nil},
- {"/β", false, "/β", nil},
- })
-
- checkPriorities(t, tree)
- checkMaxParams(t, tree)
-}
-
-func TestTreeWildcard(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/",
- "/cmd/:tool/:sub",
- "/cmd/:tool/",
- "/src/*filepath",
- "/search/",
- "/search/:query",
- "/user_:name",
- "/user_:name/about",
- "/files/:dir/*filepath",
- "/doc/",
- "/doc/go_faq.html",
- "/doc/go1.html",
- "/info/:user/public",
- "/info/:user/project/:project",
- }
- for _, route := range routes {
- tree.addRoute(route, fakeHandler(route))
- }
-
- //printChildren(tree, "")
-
- checkRequests(t, tree, testRequests{
- {"/", false, "/", nil},
- {"/cmd/test/", false, "/cmd/:tool/", Params{Param{"tool", "test"}}},
- {"/cmd/test", true, "", Params{Param{"tool", "test"}}},
- {"/cmd/test/3", false, "/cmd/:tool/:sub", Params{Param{"tool", "test"}, Param{"sub", "3"}}},
- {"/src/", false, "/src/*filepath", Params{Param{"filepath", "/"}}},
- {"/src/some/file.png", false, "/src/*filepath", Params{Param{"filepath", "/some/file.png"}}},
- {"/search/", false, "/search/", nil},
- {"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{"query", "someth!ng+in+ünìcodé"}}},
- {"/search/someth!ng+in+ünìcodé/", true, "", Params{Param{"query", "someth!ng+in+ünìcodé"}}},
- {"/user_gopher", false, "/user_:name", Params{Param{"name", "gopher"}}},
- {"/user_gopher/about", false, "/user_:name/about", Params{Param{"name", "gopher"}}},
- {"/files/js/inc/framework.js", false, "/files/:dir/*filepath", Params{Param{"dir", "js"}, Param{"filepath", "/inc/framework.js"}}},
- {"/info/gordon/public", false, "/info/:user/public", Params{Param{"user", "gordon"}}},
- {"/info/gordon/project/go", false, "/info/:user/project/:project", Params{Param{"user", "gordon"}, Param{"project", "go"}}},
- })
-
- checkPriorities(t, tree)
- checkMaxParams(t, tree)
-}
-
-func catchPanic(testFunc func()) (recv interface{}) {
- defer func() {
- recv = recover()
- }()
-
- testFunc()
- return
-}
-
-type testRoute struct {
- path string
- conflict bool
-}
-
-func testRoutes(t *testing.T, routes []testRoute) {
- tree := &node{}
-
- for _, route := range routes {
- recv := catchPanic(func() {
- tree.addRoute(route.path, nil)
- })
-
- if route.conflict {
- if recv == nil {
- t.Errorf("no panic for conflicting route '%s'", route.path)
- }
- } else if recv != nil {
- t.Errorf("unexpected panic for route '%s': %v", route.path, recv)
- }
- }
-
- //printChildren(tree, "")
-}
-
-func TestTreeWildcardConflict(t *testing.T) {
- routes := []testRoute{
- {"/cmd/:tool/:sub", false},
- {"/cmd/vet", true},
- {"/src/*filepath", false},
- {"/src/*filepathx", true},
- {"/src/", true},
- {"/src1/", false},
- {"/src1/*filepath", true},
- {"/src2*filepath", true},
- {"/search/:query", false},
- {"/search/invalid", true},
- {"/user_:name", false},
- {"/user_x", true},
- {"/user_:name", false},
- {"/id:id", false},
- {"/id/:id", true},
- }
- testRoutes(t, routes)
-}
-
-func TestTreeChildConflict(t *testing.T) {
- routes := []testRoute{
- {"/cmd/vet", false},
- {"/cmd/:tool/:sub", true},
- {"/src/AUTHORS", false},
- {"/src/*filepath", true},
- {"/user_x", false},
- {"/user_:name", true},
- {"/id/:id", false},
- {"/id:id", true},
- {"/:id", true},
- {"/*filepath", true},
- }
- testRoutes(t, routes)
-}
-
-func TestTreeDupliatePath(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/",
- "/doc/",
- "/src/*filepath",
- "/search/:query",
- "/user_:name",
- }
- for _, route := range routes {
- recv := catchPanic(func() {
- tree.addRoute(route, fakeHandler(route))
- })
- if recv != nil {
- t.Fatalf("panic inserting route '%s': %v", route, recv)
- }
-
- // Add again
- recv = catchPanic(func() {
- tree.addRoute(route, nil)
- })
- if recv == nil {
- t.Fatalf("no panic while inserting duplicate route '%s", route)
- }
- }
-
- //printChildren(tree, "")
-
- checkRequests(t, tree, testRequests{
- {"/", false, "/", nil},
- {"/doc/", false, "/doc/", nil},
- {"/src/some/file.png", false, "/src/*filepath", Params{Param{"filepath", "/some/file.png"}}},
- {"/search/someth!ng+in+ünìcodé", false, "/search/:query", Params{Param{"query", "someth!ng+in+ünìcodé"}}},
- {"/user_gopher", false, "/user_:name", Params{Param{"name", "gopher"}}},
- })
-}
-
-func TestEmptyWildcardName(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/user:",
- "/user:/",
- "/cmd/:/",
- "/src/*",
- }
- for _, route := range routes {
- recv := catchPanic(func() {
- tree.addRoute(route, nil)
- })
- if recv == nil {
- t.Fatalf("no panic while inserting route with empty wildcard name '%s", route)
- }
- }
-}
-
-func TestTreeCatchAllConflict(t *testing.T) {
- routes := []testRoute{
- {"/src/*filepath/x", true},
- {"/src2/", false},
- {"/src2/*filepath/x", true},
- }
- testRoutes(t, routes)
-}
-
-func TestTreeCatchAllConflictRoot(t *testing.T) {
- routes := []testRoute{
- {"/", false},
- {"/*filepath", true},
- }
- testRoutes(t, routes)
-}
-
-func TestTreeDoubleWildcard(t *testing.T) {
- const panicMsg = "only one wildcard per path segment is allowed"
-
- routes := [...]string{
- "/:foo:bar",
- "/:foo:bar/",
- "/:foo*bar",
- }
-
- for _, route := range routes {
- tree := &node{}
- recv := catchPanic(func() {
- tree.addRoute(route, nil)
- })
-
- if rs, ok := recv.(string); !ok || !strings.HasPrefix(rs, panicMsg) {
- t.Fatalf(`"Expected panic "%s" for route '%s', got "%v"`, panicMsg, route, recv)
- }
- }
-}
-
-/*func TestTreeDuplicateWildcard(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/:id/:name/:id",
- }
- for _, route := range routes {
- ...
- }
-}*/
-
-func TestTreeTrailingSlashRedirect(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/hi",
- "/b/",
- "/search/:query",
- "/cmd/:tool/",
- "/src/*filepath",
- "/x",
- "/x/y",
- "/y/",
- "/y/z",
- "/0/:id",
- "/0/:id/1",
- "/1/:id/",
- "/1/:id/2",
- "/aa",
- "/a/",
- "/admin",
- "/admin/:category",
- "/admin/:category/:page",
- "/doc",
- "/doc/go_faq.html",
- "/doc/go1.html",
- "/no/a",
- "/no/b",
- "/api/hello/:name",
- }
- for _, route := range routes {
- recv := catchPanic(func() {
- tree.addRoute(route, fakeHandler(route))
- })
- if recv != nil {
- t.Fatalf("panic inserting route '%s': %v", route, recv)
- }
- }
-
- //printChildren(tree, "")
-
- tsrRoutes := [...]string{
- "/hi/",
- "/b",
- "/search/gopher/",
- "/cmd/vet",
- "/src",
- "/x/",
- "/y",
- "/0/go/",
- "/1/go",
- "/a",
- "/admin/",
- "/admin/config/",
- "/admin/config/permissions/",
- "/doc/",
- }
- for _, route := range tsrRoutes {
- handler, _, tsr := tree.getValue(route)
- if handler != nil {
- t.Fatalf("non-nil handler for TSR route '%s", route)
- } else if !tsr {
- t.Errorf("expected TSR recommendation for route '%s'", route)
- }
- }
-
- noTsrRoutes := [...]string{
- "/",
- "/no",
- "/no/",
- "/_",
- "/_/",
- "/api/world/abc",
- }
- for _, route := range noTsrRoutes {
- handler, _, tsr := tree.getValue(route)
- if handler != nil {
- t.Fatalf("non-nil handler for No-TSR route '%s", route)
- } else if tsr {
- t.Errorf("expected no TSR recommendation for route '%s'", route)
- }
- }
-}
-
-func TestTreeRootTrailingSlashRedirect(t *testing.T) {
- tree := &node{}
-
- recv := catchPanic(func() {
- tree.addRoute("/:test", fakeHandler("/:test"))
- })
- if recv != nil {
- t.Fatalf("panic inserting test route: %v", recv)
- }
-
- handler, _, tsr := tree.getValue("/")
- if handler != nil {
- t.Fatalf("non-nil handler")
- } else if tsr {
- t.Errorf("expected no TSR recommendation")
- }
-}
-
-func TestTreeFindCaseInsensitivePath(t *testing.T) {
- tree := &node{}
-
- routes := [...]string{
- "/hi",
- "/b/",
- "/ABC/",
- "/search/:query",
- "/cmd/:tool/",
- "/src/*filepath",
- "/x",
- "/x/y",
- "/y/",
- "/y/z",
- "/0/:id",
- "/0/:id/1",
- "/1/:id/",
- "/1/:id/2",
- "/aa",
- "/a/",
- "/doc",
- "/doc/go_faq.html",
- "/doc/go1.html",
- "/doc/go/away",
- "/no/a",
- "/no/b",
- }
-
- for _, route := range routes {
- recv := catchPanic(func() {
- tree.addRoute(route, fakeHandler(route))
- })
- if recv != nil {
- t.Fatalf("panic inserting route '%s': %v", route, recv)
- }
- }
-
- // Check out == in for all registered routes
- // With fixTrailingSlash = true
- for _, route := range routes {
- out, found := tree.findCaseInsensitivePath(route, true)
- if !found {
- t.Errorf("Route '%s' not found!", route)
- } else if string(out) != route {
- t.Errorf("Wrong result for route '%s': %s", route, string(out))
- }
- }
- // With fixTrailingSlash = false
- for _, route := range routes {
- out, found := tree.findCaseInsensitivePath(route, false)
- if !found {
- t.Errorf("Route '%s' not found!", route)
- } else if string(out) != route {
- t.Errorf("Wrong result for route '%s': %s", route, string(out))
- }
- }
-
- tests := []struct {
- in string
- out string
- found bool
- slash bool
- }{
- {"/HI", "/hi", true, false},
- {"/HI/", "/hi", true, true},
- {"/B", "/b/", true, true},
- {"/B/", "/b/", true, false},
- {"/abc", "/ABC/", true, true},
- {"/abc/", "/ABC/", true, false},
- {"/aBc", "/ABC/", true, true},
- {"/aBc/", "/ABC/", true, false},
- {"/abC", "/ABC/", true, true},
- {"/abC/", "/ABC/", true, false},
- {"/SEARCH/QUERY", "/search/QUERY", true, false},
- {"/SEARCH/QUERY/", "/search/QUERY", true, true},
- {"/CMD/TOOL/", "/cmd/TOOL/", true, false},
- {"/CMD/TOOL", "/cmd/TOOL/", true, true},
- {"/SRC/FILE/PATH", "/src/FILE/PATH", true, false},
- {"/x/Y", "/x/y", true, false},
- {"/x/Y/", "/x/y", true, true},
- {"/X/y", "/x/y", true, false},
- {"/X/y/", "/x/y", true, true},
- {"/X/Y", "/x/y", true, false},
- {"/X/Y/", "/x/y", true, true},
- {"/Y/", "/y/", true, false},
- {"/Y", "/y/", true, true},
- {"/Y/z", "/y/z", true, false},
- {"/Y/z/", "/y/z", true, true},
- {"/Y/Z", "/y/z", true, false},
- {"/Y/Z/", "/y/z", true, true},
- {"/y/Z", "/y/z", true, false},
- {"/y/Z/", "/y/z", true, true},
- {"/Aa", "/aa", true, false},
- {"/Aa/", "/aa", true, true},
- {"/AA", "/aa", true, false},
- {"/AA/", "/aa", true, true},
- {"/aA", "/aa", true, false},
- {"/aA/", "/aa", true, true},
- {"/A/", "/a/", true, false},
- {"/A", "/a/", true, true},
- {"/DOC", "/doc", true, false},
- {"/DOC/", "/doc", true, true},
- {"/NO", "", false, true},
- {"/DOC/GO", "", false, true},
- }
- // With fixTrailingSlash = true
- for _, test := range tests {
- out, found := tree.findCaseInsensitivePath(test.in, true)
- if found != test.found || (found && (string(out) != test.out)) {
- t.Errorf("Wrong result for '%s': got %s, %t; want %s, %t",
- test.in, string(out), found, test.out, test.found)
- return
- }
- }
- // With fixTrailingSlash = false
- for _, test := range tests {
- out, found := tree.findCaseInsensitivePath(test.in, false)
- if test.slash {
- if found { // test needs a trailingSlash fix. It must not be found!
- t.Errorf("Found without fixTrailingSlash: %s; got %s", test.in, string(out))
- }
- } else {
- if found != test.found || (found && (string(out) != test.out)) {
- t.Errorf("Wrong result for '%s': got %s, %t; want %s, %t",
- test.in, string(out), found, test.out, test.found)
- return
- }
- }
- }
-}
-
-func TestTreeInvalidNodeType(t *testing.T) {
- const panicMsg = "invalid node type"
-
- tree := &node{}
- tree.addRoute("/", fakeHandler("/"))
- tree.addRoute("/:page", fakeHandler("/:page"))
-
- // set invalid node type
- tree.children[0].nType = 42
-
- // normal lookup
- recv := catchPanic(func() {
- tree.getValue("/test")
- })
- if rs, ok := recv.(string); !ok || rs != panicMsg {
- t.Fatalf("Expected panic '"+panicMsg+"', got '%v'", recv)
- }
-
- // case-insensitive lookup
- recv = catchPanic(func() {
- tree.findCaseInsensitivePath("/test", true)
- })
- if rs, ok := recv.(string); !ok || rs != panicMsg {
- t.Fatalf("Expected panic '"+panicMsg+"', got '%v'", recv)
- }
-}
diff --git a/src/vendor/github.com/justinas/alice/.travis.yml b/src/vendor/github.com/justinas/alice/.travis.yml
deleted file mode 100644
index 9398694..0000000
--- a/src/vendor/github.com/justinas/alice/.travis.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-language: go
-
-install:
- - go get github.com/stretchr/testify/assert
-
-go:
- - 1.1
- - 1.2
- - 1.3
- - 1.4
- - tip
diff --git a/src/vendor/github.com/justinas/alice/README.md b/src/vendor/github.com/justinas/alice/README.md
deleted file mode 100644
index 88d2134..0000000
--- a/src/vendor/github.com/justinas/alice/README.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Alice
-
-[![Build Status](https://travis-ci.org/justinas/alice.svg?branch=master)](https://travis-ci.org/justinas/alice)
-
-Alice provides a convenient way to chain
-your HTTP middleware functions and the app handler.
-
-In short, it transforms
-
- Middleware1(Middleware2(Middleware3(App)))
-
-to
-
- alice.New(Middleware1, Middleware2, Middleware3).Then(App).
-
-### Why?
-
-None of the other middleware chaining solutions
-behaves exactly like Alice.
-Alice is as minimal as it gets:
-in essence, it's just a for loop that does the wrapping for you.
-
-Check out [this blog post](http://justinas.org/alice-painless-middleware-chaining-for-go/)
-for explanation how Alice is different from other chaining solutions.
-
-### Usage
-
-Your middleware constructors should have the form of
-
- func (http.Handler) http.Handler
-
-Some middleware provide this out of the box.
-For ones that don't, it's trivial to write one yourself.
-
-```go
-func myStripPrefix(h http.Handler) http.Handler {
- return http.StripPrefix("/old", h)
-}
-```
-
-This complete example shows the full power of Alice.
-
-```go
-package main
-
-import (
- "net/http"
- "time"
-
- "github.com/PuerkitoBio/throttled"
- "github.com/justinas/alice"
- "github.com/justinas/nosurf"
-)
-
-func timeoutHandler(h http.Handler) http.Handler {
- return http.TimeoutHandler(h, 1*time.Second, "timed out")
-}
-
-func myApp(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("Hello world!"))
-}
-
-func main() {
- th := throttled.Interval(throttled.PerSec(10), 1, &throttled.VaryBy{Path: true}, 50)
- myHandler := http.HandlerFunc(myApp)
-
- chain := alice.New(th.Throttle, timeoutHandler, nosurf.NewPure).Then(myHandler)
- http.ListenAndServe(":8000", chain)
-}
-```
-
-Here, the request will pass [throttled](https://github.com/PuerkitoBio/throttled) first,
-then an http.TimeoutHandler we've set up,
-then [nosurf](https://github.com/justinas/nosurf)
-and will finally reach our handler.
-
-Note that Alice makes **no guarantees** for
-how one or another piece of middleware will behave.
-It executes all middleware sequentially so that if a
-piece of middleware were to stop the chain,
-the request will not reach the inner handlers.
-This is intentional behavior.
-
-Alice works with Go 1.0 and higher,
-but running tests requires at least Go 1.1.
-
-### Contributing
-
-0. Find an issue that bugs you / open a new one.
-1. Discuss.
-2. Branch off, commit, test.
-3. Make a pull request / attach the commits to the issue.
diff --git a/src/vendor/github.com/justinas/alice/chain_test.go b/src/vendor/github.com/justinas/alice/chain_test.go
deleted file mode 100644
index 49c0470..0000000
--- a/src/vendor/github.com/justinas/alice/chain_test.go
+++ /dev/null
@@ -1,144 +0,0 @@
-// Package alice implements a middleware chaining solution.
-package alice
-
-import (
- "net/http"
- "net/http/httptest"
- "reflect"
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-// A constructor for middleware
-// 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)
- })
- }
-}
-
-// Not recommended (https://golang.org/pkg/reflect/#Value.Pointer),
-// but the best we can do.
-func funcsEqual(f1, f2 interface{}) bool {
- val1 := reflect.ValueOf(f1)
- val2 := reflect.ValueOf(f2)
- return val1.Pointer() == val2.Pointer()
-}
-
-var testApp = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("app\n"))
-})
-
-// Tests creating a new chain
-func TestNew(t *testing.T) {
- c1 := func(h http.Handler) http.Handler {
- return nil
- }
- c2 := func(h http.Handler) http.Handler {
- return http.StripPrefix("potato", nil)
- }
-
- slice := []Constructor{c1, c2}
-
- chain := New(slice...)
- assert.True(t, funcsEqual(chain.constructors[0], slice[0]))
- assert.True(t, funcsEqual(chain.constructors[1], slice[1]))
-}
-
-func TestThenWorksWithNoMiddleware(t *testing.T) {
- assert.NotPanics(t, func() {
- chain := New()
- final := chain.Then(testApp)
-
- assert.True(t, funcsEqual(final, testApp))
- })
-}
-
-func TestThenTreatsNilAsDefaultServeMux(t *testing.T) {
- chained := New().Then(nil)
- assert.Equal(t, chained, http.DefaultServeMux)
-}
-
-func TestThenFuncTreatsNilAsDefaultServeMux(t *testing.T) {
- chained := New().ThenFunc(nil)
- assert.Equal(t, chained, http.DefaultServeMux)
-}
-
-func TestThenOrdersHandlersRight(t *testing.T) {
- t1 := tagMiddleware("t1\n")
- t2 := tagMiddleware("t2\n")
- t3 := tagMiddleware("t3\n")
-
- chained := New(t1, t2, t3).Then(testApp)
-
- w := httptest.NewRecorder()
- r, err := http.NewRequest("GET", "/", nil)
- if err != nil {
- t.Fatal(err)
- }
-
- chained.ServeHTTP(w, r)
-
- assert.Equal(t, w.Body.String(), "t1\nt2\nt3\napp\n")
-}
-
-func TestAppendAddsHandlersCorrectly(t *testing.T) {
- chain := New(tagMiddleware("t1\n"), tagMiddleware("t2\n"))
- newChain := chain.Append(tagMiddleware("t3\n"), tagMiddleware("t4\n"))
-
- assert.Equal(t, len(chain.constructors), 2)
- assert.Equal(t, len(newChain.constructors), 4)
-
- chained := newChain.Then(testApp)
-
- w := httptest.NewRecorder()
- r, err := http.NewRequest("GET", "/", nil)
- if err != nil {
- t.Fatal(err)
- }
-
- chained.ServeHTTP(w, r)
-
- assert.Equal(t, w.Body.String(), "t1\nt2\nt3\nt4\napp\n")
-}
-
-func TestAppendRespectsImmutability(t *testing.T) {
- chain := New(tagMiddleware(""))
- newChain := chain.Append(tagMiddleware(""))
-
- assert.NotEqual(t, &chain.constructors[0], &newChain.constructors[0])
-}
-
-func TestExtendAddsHandlersCorrectly(t *testing.T) {
- chain1 := New(tagMiddleware("t1\n"), tagMiddleware("t2\n"))
- chain2 := New(tagMiddleware("t3\n"), tagMiddleware("t4\n"))
- newChain := chain1.Extend(chain2)
-
- assert.Equal(t, len(chain1.constructors), 2)
- assert.Equal(t, len(chain2.constructors), 2)
- assert.Equal(t, len(newChain.constructors), 4)
-
- chained := newChain.Then(testApp)
-
- w := httptest.NewRecorder()
- r, err := http.NewRequest("GET", "/", nil)
- if err != nil {
- t.Fatal(err)
- }
-
- chained.ServeHTTP(w, r)
-
- assert.Equal(t, w.Body.String(), "t1\nt2\nt3\nt4\napp\n")
-}
-
-func TestExtendRespectsImmutability(t *testing.T) {
- chain := New(tagMiddleware(""))
- newChain := chain.Extend(New(tagMiddleware("")))
-
- assert.NotEqual(t, &chain.constructors[0], &newChain.constructors[0])
-}
diff --git a/src/vendor/github.com/rs/cors/.travis.yml b/src/vendor/github.com/rs/cors/.travis.yml
deleted file mode 100644
index bbb5185..0000000
--- a/src/vendor/github.com/rs/cors/.travis.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-language: go
-go:
-- 1.3
-- 1.4
diff --git a/src/vendor/github.com/rs/cors/README.md b/src/vendor/github.com/rs/cors/README.md
deleted file mode 100644
index 4bf5672..0000000
--- a/src/vendor/github.com/rs/cors/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# Go CORS handler [![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/cors) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/cors/master/LICENSE) [![build](https://img.shields.io/travis/rs/cors.svg?style=flat)](https://travis-ci.org/rs/cors) [![Coverage](http://gocover.io/_badge/github.com/rs/cors)](http://gocover.io/github.com/rs/cors)
-
-CORS is a `net/http` handler implementing [Cross Origin Resource Sharing W3 specification](http://www.w3.org/TR/cors/) in Golang.
-
-## Getting Started
-
-After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`.
-
-```go
-package main
-
-import (
- "net/http"
-
- "github.com/rs/cors"
-)
-
-func main() {
- mux := http.NewServeMux()
- mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
- w.Header().Set("Content-Type", "application/json")
- w.Write([]byte("{\"hello\": \"world\"}"))
- })
-
- // cors.Default() setup the middleware with default options being
- // all origins accepted with simple methods (GET, POST). See
- // documentation below for more options.
- handler := cors.Default().Handler(mux)
- http.ListenAndServe(":8080", handler)
-}
-```
-
-Install `cors`:
-
- go get github.com/rs/cors
-
-Then run your server:
-
- go run server.go
-
-The server now runs on `localhost:8080`:
-
- $ curl -D - -H 'Origin: http://foo.com' http://localhost:8080/
- HTTP/1.1 200 OK
- Access-Control-Allow-Origin: foo.com
- Content-Type: application/json
- Date: Sat, 25 Oct 2014 03:43:57 GMT
- Content-Length: 18
-
- {"hello": "world"}
-
-### More Examples
-
-* `net/http`: [examples/nethttp/server.go](https://github.com/rs/cors/blob/master/examples/nethttp/server.go)
-* [Goji](https://goji.io): [examples/goji/server.go](https://github.com/rs/cors/blob/master/examples/goji/server.go)
-* [Martini](http://martini.codegangsta.io): [examples/martini/server.go](https://github.com/rs/cors/blob/master/examples/martini/server.go)
-* [Negroni](https://github.com/codegangsta/negroni): [examples/negroni/server.go](https://github.com/rs/cors/blob/master/examples/negroni/server.go)
-* [Alice](https://github.com/justinas/alice): [examples/alice/server.go](https://github.com/rs/cors/blob/master/examples/alice/server.go)
-
-## Parameters
-
-Parameters are passed to the middleware thru the `cors.New` method as follow:
-
-```go
-c := cors.New(cors.Options{
- AllowedOrigins: []string{"http://foo.com"},
- AllowCredentials: true,
-})
-
-// Insert the middleware
-handler = c.Handler(handler)
-```
-
-* **AllowedOrigins** `[]string`: A list of origins a cross-domain request can be executed from. If the special `*` value is present in the list, all origins will be allowed. An origin may contain a wildcard (`*`) to replace 0 or more characters (i.e.: `http://*.domain.com`). Usage of wildcards implies a small performance penality. Only one wildcard can be used per origin. The default value is `*`.
-* **AllowOriginFunc** `func (origin string) bool`: A custom function to validate the origin. It take the origin as argument and returns true if allowed or false otherwise. If this option is set, the content of `AllowedOrigins` is ignored
-* **AllowedMethods** `[]string`: A list of methods the client is allowed to use with cross-domain requests. Default value is simple methods (`GET` and `POST`).
-* **AllowedHeaders** `[]string`: A list of non simple headers the client is allowed to use with cross-domain requests.
-* **ExposedHeaders** `[]string`: Indicates which headers are safe to expose to the API of a CORS API specification
-* **AllowCredentials** `bool`: Indicates whether the request can include user credentials like cookies, HTTP authentication or client side SSL certificates. The default is `false`.
-* **MaxAge** `int`: Indicates how long (in seconds) the results of a preflight request can be cached. The default is `0` which stands for no max age.
-* **OptionsPassthrough** `bool`: Instructs preflight to let other potential next handlers to process the `OPTIONS` method. Turn this on if your application handles `OPTIONS`.
-* **Debug** `bool`: Debugging flag adds additional output to debug server side CORS issues.
-
-See [API documentation](http://godoc.org/github.com/rs/cors) for more info.
-
-## Benchmarks
-
- BenchmarkWithout 20000000 64.6 ns/op 8 B/op 1 allocs/op
- BenchmarkDefault 3000000 469 ns/op 114 B/op 2 allocs/op
- BenchmarkAllowedOrigin 3000000 608 ns/op 114 B/op 2 allocs/op
- BenchmarkPreflight 20000000 73.2 ns/op 0 B/op 0 allocs/op
- BenchmarkPreflightHeader 20000000 73.6 ns/op 0 B/op 0 allocs/op
- BenchmarkParseHeaderList 2000000 847 ns/op 184 B/op 6 allocs/op
- BenchmarkParse…Single 5000000 290 ns/op 32 B/op 3 allocs/op
- BenchmarkParse…Normalized 2000000 776 ns/op 160 B/op 6 allocs/op
-
-## Licenses
-
-All source code is licensed under the [MIT License](https://raw.github.com/rs/cors/master/LICENSE).
diff --git a/src/vendor/github.com/rs/cors/bench_test.go b/src/vendor/github.com/rs/cors/bench_test.go
deleted file mode 100644
index b6e3721..0000000
--- a/src/vendor/github.com/rs/cors/bench_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package cors
-
-import (
- "net/http"
- "testing"
-)
-
-type FakeResponse struct {
- header http.Header
-}
-
-func (r FakeResponse) Header() http.Header {
- return r.header
-}
-
-func (r FakeResponse) WriteHeader(n int) {
-}
-
-func (r FakeResponse) Write(b []byte) (n int, err error) {
- return len(b), nil
-}
-
-func BenchmarkWithout(b *testing.B) {
- res := FakeResponse{http.Header{}}
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
-
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- testHandler.ServeHTTP(res, req)
- }
-}
-
-func BenchmarkDefault(b *testing.B) {
- res := FakeResponse{http.Header{}}
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "somedomain.com")
- handler := Default().Handler(testHandler)
-
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- handler.ServeHTTP(res, req)
- }
-}
-
-func BenchmarkAllowedOrigin(b *testing.B) {
- res := FakeResponse{http.Header{}}
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "somedomain.com")
- c := New(Options{
- AllowedOrigins: []string{"somedomain.com"},
- })
- handler := c.Handler(testHandler)
-
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- handler.ServeHTTP(res, req)
- }
-}
-
-func BenchmarkPreflight(b *testing.B) {
- res := FakeResponse{http.Header{}}
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Access-Control-Request-Method", "GET")
- handler := Default().Handler(testHandler)
-
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- handler.ServeHTTP(res, req)
- }
-}
-
-func BenchmarkPreflightHeader(b *testing.B) {
- res := FakeResponse{http.Header{}}
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "Accept")
- handler := Default().Handler(testHandler)
-
- b.ReportAllocs()
- b.ResetTimer()
- for i := 0; i < b.N; i++ {
- handler.ServeHTTP(res, req)
- }
-}
diff --git a/src/vendor/github.com/rs/cors/cors_test.go b/src/vendor/github.com/rs/cors/cors_test.go
deleted file mode 100644
index 28672a0..0000000
--- a/src/vendor/github.com/rs/cors/cors_test.go
+++ /dev/null
@@ -1,371 +0,0 @@
-package cors
-
-import (
- "net/http"
- "net/http/httptest"
- "regexp"
- "strings"
- "testing"
-)
-
-var testHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("bar"))
-})
-
-func assertHeaders(t *testing.T, resHeaders http.Header, reqHeaders map[string]string) {
- for name, value := range reqHeaders {
- if actual := strings.Join(resHeaders[name], ", "); actual != value {
- t.Errorf("Invalid header `%s', wanted `%s', got `%s'", name, value, actual)
- }
- }
-}
-
-func TestNoConfig(t *testing.T) {
- s := New(Options{
- // Intentionally left blank.
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestMatchAllOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"*"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestWildcardOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://*.bar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foo.bar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "http://foo.bar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://barbaz.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedWildcardOrigin(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://*.bar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foo.baz.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedOriginFunc(t *testing.T) {
- r, _ := regexp.Compile("^http://foo")
- s := New(Options{
- AllowOriginFunc: func(o string) bool {
- return r.MatchString(o)
- },
- })
-
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
-
- res := httptest.NewRecorder()
- req.Header.Set("Origin", "http://foobar.com")
- s.Handler(testHandler).ServeHTTP(res, req)
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "http://foobar.com",
- })
-
- res = httptest.NewRecorder()
- req.Header.Set("Origin", "http://barfoo.com")
- s.Handler(testHandler).ServeHTTP(res, req)
- assertHeaders(t, res.Header(), map[string]string{
- "Access-Control-Allow-Origin": "",
- })
-}
-
-func TestAllowedMethod(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedMethods: []string{"PUT", "DELETE"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "PUT")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "PUT",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedMethod(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedMethods: []string{"PUT", "DELETE"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "PATCH")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedHeaders: []string{"X-Header-1", "x-header-2"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "X-Header-2, X-Header-1",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestAllowedWildcardHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedHeaders: []string{"*"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "X-Header-2, X-HEADER-1")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "X-Header-2, X-Header-1",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestDisallowedHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowedHeaders: []string{"X-Header-1", "x-header-2"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "X-Header-3, X-Header-1")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestOriginHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
- req.Header.Add("Access-Control-Request-Headers", "origin")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "Origin",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
-
-func TestExposedHeader(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- ExposedHeaders: []string{"X-Header-1", "x-header-2"},
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("GET", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "X-Header-1, X-Header-2",
- })
-}
-
-func TestAllowedCredentials(t *testing.T) {
- s := New(Options{
- AllowedOrigins: []string{"http://foobar.com"},
- AllowCredentials: true,
- })
-
- res := httptest.NewRecorder()
- req, _ := http.NewRequest("OPTIONS", "http://example.com/foo", nil)
- req.Header.Add("Origin", "http://foobar.com")
- req.Header.Add("Access-Control-Request-Method", "GET")
-
- s.Handler(testHandler).ServeHTTP(res, req)
-
- assertHeaders(t, res.Header(), map[string]string{
- "Vary": "Origin, Access-Control-Request-Method, Access-Control-Request-Headers",
- "Access-Control-Allow-Origin": "http://foobar.com",
- "Access-Control-Allow-Methods": "GET",
- "Access-Control-Allow-Headers": "",
- "Access-Control-Allow-Credentials": "true",
- "Access-Control-Max-Age": "",
- "Access-Control-Expose-Headers": "",
- })
-}
diff --git a/src/vendor/github.com/rs/cors/utils_test.go b/src/vendor/github.com/rs/cors/utils_test.go
deleted file mode 100644
index 83053b3..0000000
--- a/src/vendor/github.com/rs/cors/utils_test.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package cors
-
-import (
- "strings"
- "testing"
-)
-
-func TestWildcard(t *testing.T) {
- w := wildcard{"foo", "bar"}
- if !w.match("foobar") {
- t.Error("foo*bar should match foobar")
- }
- if !w.match("foobazbar") {
- t.Error("foo*bar should match foobazbar")
- }
- if w.match("foobaz") {
- t.Error("foo*bar should not match foobaz")
- }
-
- w = wildcard{"foo", "oof"}
- if w.match("foof") {
- t.Error("foo*oof should not match foof")
- }
-}
-
-func TestConvert(t *testing.T) {
- s := convert([]string{"A", "b", "C"}, strings.ToLower)
- e := []string{"a", "b", "c"}
- if s[0] != e[0] || s[1] != e[1] || s[2] != e[2] {
- t.Errorf("%v != %v", s, e)
- }
-}
-
-func TestParseHeaderList(t *testing.T) {
- h := parseHeaderList("header, second-header, THIRD-HEADER, Numb3r3d-H34d3r")
- e := []string{"Header", "Second-Header", "Third-Header", "Numb3r3d-H34d3r"}
- if h[0] != e[0] || h[1] != e[1] || h[2] != e[2] {
- t.Errorf("%v != %v", h, e)
- }
-}
-
-func TestParseHeaderListEmpty(t *testing.T) {
- if len(parseHeaderList("")) != 0 {
- t.Error("should be empty sclice")
- }
- if len(parseHeaderList(" , ")) != 0 {
- t.Error("should be empty sclice")
- }
-}
-
-func BenchmarkParseHeaderList(b *testing.B) {
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- parseHeaderList("header, second-header, THIRD-HEADER")
- }
-}
-
-func BenchmarkParseHeaderListSingle(b *testing.B) {
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- parseHeaderList("header")
- }
-}
-
-func BenchmarkParseHeaderListNormalized(b *testing.B) {
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- parseHeaderList("Header1, Header2, Third-Header")
- }
-}
diff --git a/src/vendor/github.com/rs/xhandler/.travis.yml b/src/vendor/github.com/rs/xhandler/.travis.yml
deleted file mode 100644
index b65c7a9..0000000
--- a/src/vendor/github.com/rs/xhandler/.travis.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-language: go
-go:
-- 1.5
-- tip
-matrix:
- allow_failures:
- - go: tip
diff --git a/src/vendor/github.com/rs/xhandler/README.md b/src/vendor/github.com/rs/xhandler/README.md
deleted file mode 100644
index 91c594b..0000000
--- a/src/vendor/github.com/rs/xhandler/README.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# XHandler
-
-[![godoc](http://img.shields.io/badge/godoc-reference-blue.svg?style=flat)](https://godoc.org/github.com/rs/xhandler) [![license](http://img.shields.io/badge/license-MIT-red.svg?style=flat)](https://raw.githubusercontent.com/rs/xhandler/master/LICENSE) [![Build Status](https://travis-ci.org/rs/xhandler.svg?branch=master)](https://travis-ci.org/rs/xhandler) [![Coverage](http://gocover.io/_badge/github.com/rs/xhandler)](http://gocover.io/github.com/rs/xhandler)
-
-XHandler is a bridge between [net/context](https://godoc.org/golang.org/x/net/context) and `http.Handler`.
-
-It lets you enforce `net/context` in your handlers without sacrificing compatibility with existing `http.Handlers` nor imposing a specific router.
-
-Thanks to `net/context` deadline management, `xhandler` is able to enforce a per request deadline and will cancel the context when the client closes the connection unexpectedly.
-
-You may create your own `net/context` aware handler pretty much the same way as you would do with http.Handler.
-
-Read more about xhandler on [Dailymotion engineering blog](http://engineering.dailymotion.com/our-way-to-go/).
-
-## Installing
-
- go get -u github.com/rs/xhandler
-
-## Usage
-
-```go
-package main
-
-import (
- "log"
- "net/http"
- "time"
-
- "github.com/rs/cors"
- "github.com/rs/xhandler"
- "golang.org/x/net/context"
-)
-
-type myMiddleware struct {
- next xhandler.HandlerC
-}
-
-func (h myMiddleware) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- ctx = context.WithValue(ctx, "test", "World")
- h.next.ServeHTTPC(ctx, w, r)
-}
-
-func main() {
- c := xhandler.Chain{}
-
- // Add close notifier handler so context is cancelled when the client closes
- // the connection
- c.UseC(xhandler.CloseHandler)
-
- // Add timeout handler
- c.UseC(xhandler.TimeoutHandler(2 * time.Second))
-
- // Middleware putting something in the context
- c.UseC(func(next xhandler.HandlerC) xhandler.HandlerC {
- return myMiddleware{next: next}
- })
-
- // Mix it with a non-context-aware middleware handler
- c.Use(cors.Default().Handler)
-
- // Final handler (using handlerFuncC), reading from the context
- xh := xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- value := ctx.Value("test").(string)
- w.Write([]byte("Hello " + value))
- })
-
- // Bridge context aware handlers with http.Handler using xhandler.Handle()
- http.Handle("/test", c.Handler(xh))
-
- if err := http.ListenAndServe(":8080", nil); err != nil {
- log.Fatal(err)
- }
-}
-```
-
-### Using xmux
-
-Xhandler comes with an optional context aware [muxer](https://github.com/rs/xmux) forked from [httprouter](https://github.com/julienschmidt/httprouter):
-
-```go
-package main
-
-import (
- "fmt"
- "log"
- "net/http"
- "time"
-
- "github.com/rs/xhandler"
- "github.com/rs/xmux"
- "golang.org/x/net/context"
-)
-
-func main() {
- c := xhandler.Chain{}
-
- // Append a context-aware middleware handler
- c.UseC(xhandler.CloseHandler)
-
- // Another context-aware middleware handler
- c.UseC(xhandler.TimeoutHandler(2 * time.Second))
-
- mux := xmux.New()
-
- // Use c.Handler to terminate the chain with your final handler
- mux.GET("/welcome/:name", xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "Welcome %s!", xmux.Params(ctx).Get("name"))
- }))
-
- if err := http.ListenAndServe(":8080", c.Handler(mux)); err != nil {
- log.Fatal(err)
- }
-}
-```
-
-See [xmux](https://github.com/rs/xmux) for more examples.
-
-## Context Aware Middleware
-
-Here is a list of `net/context` aware middleware handlers implementing `xhandler.HandlerC` interface.
-
-Feel free to put up a PR linking your middleware if you have built one:
-
-| Middleware | Author | Description |
-| ---------- | ------ | ----------- |
-| [xmux](https://github.com/rs/xmux) | [Olivier Poitrey](https://github.com/rs) | HTTP request muxer |
-| [xlog](https://github.com/rs/xlog) | [Olivier Poitrey](https://github.com/rs) | HTTP handler logger |
-| [xstats](https://github.com/rs/xstats) | [Olivier Poitrey](https://github.com/rs) | A generic client for service instrumentation |
-| [xaccess](https://github.com/rs/xaccess) | [Olivier Poitrey](https://github.com/rs) | HTTP handler access logger with [xlog](https://github.com/rs/xlog) and [xstats](https://github.com/rs/xstats) |
-| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support |
-
-## Licenses
-
-All source code is licensed under the [MIT License](https://raw.github.com/rs/xhandler/master/LICENSE).
diff --git a/src/vendor/github.com/rs/xhandler/chain_example_test.go b/src/vendor/github.com/rs/xhandler/chain_example_test.go
deleted file mode 100644
index 005b5b2..0000000
--- a/src/vendor/github.com/rs/xhandler/chain_example_test.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package xhandler_test
-
-import (
- "fmt"
- "net/http"
- "strings"
- "time"
-
- "github.com/rs/cors"
- "github.com/rs/xhandler"
- "golang.org/x/net/context"
-)
-
-func ExampleChain() {
- c := xhandler.Chain{}
- // Append a context-aware middleware handler
- c.UseC(xhandler.CloseHandler)
-
- // Mix it with a non-context-aware middleware handler
- c.Use(cors.Default().Handler)
-
- // Another context-aware middleware handler
- c.UseC(xhandler.TimeoutHandler(2 * time.Second))
-
- mux := http.NewServeMux()
-
- // Use c.Handler to terminate the chain with your final handler
- mux.Handle("/", c.Handler(xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "Welcome to the home page!")
- })))
-
- // You can reuse the same chain for other handlers
- mux.Handle("/api", c.Handler(xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "Welcome to the API!")
- })))
-}
-
-func ExampleIf() {
- c := xhandler.Chain{}
-
- // Add timeout handler only if the path match a prefix
- c.UseC(xhandler.If(
- func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool {
- return strings.HasPrefix(r.URL.Path, "/with-timeout/")
- },
- xhandler.TimeoutHandler(2*time.Second),
- ))
-
- http.Handle("/", c.Handler(xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "Welcome to the home page!")
- })))
-}
diff --git a/src/vendor/github.com/rs/xhandler/chain_test.go b/src/vendor/github.com/rs/xhandler/chain_test.go
deleted file mode 100644
index 0ce9410..0000000
--- a/src/vendor/github.com/rs/xhandler/chain_test.go
+++ /dev/null
@@ -1,112 +0,0 @@
-package xhandler
-
-import (
- "net/http"
- "net/http/httptest"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "golang.org/x/net/context"
-)
-
-func TestAppendHandlerC(t *testing.T) {
- init := 0
- h1 := func(next HandlerC) HandlerC {
- init++
- return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- ctx = context.WithValue(ctx, "test", 1)
- next.ServeHTTPC(ctx, w, r)
- })
- }
- h2 := func(next HandlerC) HandlerC {
- return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- ctx = context.WithValue(ctx, "test", 2)
- next.ServeHTTPC(ctx, w, r)
- })
- }
- c := Chain{}
- c.UseC(h1)
- c.UseC(h2)
- assert.Len(t, c, 2)
-
- h := c.Handler(HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- // Test ordering
- assert.Equal(t, 2, ctx.Value("test"), "second handler should overwrite first handler's context value")
- }))
-
- h.ServeHTTP(nil, nil)
- h.ServeHTTP(nil, nil)
- assert.Equal(t, 1, init, "handler init called once")
-}
-
-func TestAppendHandler(t *testing.T) {
- init := 0
- h1 := func(next HandlerC) HandlerC {
- return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- ctx = context.WithValue(ctx, "test", 1)
- next.ServeHTTPC(ctx, w, r)
- })
- }
- h2 := func(next http.Handler) http.Handler {
- init++
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- // Change r and w values
- w = httptest.NewRecorder()
- r = &http.Request{}
- next.ServeHTTP(w, r)
- })
- }
- c := Chain{}
- c.UseC(h1)
- c.Use(h2)
- assert.Len(t, c, 2)
-
- h := c.Handler(HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- // Test ordering
- assert.Equal(t, 1, ctx.Value("test"),
- "the first handler value should be pass through the second (non-aware) one")
- // Test r and w overwrite
- assert.NotNil(t, w)
- assert.NotNil(t, r)
- }))
-
- h.ServeHTTP(nil, nil)
- h.ServeHTTP(nil, nil)
- // There's no safe way to not initialize non ctx aware handlers on each request :/
- //assert.Equal(t, 1, init, "handler init called once")
-}
-
-func TestChainHandlerC(t *testing.T) {
- handlerCalls := 0
- h1 := func(next HandlerC) HandlerC {
- return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- handlerCalls++
- ctx = context.WithValue(ctx, "test", 1)
- next.ServeHTTPC(ctx, w, r)
- })
- }
- h2 := func(next HandlerC) HandlerC {
- return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- handlerCalls++
- ctx = context.WithValue(ctx, "test", 2)
- next.ServeHTTPC(ctx, w, r)
- })
- }
-
- c := Chain{}
- c.UseC(h1)
- c.UseC(h2)
- h := c.HandlerC(HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- handlerCalls++
-
- assert.Equal(t, 2, ctx.Value("test"),
- "second handler should overwrite first handler's context value")
- assert.Equal(t, 1, ctx.Value("mainCtx"),
- "the mainCtx value should be pass through")
- }))
-
- mainCtx := context.WithValue(context.Background(), "mainCtx", 1)
- h.ServeHTTPC(mainCtx, nil, nil)
-
- assert.Equal(t, 3, handlerCalls, "all handler called once")
-}
diff --git a/src/vendor/github.com/rs/xhandler/middleware_test.go b/src/vendor/github.com/rs/xhandler/middleware_test.go
deleted file mode 100644
index 51306e3..0000000
--- a/src/vendor/github.com/rs/xhandler/middleware_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package xhandler
-
-import (
- "log"
- "net/http"
- "net/http/httptest"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "golang.org/x/net/context"
-)
-
-func TestTimeoutHandler(t *testing.T) {
- ctx := context.WithValue(context.Background(), contextKey, "value")
- xh := TimeoutHandler(time.Second)(&handler{})
- h := New(ctx, xh)
- w := httptest.NewRecorder()
- r, err := http.NewRequest("GET", "http://example.com/foo", nil)
- if err != nil {
- log.Fatal(err)
- }
- h.ServeHTTP(w, r)
- assert.Equal(t, "value with deadline", w.Body.String())
-}
-
-type closeNotifyWriter struct {
- *httptest.ResponseRecorder
- closed bool
-}
-
-func (w *closeNotifyWriter) CloseNotify() <-chan bool {
- notify := make(chan bool, 1)
- if w.closed {
- // return an already "closed" notifier
- notify <- true
- }
- return notify
-}
-
-func TestCloseHandlerClientClose(t *testing.T) {
- ctx := context.WithValue(context.Background(), contextKey, "value")
- xh := CloseHandler(&handler{})
- h := New(ctx, xh)
- w := &closeNotifyWriter{ResponseRecorder: httptest.NewRecorder(), closed: true}
- r, err := http.NewRequest("GET", "http://example.com/foo", nil)
- if err != nil {
- log.Fatal(err)
- }
- h.ServeHTTP(w, r)
- assert.Equal(t, "value canceled", w.Body.String())
-}
-
-func TestCloseHandlerRequestEnds(t *testing.T) {
- ctx := context.WithValue(context.Background(), contextKey, "value")
- xh := CloseHandler(&handler{})
- h := New(ctx, xh)
- w := &closeNotifyWriter{ResponseRecorder: httptest.NewRecorder(), closed: false}
- r, err := http.NewRequest("GET", "http://example.com/foo", nil)
- if err != nil {
- log.Fatal(err)
- }
- h.ServeHTTP(w, r)
- assert.Equal(t, "value", w.Body.String())
-}
-
-func TestIf(t *testing.T) {
- trueHandler := HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- assert.Equal(t, "/true", r.URL.Path)
- })
- falseHandler := HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- assert.NotEqual(t, "/true", r.URL.Path)
- })
- ctx := context.WithValue(context.Background(), contextKey, "value")
- xh := If(
- func(ctx context.Context, w http.ResponseWriter, r *http.Request) bool {
- return r.URL.Path == "/true"
- },
- func(next HandlerC) HandlerC {
- return trueHandler
- },
- )(falseHandler)
- h := New(ctx, xh)
- r, _ := http.NewRequest("GET", "http://example.com/true", nil)
- h.ServeHTTP(nil, r)
- r, _ = http.NewRequest("GET", "http://example.com/false", nil)
- h.ServeHTTP(nil, r)
-}
diff --git a/src/vendor/github.com/rs/xhandler/xhandler_example_test.go b/src/vendor/github.com/rs/xhandler/xhandler_example_test.go
deleted file mode 100644
index 9f6f8a5..0000000
--- a/src/vendor/github.com/rs/xhandler/xhandler_example_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-package xhandler_test
-
-import (
- "log"
- "net/http"
- "time"
-
- "github.com/rs/xhandler"
- "golang.org/x/net/context"
-)
-
-type key int
-
-const contextKey key = 0
-
-func newContext(ctx context.Context, value string) context.Context {
- return context.WithValue(ctx, contextKey, value)
-}
-
-func fromContext(ctx context.Context) (string, bool) {
- value, ok := ctx.Value(contextKey).(string)
- return value, ok
-}
-
-func ExampleHandle() {
- var xh xhandler.HandlerC
- xh = xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- value, _ := fromContext(ctx)
- w.Write([]byte("Hello " + value))
- })
-
- xh = (func(next xhandler.HandlerC) xhandler.HandlerC {
- return xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- ctx = newContext(ctx, "World")
- next.ServeHTTPC(ctx, w, r)
- })
- })(xh)
-
- ctx := context.Background()
- // Bridge context aware handlers with http.Handler using xhandler.Handle()
- http.Handle("/", xhandler.New(ctx, xh))
-
- if err := http.ListenAndServe(":8080", nil); err != nil {
- log.Fatal(err)
- }
-}
-
-func ExampleHandleTimeout() {
- var xh xhandler.HandlerC
- xh = xhandler.HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- w.Write([]byte("Hello World"))
- if _, ok := ctx.Deadline(); ok {
- w.Write([]byte(" with deadline"))
- }
- })
-
- // This handler adds a timeout to the handler
- xh = xhandler.TimeoutHandler(5 * time.Second)(xh)
-
- ctx := context.Background()
- // Bridge context aware handlers with http.Handler using xhandler.Handle()
- http.Handle("/", xhandler.New(ctx, xh))
-
- if err := http.ListenAndServe(":8080", nil); err != nil {
- log.Fatal(err)
- }
-}
diff --git a/src/vendor/github.com/rs/xhandler/xhandler_test.go b/src/vendor/github.com/rs/xhandler/xhandler_test.go
deleted file mode 100644
index 3f5021f..0000000
--- a/src/vendor/github.com/rs/xhandler/xhandler_test.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package xhandler
-
-import (
- "log"
- "net/http"
- "net/http/httptest"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
- "golang.org/x/net/context"
-)
-
-type handler struct{}
-
-type key int
-
-const contextKey key = 0
-
-func newContext(ctx context.Context, value string) context.Context {
- return context.WithValue(ctx, contextKey, value)
-}
-
-func fromContext(ctx context.Context) (string, bool) {
- value, ok := ctx.Value(contextKey).(string)
- return value, ok
-}
-
-func (h handler) ServeHTTPC(ctx context.Context, w http.ResponseWriter, r *http.Request) {
- // Leave other go routines a chance to run
- time.Sleep(time.Nanosecond)
- value, _ := fromContext(ctx)
- if _, ok := ctx.Deadline(); ok {
- value += " with deadline"
- }
- if ctx.Err() == context.Canceled {
- value += " canceled"
- }
- w.Write([]byte(value))
-}
-
-func TestHandle(t *testing.T) {
- ctx := context.WithValue(context.Background(), contextKey, "value")
- h := New(ctx, &handler{})
- w := httptest.NewRecorder()
- r, err := http.NewRequest("GET", "http://example.com/foo", nil)
- if err != nil {
- log.Fatal(err)
- }
- h.ServeHTTP(w, r)
- assert.Equal(t, "value", w.Body.String())
-}
-
-func TestHandlerFunc(t *testing.T) {
- ok := false
- xh := HandlerFuncC(func(context.Context, http.ResponseWriter, *http.Request) {
- ok = true
- })
- xh.ServeHTTPC(nil, nil, nil)
- assert.True(t, ok)
-}
diff --git a/src/vendor/github.com/rs/xhandler/xmux/README.md b/src/vendor/github.com/rs/xhandler/xmux/README.md
deleted file mode 100644
index 6ea3c0f..0000000
--- a/src/vendor/github.com/rs/xhandler/xmux/README.md
+++ /dev/null
@@ -1 +0,0 @@
-Xmux did move to it's [own repository](https://github.com/rs/xmux/blob/master/README.md)
diff --git a/src/vendor/github.com/stretchr/graceful/.gitignore b/src/vendor/github.com/stretchr/graceful/.gitignore
deleted file mode 100644
index 8365624..0000000
--- a/src/vendor/github.com/stretchr/graceful/.gitignore
+++ /dev/null
@@ -1,23 +0,0 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-*.test
diff --git a/src/vendor/github.com/stretchr/graceful/README.md b/src/vendor/github.com/stretchr/graceful/README.md
deleted file mode 100644
index 531249a..0000000
--- a/src/vendor/github.com/stretchr/graceful/README.md
+++ /dev/null
@@ -1,137 +0,0 @@
-graceful [![GoDoc](https://godoc.org/github.com/tylerb/graceful?status.png)](http://godoc.org/github.com/tylerb/graceful) [![Build Status](https://drone.io/github.com/tylerb/graceful/status.png)](https://drone.io/github.com/tylerb/graceful/latest) [![Coverage Status](https://coveralls.io/repos/tylerb/graceful/badge.svg?branch=dronedebug)](https://coveralls.io/r/tylerb/graceful?branch=dronedebug) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tylerb/graceful?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
-========
-
-Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers.
-
-## Installation
-
-To install, simply execute:
-
-```
-go get gopkg.in/tylerb/graceful.v1
-```
-
-I am using [gopkg.in](http://labix.org/gopkg.in) to control releases.
-
-## Usage
-
-Using Graceful is easy. Simply create your http.Handler and pass it to the `Run` function:
-
-```go
-package main
-
-import (
- "gopkg.in/tylerb/graceful.v1"
- "net/http"
- "fmt"
- "time"
-)
-
-func main() {
- mux := http.NewServeMux()
- mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "Welcome to the home page!")
- })
-
- graceful.Run(":3001",10*time.Second,mux)
-}
-```
-
-Another example, using [Negroni](https://github.com/codegangsta/negroni), functions in much the same manner:
-
-```go
-package main
-
-import (
- "github.com/codegangsta/negroni"
- "gopkg.in/tylerb/graceful.v1"
- "net/http"
- "fmt"
- "time"
-)
-
-func main() {
- mux := http.NewServeMux()
- mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "Welcome to the home page!")
- })
-
- n := negroni.Classic()
- n.UseHandler(mux)
- //n.Run(":3000")
- graceful.Run(":3001",10*time.Second,n)
-}
-```
-
-In addition to Run there are the http.Server counterparts ListenAndServe, ListenAndServeTLS and Serve, which allow you to configure HTTPS, custom timeouts and error handling.
-Graceful may also be used by instantiating its Server type directly, which embeds an http.Server:
-
-```go
-mux := // ...
-
-srv := &graceful.Server{
- Timeout: 10 * time.Second,
-
- Server: &http.Server{
- Addr: ":1234",
- Handler: mux,
- },
-}
-
-srv.ListenAndServe()
-```
-
-This form allows you to set the ConnState callback, which works in the same way as in http.Server:
-
-```go
-mux := // ...
-
-srv := &graceful.Server{
- Timeout: 10 * time.Second,
-
- ConnState: func(conn net.Conn, state http.ConnState) {
- // conn has a new state
- },
-
- Server: &http.Server{
- Addr: ":1234",
- Handler: mux,
- },
-}
-
-srv.ListenAndServe()
-```
-
-## Behaviour
-
-When Graceful is sent a SIGINT or SIGTERM (possibly from ^C or a kill command), it:
-
-1. Disables keepalive connections.
-2. Closes the listening socket, allowing another process to listen on that port immediately.
-3. Starts a timer of `timeout` duration to give active requests a chance to finish.
-4. When timeout expires, closes all active connections.
-5. Closes the `stopChan`, waking up any blocking goroutines.
-6. Returns from the function, allowing the server to terminate.
-
-## Notes
-
-If the `timeout` argument to `Run` is 0, the server never times out, allowing all active requests to complete.
-
-If you wish to stop the server in some way other than an OS signal, you may call the `Stop()` function.
-This function stops the server, gracefully, using the new timeout value you provide. The `StopChan()` function
-returns a channel on which you can block while waiting for the server to stop. This channel will be closed when
-the server is stopped, allowing your execution to proceed. Multiple goroutines can block on this channel at the
-same time and all will be signalled when stopping is complete.
-
-## Contributing
-
-If you would like to contribute, please:
-
-1. Create a GitHub issue regarding the contribution. Features and bugs should be discussed beforehand.
-2. Fork the repository.
-3. Create a pull request with your solution. This pull request should reference and close the issues (Fix #2).
-
-All pull requests should:
-
-1. Pass [gometalinter -t .](https://github.com/alecthomas/gometalinter) with no warnings.
-2. Be `go fmt` formatted.
diff --git a/src/vendor/github.com/stretchr/graceful/graceful_test.go b/src/vendor/github.com/stretchr/graceful/graceful_test.go
deleted file mode 100644
index 83acac3..0000000
--- a/src/vendor/github.com/stretchr/graceful/graceful_test.go
+++ /dev/null
@@ -1,439 +0,0 @@
-package graceful
-
-import (
- "fmt"
- "io"
- "net"
- "net/http"
- "net/url"
- "os"
- "reflect"
- "strings"
- "sync"
- "syscall"
- "testing"
- "time"
-)
-
-var (
- killTime = 500 * time.Millisecond
- timeoutTime = 1000 * time.Millisecond
- waitTime = 100 * time.Millisecond
-)
-
-func runQuery(t *testing.T, expected int, shouldErr bool, wg *sync.WaitGroup, once *sync.Once) {
- wg.Add(1)
- defer wg.Done()
- client := http.Client{}
- r, err := client.Get("http://localhost:9654")
- if shouldErr && err == nil {
- once.Do(func() {
- t.Fatal("Expected an error but none was encountered.")
- })
- } else if shouldErr && err != nil {
- if checkErr(t, err, once) {
- return
- }
- }
- if r != nil && r.StatusCode != expected {
- once.Do(func() {
- t.Fatalf("Incorrect status code on response. Expected %d. Got %d", expected, r.StatusCode)
- })
- } else if r == nil {
- once.Do(func() {
- t.Fatal("No response when a response was expected.")
- })
- }
-}
-
-func checkErr(t *testing.T, err error, once *sync.Once) bool {
- if err.(*url.Error).Err == io.EOF {
- return true
- }
- var errno syscall.Errno
- switch oe := err.(*url.Error).Err.(type) {
- case *net.OpError:
- switch e := oe.Err.(type) {
- case syscall.Errno:
- errno = e
- case *os.SyscallError:
- errno = e.Err.(syscall.Errno)
- }
- if errno == syscall.ECONNREFUSED {
- return true
- } else if err != nil {
- once.Do(func() {
- t.Fatal("Error on Get:", err)
- })
- }
- default:
- if strings.Contains(err.Error(), "transport closed before response was received") {
- return true
- }
- fmt.Printf("unknown err: %s, %#v\n", err, err)
- }
- return false
-}
-
-func createListener(sleep time.Duration) (*http.Server, net.Listener, error) {
- mux := http.NewServeMux()
- mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
- time.Sleep(sleep)
- rw.WriteHeader(http.StatusOK)
- })
-
- time.Sleep(1 * time.Second)
- server := &http.Server{Addr: ":9654", Handler: mux}
- l, err := net.Listen("tcp", ":9654")
- if err != nil {
- }
- return server, l, err
-}
-
-func runServer(timeout, sleep time.Duration, c chan os.Signal) error {
- server, l, err := createListener(sleep)
- if err != nil {
- return err
- }
-
- srv := &Server{Timeout: timeout, Server: server, interrupt: c}
- return srv.Serve(l)
-}
-
-func launchTestQueries(t *testing.T, wg *sync.WaitGroup, c chan os.Signal) {
- var once sync.Once
- for i := 0; i < 8; i++ {
- go runQuery(t, http.StatusOK, false, wg, &once)
- }
-
- time.Sleep(waitTime)
- c <- os.Interrupt
- time.Sleep(waitTime)
-
- for i := 0; i < 8; i++ {
- go runQuery(t, 0, true, wg, &once)
- }
-
- wg.Done()
-}
-
-func TestGracefulRun(t *testing.T) {
- c := make(chan os.Signal, 1)
-
- var wg sync.WaitGroup
- wg.Add(1)
-
- go func() {
- runServer(killTime, killTime/2, c)
- wg.Done()
- }()
- time.Sleep(1 * time.Second)
-
- wg.Add(1)
- go launchTestQueries(t, &wg, c)
- wg.Wait()
-}
-
-func TestGracefulRunTimesOut(t *testing.T) {
- c := make(chan os.Signal, 1)
-
- var wg sync.WaitGroup
- wg.Add(1)
-
- go func() {
- runServer(killTime, killTime*10, c)
- wg.Done()
- }()
- time.Sleep(2 * time.Second)
-
- var once sync.Once
- wg.Add(1)
- go func() {
- for i := 0; i < 8; i++ {
- go runQuery(t, 0, true, &wg, &once)
- }
- time.Sleep(waitTime)
- c <- os.Interrupt
- time.Sleep(waitTime)
- for i := 0; i < 8; i++ {
- go runQuery(t, 0, true, &wg, &once)
- }
- wg.Done()
- }()
-
- wg.Wait()
-
-}
-
-func TestGracefulRunDoesntTimeOut(t *testing.T) {
- c := make(chan os.Signal, 1)
-
- var wg sync.WaitGroup
- wg.Add(1)
-
- go func() {
- runServer(0, killTime*2, c)
- wg.Done()
- }()
- time.Sleep(1 * time.Second)
-
- wg.Add(1)
- go launchTestQueries(t, &wg, c)
- wg.Wait()
-}
-
-func TestGracefulRunNoRequests(t *testing.T) {
- c := make(chan os.Signal, 1)
-
- var wg sync.WaitGroup
- wg.Add(1)
-
- go func() {
- runServer(0, killTime*2, c)
- wg.Done()
- }()
- time.Sleep(1 * time.Second)
-
- c <- os.Interrupt
-
- wg.Wait()
-
-}
-
-func TestGracefulForwardsConnState(t *testing.T) {
- c := make(chan os.Signal, 1)
- states := make(map[http.ConnState]int)
- var stateLock sync.Mutex
-
- connState := func(conn net.Conn, state http.ConnState) {
- stateLock.Lock()
- states[state]++
- stateLock.Unlock()
- }
-
- var wg sync.WaitGroup
- wg.Add(1)
-
- expected := map[http.ConnState]int{
- http.StateNew: 8,
- http.StateActive: 8,
- http.StateClosed: 8,
- }
-
- go func() {
- server, l, _ := createListener(killTime / 2)
- srv := &Server{
- ConnState: connState,
- Timeout: killTime,
- Server: server,
- interrupt: c,
- }
- srv.Serve(l)
-
- wg.Done()
- }()
- time.Sleep(2 * time.Second)
-
- wg.Add(1)
- go launchTestQueries(t, &wg, c)
- wg.Wait()
-
- stateLock.Lock()
- if !reflect.DeepEqual(states, expected) {
- t.Errorf("Incorrect connection state tracking.\n actual: %v\nexpected: %v\n", states, expected)
- }
- stateLock.Unlock()
-}
-
-func TestGracefulExplicitStop(t *testing.T) {
- server, l, err := createListener(1 * time.Millisecond)
- if err != nil {
- t.Fatal(err)
- }
-
- srv := &Server{Timeout: killTime, Server: server}
-
- go func() {
- go srv.Serve(l)
- time.Sleep(waitTime)
- srv.Stop(killTime)
- }()
-
- // block on the stopChan until the server has shut down
- select {
- case <-srv.StopChan():
- case <-time.After(timeoutTime):
- t.Fatal("Timed out while waiting for explicit stop to complete")
- }
-}
-
-func TestGracefulExplicitStopOverride(t *testing.T) {
- server, l, err := createListener(1 * time.Millisecond)
- if err != nil {
- t.Fatal(err)
- }
-
- srv := &Server{Timeout: killTime, Server: server}
-
- go func() {
- go srv.Serve(l)
- time.Sleep(waitTime)
- srv.Stop(killTime / 2)
- }()
-
- // block on the stopChan until the server has shut down
- select {
- case <-srv.StopChan():
- case <-time.After(killTime):
- t.Fatal("Timed out while waiting for explicit stop to complete")
- }
-}
-
-func TestBeforeShutdownAndShutdownInitiatedCallbacks(t *testing.T) {
- server, l, err := createListener(1 * time.Millisecond)
- if err != nil {
- t.Fatal(err)
- }
-
- beforeShutdownCalled := make(chan struct{})
- cb1 := func() { close(beforeShutdownCalled) }
- shutdownInitiatedCalled := make(chan struct{})
- cb2 := func() { close(shutdownInitiatedCalled) }
-
- srv := &Server{Server: server, BeforeShutdown: cb1, ShutdownInitiated: cb2}
-
- go func() {
- go srv.Serve(l)
- time.Sleep(waitTime)
- srv.Stop(killTime)
- }()
-
- beforeShutdown := false
- shutdownInitiated := false
- for i := 0; i < 2; i++ {
- select {
- case <-beforeShutdownCalled:
- beforeShutdownCalled = nil
- beforeShutdown = true
- case <-shutdownInitiatedCalled:
- shutdownInitiatedCalled = nil
- shutdownInitiated = true
- case <-time.After(killTime):
- t.Fatal("Timed out while waiting for ShutdownInitiated callback to be called")
- }
- }
-
- if !beforeShutdown {
- t.Fatal("beforeShutdown should be true")
- }
- if !shutdownInitiated {
- t.Fatal("shutdownInitiated should be true")
- }
-}
-func hijackingListener(srv *Server) (*http.Server, net.Listener, error) {
- mux := http.NewServeMux()
- mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
- conn, bufrw, err := rw.(http.Hijacker).Hijack()
- if err != nil {
- http.Error(rw, "webserver doesn't support hijacking", http.StatusInternalServerError)
- return
- }
-
- defer conn.Close()
-
- bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
- bufrw.Flush()
- })
-
- server := &http.Server{Addr: ":9654", Handler: mux}
- l, err := net.Listen("tcp", ":9654")
- return server, l, err
-}
-
-func TestNotifyClosed(t *testing.T) {
- c := make(chan os.Signal, 1)
-
- var wg sync.WaitGroup
- wg.Add(1)
-
- srv := &Server{Timeout: killTime, interrupt: c}
- server, l, err := hijackingListener(srv)
- if err != nil {
- t.Fatal(err)
- }
-
- srv.Server = server
-
- go func() {
- srv.Serve(l)
- wg.Done()
- }()
-
- var once sync.Once
- for i := 0; i < 8; i++ {
- runQuery(t, http.StatusOK, false, &wg, &once)
- }
-
- srv.Stop(0)
-
- // block on the stopChan until the server has shut down
- select {
- case <-srv.StopChan():
- case <-time.After(timeoutTime):
- t.Fatal("Timed out while waiting for explicit stop to complete")
- }
-
- if len(srv.connections) > 0 {
- t.Fatal("hijacked connections should not be managed")
- }
-
-}
-
-func TestStopDeadlock(t *testing.T) {
- c := make(chan struct{})
-
- server, l, err := createListener(1 * time.Millisecond)
- if err != nil {
- t.Fatal(err)
- }
-
- srv := &Server{Server: server, NoSignalHandling: true}
-
- go func() {
- time.Sleep(waitTime)
- srv.Serve(l)
- }()
-
- go func() {
- srv.Stop(0)
- close(c)
- }()
-
- select {
- case <-c:
- l.Close()
- case <-time.After(timeoutTime):
- t.Fatal("Timed out while waiting for explicit stop to complete")
- }
-}
-
-// Run with --race
-func TestStopRace(t *testing.T) {
- server, l, err := createListener(1 * time.Millisecond)
- if err != nil {
- t.Fatal(err)
- }
-
- srv := &Server{Timeout: killTime, Server: server}
-
- go func() {
- go srv.Serve(l)
- srv.Stop(killTime)
- }()
- srv.Stop(0)
- select {
- case <-srv.StopChan():
- case <-time.After(timeoutTime):
- t.Fatal("Timed out while waiting for explicit stop to complete")
- }
-}
diff --git a/src/vendor/golang.org/x/net/context/context_test.go b/src/vendor/golang.org/x/net/context/context_test.go
deleted file mode 100644
index 05345fc..0000000
--- a/src/vendor/golang.org/x/net/context/context_test.go
+++ /dev/null
@@ -1,575 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package context
-
-import (
- "fmt"
- "math/rand"
- "runtime"
- "strings"
- "sync"
- "testing"
- "time"
-)
-
-// otherContext is a Context that's not one of the types defined in context.go.
-// This lets us test code paths that differ based on the underlying type of the
-// Context.
-type otherContext struct {
- Context
-}
-
-func TestBackground(t *testing.T) {
- c := Background()
- if c == nil {
- t.Fatalf("Background returned nil")
- }
- select {
- case x := <-c.Done():
- t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
- default:
- }
- if got, want := fmt.Sprint(c), "context.Background"; got != want {
- t.Errorf("Background().String() = %q want %q", got, want)
- }
-}
-
-func TestTODO(t *testing.T) {
- c := TODO()
- if c == nil {
- t.Fatalf("TODO returned nil")
- }
- select {
- case x := <-c.Done():
- t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
- default:
- }
- if got, want := fmt.Sprint(c), "context.TODO"; got != want {
- t.Errorf("TODO().String() = %q want %q", got, want)
- }
-}
-
-func TestWithCancel(t *testing.T) {
- c1, cancel := WithCancel(Background())
-
- if got, want := fmt.Sprint(c1), "context.Background.WithCancel"; got != want {
- t.Errorf("c1.String() = %q want %q", got, want)
- }
-
- o := otherContext{c1}
- c2, _ := WithCancel(o)
- contexts := []Context{c1, o, c2}
-
- for i, c := range contexts {
- if d := c.Done(); d == nil {
- t.Errorf("c[%d].Done() == %v want non-nil", i, d)
- }
- if e := c.Err(); e != nil {
- t.Errorf("c[%d].Err() == %v want nil", i, e)
- }
-
- select {
- case x := <-c.Done():
- t.Errorf("<-c.Done() == %v want nothing (it should block)", x)
- default:
- }
- }
-
- cancel()
- time.Sleep(100 * time.Millisecond) // let cancelation propagate
-
- for i, c := range contexts {
- select {
- case <-c.Done():
- default:
- t.Errorf("<-c[%d].Done() blocked, but shouldn't have", i)
- }
- if e := c.Err(); e != Canceled {
- t.Errorf("c[%d].Err() == %v want %v", i, e, Canceled)
- }
- }
-}
-
-func TestParentFinishesChild(t *testing.T) {
- // Context tree:
- // parent -> cancelChild
- // parent -> valueChild -> timerChild
- parent, cancel := WithCancel(Background())
- cancelChild, stop := WithCancel(parent)
- defer stop()
- valueChild := WithValue(parent, "key", "value")
- timerChild, stop := WithTimeout(valueChild, 10000*time.Hour)
- defer stop()
-
- select {
- case x := <-parent.Done():
- t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
- case x := <-cancelChild.Done():
- t.Errorf("<-cancelChild.Done() == %v want nothing (it should block)", x)
- case x := <-timerChild.Done():
- t.Errorf("<-timerChild.Done() == %v want nothing (it should block)", x)
- case x := <-valueChild.Done():
- t.Errorf("<-valueChild.Done() == %v want nothing (it should block)", x)
- default:
- }
-
- // The parent's children should contain the two cancelable children.
- pc := parent.(*cancelCtx)
- cc := cancelChild.(*cancelCtx)
- tc := timerChild.(*timerCtx)
- pc.mu.Lock()
- if len(pc.children) != 2 || !pc.children[cc] || !pc.children[tc] {
- t.Errorf("bad linkage: pc.children = %v, want %v and %v",
- pc.children, cc, tc)
- }
- pc.mu.Unlock()
-
- if p, ok := parentCancelCtx(cc.Context); !ok || p != pc {
- t.Errorf("bad linkage: parentCancelCtx(cancelChild.Context) = %v, %v want %v, true", p, ok, pc)
- }
- if p, ok := parentCancelCtx(tc.Context); !ok || p != pc {
- t.Errorf("bad linkage: parentCancelCtx(timerChild.Context) = %v, %v want %v, true", p, ok, pc)
- }
-
- cancel()
-
- pc.mu.Lock()
- if len(pc.children) != 0 {
- t.Errorf("pc.cancel didn't clear pc.children = %v", pc.children)
- }
- pc.mu.Unlock()
-
- // parent and children should all be finished.
- check := func(ctx Context, name string) {
- select {
- case <-ctx.Done():
- default:
- t.Errorf("<-%s.Done() blocked, but shouldn't have", name)
- }
- if e := ctx.Err(); e != Canceled {
- t.Errorf("%s.Err() == %v want %v", name, e, Canceled)
- }
- }
- check(parent, "parent")
- check(cancelChild, "cancelChild")
- check(valueChild, "valueChild")
- check(timerChild, "timerChild")
-
- // WithCancel should return a canceled context on a canceled parent.
- precanceledChild := WithValue(parent, "key", "value")
- select {
- case <-precanceledChild.Done():
- default:
- t.Errorf("<-precanceledChild.Done() blocked, but shouldn't have")
- }
- if e := precanceledChild.Err(); e != Canceled {
- t.Errorf("precanceledChild.Err() == %v want %v", e, Canceled)
- }
-}
-
-func TestChildFinishesFirst(t *testing.T) {
- cancelable, stop := WithCancel(Background())
- defer stop()
- for _, parent := range []Context{Background(), cancelable} {
- child, cancel := WithCancel(parent)
-
- select {
- case x := <-parent.Done():
- t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
- case x := <-child.Done():
- t.Errorf("<-child.Done() == %v want nothing (it should block)", x)
- default:
- }
-
- cc := child.(*cancelCtx)
- pc, pcok := parent.(*cancelCtx) // pcok == false when parent == Background()
- if p, ok := parentCancelCtx(cc.Context); ok != pcok || (ok && pc != p) {
- t.Errorf("bad linkage: parentCancelCtx(cc.Context) = %v, %v want %v, %v", p, ok, pc, pcok)
- }
-
- if pcok {
- pc.mu.Lock()
- if len(pc.children) != 1 || !pc.children[cc] {
- t.Errorf("bad linkage: pc.children = %v, cc = %v", pc.children, cc)
- }
- pc.mu.Unlock()
- }
-
- cancel()
-
- if pcok {
- pc.mu.Lock()
- if len(pc.children) != 0 {
- t.Errorf("child's cancel didn't remove self from pc.children = %v", pc.children)
- }
- pc.mu.Unlock()
- }
-
- // child should be finished.
- select {
- case <-child.Done():
- default:
- t.Errorf("<-child.Done() blocked, but shouldn't have")
- }
- if e := child.Err(); e != Canceled {
- t.Errorf("child.Err() == %v want %v", e, Canceled)
- }
-
- // parent should not be finished.
- select {
- case x := <-parent.Done():
- t.Errorf("<-parent.Done() == %v want nothing (it should block)", x)
- default:
- }
- if e := parent.Err(); e != nil {
- t.Errorf("parent.Err() == %v want nil", e)
- }
- }
-}
-
-func testDeadline(c Context, wait time.Duration, t *testing.T) {
- select {
- case <-time.After(wait):
- t.Fatalf("context should have timed out")
- case <-c.Done():
- }
- if e := c.Err(); e != DeadlineExceeded {
- t.Errorf("c.Err() == %v want %v", e, DeadlineExceeded)
- }
-}
-
-func TestDeadline(t *testing.T) {
- c, _ := WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
- if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
- t.Errorf("c.String() = %q want prefix %q", got, prefix)
- }
- testDeadline(c, 200*time.Millisecond, t)
-
- c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
- o := otherContext{c}
- testDeadline(o, 200*time.Millisecond, t)
-
- c, _ = WithDeadline(Background(), time.Now().Add(100*time.Millisecond))
- o = otherContext{c}
- c, _ = WithDeadline(o, time.Now().Add(300*time.Millisecond))
- testDeadline(c, 200*time.Millisecond, t)
-}
-
-func TestTimeout(t *testing.T) {
- c, _ := WithTimeout(Background(), 100*time.Millisecond)
- if got, prefix := fmt.Sprint(c), "context.Background.WithDeadline("; !strings.HasPrefix(got, prefix) {
- t.Errorf("c.String() = %q want prefix %q", got, prefix)
- }
- testDeadline(c, 200*time.Millisecond, t)
-
- c, _ = WithTimeout(Background(), 100*time.Millisecond)
- o := otherContext{c}
- testDeadline(o, 200*time.Millisecond, t)
-
- c, _ = WithTimeout(Background(), 100*time.Millisecond)
- o = otherContext{c}
- c, _ = WithTimeout(o, 300*time.Millisecond)
- testDeadline(c, 200*time.Millisecond, t)
-}
-
-func TestCanceledTimeout(t *testing.T) {
- c, _ := WithTimeout(Background(), 200*time.Millisecond)
- o := otherContext{c}
- c, cancel := WithTimeout(o, 400*time.Millisecond)
- cancel()
- time.Sleep(100 * time.Millisecond) // let cancelation propagate
- select {
- case <-c.Done():
- default:
- t.Errorf("<-c.Done() blocked, but shouldn't have")
- }
- if e := c.Err(); e != Canceled {
- t.Errorf("c.Err() == %v want %v", e, Canceled)
- }
-}
-
-type key1 int
-type key2 int
-
-var k1 = key1(1)
-var k2 = key2(1) // same int as k1, different type
-var k3 = key2(3) // same type as k2, different int
-
-func TestValues(t *testing.T) {
- check := func(c Context, nm, v1, v2, v3 string) {
- if v, ok := c.Value(k1).(string); ok == (len(v1) == 0) || v != v1 {
- t.Errorf(`%s.Value(k1).(string) = %q, %t want %q, %t`, nm, v, ok, v1, len(v1) != 0)
- }
- if v, ok := c.Value(k2).(string); ok == (len(v2) == 0) || v != v2 {
- t.Errorf(`%s.Value(k2).(string) = %q, %t want %q, %t`, nm, v, ok, v2, len(v2) != 0)
- }
- if v, ok := c.Value(k3).(string); ok == (len(v3) == 0) || v != v3 {
- t.Errorf(`%s.Value(k3).(string) = %q, %t want %q, %t`, nm, v, ok, v3, len(v3) != 0)
- }
- }
-
- c0 := Background()
- check(c0, "c0", "", "", "")
-
- c1 := WithValue(Background(), k1, "c1k1")
- check(c1, "c1", "c1k1", "", "")
-
- if got, want := fmt.Sprint(c1), `context.Background.WithValue(1, "c1k1")`; got != want {
- t.Errorf("c.String() = %q want %q", got, want)
- }
-
- c2 := WithValue(c1, k2, "c2k2")
- check(c2, "c2", "c1k1", "c2k2", "")
-
- c3 := WithValue(c2, k3, "c3k3")
- check(c3, "c2", "c1k1", "c2k2", "c3k3")
-
- c4 := WithValue(c3, k1, nil)
- check(c4, "c4", "", "c2k2", "c3k3")
-
- o0 := otherContext{Background()}
- check(o0, "o0", "", "", "")
-
- o1 := otherContext{WithValue(Background(), k1, "c1k1")}
- check(o1, "o1", "c1k1", "", "")
-
- o2 := WithValue(o1, k2, "o2k2")
- check(o2, "o2", "c1k1", "o2k2", "")
-
- o3 := otherContext{c4}
- check(o3, "o3", "", "c2k2", "c3k3")
-
- o4 := WithValue(o3, k3, nil)
- check(o4, "o4", "", "c2k2", "")
-}
-
-func TestAllocs(t *testing.T) {
- bg := Background()
- for _, test := range []struct {
- desc string
- f func()
- limit float64
- gccgoLimit float64
- }{
- {
- desc: "Background()",
- f: func() { Background() },
- limit: 0,
- gccgoLimit: 0,
- },
- {
- desc: fmt.Sprintf("WithValue(bg, %v, nil)", k1),
- f: func() {
- c := WithValue(bg, k1, nil)
- c.Value(k1)
- },
- limit: 3,
- gccgoLimit: 3,
- },
- {
- desc: "WithTimeout(bg, 15*time.Millisecond)",
- f: func() {
- c, _ := WithTimeout(bg, 15*time.Millisecond)
- <-c.Done()
- },
- limit: 8,
- gccgoLimit: 15,
- },
- {
- desc: "WithCancel(bg)",
- f: func() {
- c, cancel := WithCancel(bg)
- cancel()
- <-c.Done()
- },
- limit: 5,
- gccgoLimit: 8,
- },
- {
- desc: "WithTimeout(bg, 100*time.Millisecond)",
- f: func() {
- c, cancel := WithTimeout(bg, 100*time.Millisecond)
- cancel()
- <-c.Done()
- },
- limit: 8,
- gccgoLimit: 25,
- },
- } {
- limit := test.limit
- if runtime.Compiler == "gccgo" {
- // gccgo does not yet do escape analysis.
- // TOOD(iant): Remove this when gccgo does do escape analysis.
- limit = test.gccgoLimit
- }
- if n := testing.AllocsPerRun(100, test.f); n > limit {
- t.Errorf("%s allocs = %f want %d", test.desc, n, int(limit))
- }
- }
-}
-
-func TestSimultaneousCancels(t *testing.T) {
- root, cancel := WithCancel(Background())
- m := map[Context]CancelFunc{root: cancel}
- q := []Context{root}
- // Create a tree of contexts.
- for len(q) != 0 && len(m) < 100 {
- parent := q[0]
- q = q[1:]
- for i := 0; i < 4; i++ {
- ctx, cancel := WithCancel(parent)
- m[ctx] = cancel
- q = append(q, ctx)
- }
- }
- // Start all the cancels in a random order.
- var wg sync.WaitGroup
- wg.Add(len(m))
- for _, cancel := range m {
- go func(cancel CancelFunc) {
- cancel()
- wg.Done()
- }(cancel)
- }
- // Wait on all the contexts in a random order.
- for ctx := range m {
- select {
- case <-ctx.Done():
- case <-time.After(1 * time.Second):
- buf := make([]byte, 10<<10)
- n := runtime.Stack(buf, true)
- t.Fatalf("timed out waiting for <-ctx.Done(); stacks:\n%s", buf[:n])
- }
- }
- // Wait for all the cancel functions to return.
- done := make(chan struct{})
- go func() {
- wg.Wait()
- close(done)
- }()
- select {
- case <-done:
- case <-time.After(1 * time.Second):
- buf := make([]byte, 10<<10)
- n := runtime.Stack(buf, true)
- t.Fatalf("timed out waiting for cancel functions; stacks:\n%s", buf[:n])
- }
-}
-
-func TestInterlockedCancels(t *testing.T) {
- parent, cancelParent := WithCancel(Background())
- child, cancelChild := WithCancel(parent)
- go func() {
- parent.Done()
- cancelChild()
- }()
- cancelParent()
- select {
- case <-child.Done():
- case <-time.After(1 * time.Second):
- buf := make([]byte, 10<<10)
- n := runtime.Stack(buf, true)
- t.Fatalf("timed out waiting for child.Done(); stacks:\n%s", buf[:n])
- }
-}
-
-func TestLayersCancel(t *testing.T) {
- testLayers(t, time.Now().UnixNano(), false)
-}
-
-func TestLayersTimeout(t *testing.T) {
- testLayers(t, time.Now().UnixNano(), true)
-}
-
-func testLayers(t *testing.T, seed int64, testTimeout bool) {
- rand.Seed(seed)
- errorf := func(format string, a ...interface{}) {
- t.Errorf(fmt.Sprintf("seed=%d: %s", seed, format), a...)
- }
- const (
- timeout = 200 * time.Millisecond
- minLayers = 30
- )
- type value int
- var (
- vals []*value
- cancels []CancelFunc
- numTimers int
- ctx = Background()
- )
- for i := 0; i < minLayers || numTimers == 0 || len(cancels) == 0 || len(vals) == 0; i++ {
- switch rand.Intn(3) {
- case 0:
- v := new(value)
- ctx = WithValue(ctx, v, v)
- vals = append(vals, v)
- case 1:
- var cancel CancelFunc
- ctx, cancel = WithCancel(ctx)
- cancels = append(cancels, cancel)
- case 2:
- var cancel CancelFunc
- ctx, cancel = WithTimeout(ctx, timeout)
- cancels = append(cancels, cancel)
- numTimers++
- }
- }
- checkValues := func(when string) {
- for _, key := range vals {
- if val := ctx.Value(key).(*value); key != val {
- errorf("%s: ctx.Value(%p) = %p want %p", when, key, val, key)
- }
- }
- }
- select {
- case <-ctx.Done():
- errorf("ctx should not be canceled yet")
- default:
- }
- if s, prefix := fmt.Sprint(ctx), "context.Background."; !strings.HasPrefix(s, prefix) {
- t.Errorf("ctx.String() = %q want prefix %q", s, prefix)
- }
- t.Log(ctx)
- checkValues("before cancel")
- if testTimeout {
- select {
- case <-ctx.Done():
- case <-time.After(timeout + 100*time.Millisecond):
- errorf("ctx should have timed out")
- }
- checkValues("after timeout")
- } else {
- cancel := cancels[rand.Intn(len(cancels))]
- cancel()
- select {
- case <-ctx.Done():
- default:
- errorf("ctx should be canceled")
- }
- checkValues("after cancel")
- }
-}
-
-func TestCancelRemoves(t *testing.T) {
- checkChildren := func(when string, ctx Context, want int) {
- if got := len(ctx.(*cancelCtx).children); got != want {
- t.Errorf("%s: context has %d children, want %d", when, got, want)
- }
- }
-
- ctx, _ := WithCancel(Background())
- checkChildren("after creation", ctx, 0)
- _, cancel := WithCancel(ctx)
- checkChildren("with WithCancel child ", ctx, 1)
- cancel()
- checkChildren("after cancelling WithCancel child", ctx, 0)
-
- ctx, _ = WithCancel(Background())
- checkChildren("after creation", ctx, 0)
- _, cancel = WithTimeout(ctx, 60*time.Minute)
- checkChildren("with WithTimeout child ", ctx, 1)
- cancel()
- checkChildren("after cancelling WithTimeout child", ctx, 0)
-}
diff --git a/src/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go b/src/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go
deleted file mode 100644
index e3170e3..0000000
--- a/src/vendor/golang.org/x/net/context/ctxhttp/cancelreq.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.5
-
-package ctxhttp
-
-import "net/http"
-
-func canceler(client *http.Client, req *http.Request) func() {
- // TODO(djd): Respect any existing value of req.Cancel.
- ch := make(chan struct{})
- req.Cancel = ch
-
- return func() {
- close(ch)
- }
-}
diff --git a/src/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go b/src/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
deleted file mode 100644
index 56bcbad..0000000
--- a/src/vendor/golang.org/x/net/context/ctxhttp/cancelreq_go14.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.5
-
-package ctxhttp
-
-import "net/http"
-
-type requestCanceler interface {
- CancelRequest(*http.Request)
-}
-
-func canceler(client *http.Client, req *http.Request) func() {
- rc, ok := client.Transport.(requestCanceler)
- if !ok {
- return func() {}
- }
- return func() {
- rc.CancelRequest(req)
- }
-}
diff --git a/src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go b/src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go
deleted file mode 100644
index 77c25ba..0000000
--- a/src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_test.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !plan9
-
-package ctxhttp
-
-import (
- "io/ioutil"
- "net"
- "net/http"
- "net/http/httptest"
- "sync"
- "testing"
- "time"
-
- "golang.org/x/net/context"
-)
-
-const (
- requestDuration = 100 * time.Millisecond
- requestBody = "ok"
-)
-
-func TestNoTimeout(t *testing.T) {
- ctx := context.Background()
- resp, err := doRequest(ctx)
-
- if resp == nil || err != nil {
- t.Fatalf("error received from client: %v %v", err, resp)
- }
-}
-
-func TestCancel(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- go func() {
- time.Sleep(requestDuration / 2)
- cancel()
- }()
-
- resp, err := doRequest(ctx)
-
- if resp != nil || err == nil {
- t.Fatalf("expected error, didn't get one. resp: %v", resp)
- }
- if err != ctx.Err() {
- t.Fatalf("expected error from context but got: %v", err)
- }
-}
-
-func TestCancelAfterRequest(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
-
- resp, err := doRequest(ctx)
-
- // Cancel before reading the body.
- // Request.Body should still be readable after the context is canceled.
- cancel()
-
- b, err := ioutil.ReadAll(resp.Body)
- if err != nil || string(b) != requestBody {
- t.Fatalf("could not read body: %q %v", b, err)
- }
-}
-
-func TestCancelAfterHangingRequest(t *testing.T) {
- handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusOK)
- w.(http.Flusher).Flush()
- <-w.(http.CloseNotifier).CloseNotify()
- })
-
- serv := httptest.NewServer(handler)
- defer serv.Close()
-
- ctx, cancel := context.WithCancel(context.Background())
- resp, err := Get(ctx, nil, serv.URL)
- if err != nil {
- t.Fatalf("unexpected error in Get: %v", err)
- }
-
- // Cancel befer reading the body.
- // Reading Request.Body should fail, since the request was
- // canceled before anything was written.
- cancel()
-
- done := make(chan struct{})
-
- go func() {
- b, err := ioutil.ReadAll(resp.Body)
- if len(b) != 0 || err == nil {
- t.Errorf(`Read got (%q, %v); want ("", error)`, b, err)
- }
- close(done)
- }()
-
- select {
- case <-time.After(1 * time.Second):
- t.Errorf("Test timed out")
- case <-done:
- }
-}
-
-func doRequest(ctx context.Context) (*http.Response, error) {
- var okHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- time.Sleep(requestDuration)
- w.Write([]byte(requestBody))
- })
-
- serv := httptest.NewServer(okHandler)
- defer serv.Close()
-
- return Get(ctx, nil, serv.URL)
-}
-
-// golang.org/issue/14065
-func TestClosesResponseBodyOnCancel(t *testing.T) {
- defer func() { testHookContextDoneBeforeHeaders = nop }()
- defer func() { testHookDoReturned = nop }()
- defer func() { testHookDidBodyClose = nop }()
-
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
- defer ts.Close()
-
- ctx, cancel := context.WithCancel(context.Background())
-
- // closed when Do enters select case <-ctx.Done()
- enteredDonePath := make(chan struct{})
-
- testHookContextDoneBeforeHeaders = func() {
- close(enteredDonePath)
- }
-
- testHookDoReturned = func() {
- // We now have the result (the Flush'd headers) at least,
- // so we can cancel the request.
- cancel()
-
- // But block the client.Do goroutine from sending
- // until Do enters into the <-ctx.Done() path, since
- // otherwise if both channels are readable, select
- // picks a random one.
- <-enteredDonePath
- }
-
- sawBodyClose := make(chan struct{})
- testHookDidBodyClose = func() { close(sawBodyClose) }
-
- tr := &http.Transport{}
- defer tr.CloseIdleConnections()
- c := &http.Client{Transport: tr}
- req, _ := http.NewRequest("GET", ts.URL, nil)
- _, doErr := Do(ctx, c, req)
-
- select {
- case <-sawBodyClose:
- case <-time.After(5 * time.Second):
- t.Fatal("timeout waiting for body to close")
- }
-
- if doErr != ctx.Err() {
- t.Errorf("Do error = %v; want %v", doErr, ctx.Err())
- }
-}
-
-type noteCloseConn struct {
- net.Conn
- onceClose sync.Once
- closefn func()
-}
-
-func (c *noteCloseConn) Close() error {
- c.onceClose.Do(c.closefn)
- return c.Conn.Close()
-}
diff --git a/src/vendor/golang.org/x/net/context/withtimeout_test.go b/src/vendor/golang.org/x/net/context/withtimeout_test.go
deleted file mode 100644
index a6754dc..0000000
--- a/src/vendor/golang.org/x/net/context/withtimeout_test.go
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2014 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package context_test
-
-import (
- "fmt"
- "time"
-
- "golang.org/x/net/context"
-)
-
-func ExampleWithTimeout() {
- // Pass a context with a timeout to tell a blocking function that it
- // should abandon its work after the timeout elapses.
- ctx, _ := context.WithTimeout(context.Background(), 100*time.Millisecond)
- select {
- case <-time.After(200 * time.Millisecond):
- fmt.Println("overslept")
- case <-ctx.Done():
- fmt.Println(ctx.Err()) // prints "context deadline exceeded"
- }
- // Output:
- // context deadline exceeded
-}
diff --git a/src/vendor/golang.org/x/net/netutil/listen.go b/src/vendor/golang.org/x/net/netutil/listen.go
deleted file mode 100644
index b317ba2..0000000
--- a/src/vendor/golang.org/x/net/netutil/listen.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package netutil provides network utility functions, complementing the more
-// common ones in the net package.
-package netutil // import "golang.org/x/net/netutil"
-
-import (
- "net"
- "sync"
-)
-
-// LimitListener returns a Listener that accepts at most n simultaneous
-// connections from the provided Listener.
-func LimitListener(l net.Listener, n int) net.Listener {
- return &limitListener{l, make(chan struct{}, n)}
-}
-
-type limitListener struct {
- net.Listener
- sem chan struct{}
-}
-
-func (l *limitListener) acquire() { l.sem <- struct{}{} }
-func (l *limitListener) release() { <-l.sem }
-
-func (l *limitListener) Accept() (net.Conn, error) {
- l.acquire()
- c, err := l.Listener.Accept()
- if err != nil {
- l.release()
- return nil, err
- }
- return &limitListenerConn{Conn: c, release: l.release}, nil
-}
-
-type limitListenerConn struct {
- net.Conn
- releaseOnce sync.Once
- release func()
-}
-
-func (l *limitListenerConn) Close() error {
- err := l.Conn.Close()
- l.releaseOnce.Do(l.release)
- return err
-}
diff --git a/src/vendor/golang.org/x/net/netutil/listen_test.go b/src/vendor/golang.org/x/net/netutil/listen_test.go
deleted file mode 100644
index c1a3d55..0000000
--- a/src/vendor/golang.org/x/net/netutil/listen_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package netutil
-
-import (
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "sync"
- "sync/atomic"
- "testing"
- "time"
-
- "golang.org/x/net/internal/nettest"
-)
-
-func TestLimitListener(t *testing.T) {
- const max = 5
- attempts := (nettest.MaxOpenFiles() - max) / 2
- if attempts > 256 { // maximum length of accept queue is 128 by default
- attempts = 256
- }
-
- l, err := net.Listen("tcp", "127.0.0.1:0")
- if err != nil {
- t.Fatal(err)
- }
- defer l.Close()
- l = LimitListener(l, max)
-
- var open int32
- go http.Serve(l, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- if n := atomic.AddInt32(&open, 1); n > max {
- t.Errorf("%d open connections, want <= %d", n, max)
- }
- defer atomic.AddInt32(&open, -1)
- time.Sleep(10 * time.Millisecond)
- fmt.Fprint(w, "some body")
- }))
-
- var wg sync.WaitGroup
- var failed int32
- for i := 0; i < attempts; i++ {
- wg.Add(1)
- go func() {
- defer wg.Done()
- c := http.Client{Timeout: 3 * time.Second}
- r, err := c.Get("http://" + l.Addr().String())
- if err != nil {
- t.Log(err)
- atomic.AddInt32(&failed, 1)
- return
- }
- defer r.Body.Close()
- io.Copy(ioutil.Discard, r.Body)
- }()
- }
- wg.Wait()
-
- // We expect some Gets to fail as the kernel's accept queue is filled,
- // but most should succeed.
- if int(failed) >= attempts/2 {
- t.Errorf("%d requests failed within %d attempts", failed, attempts)
- }
-}
-
-type errorListener struct {
- net.Listener
-}
-
-func (errorListener) Accept() (net.Conn, error) {
- return nil, errFake
-}
-
-var errFake = errors.New("fake error from errorListener")
-
-// This used to hang.
-func TestLimitListenerError(t *testing.T) {
- donec := make(chan bool, 1)
- go func() {
- const n = 2
- ll := LimitListener(errorListener{}, n)
- for i := 0; i < n+1; i++ {
- _, err := ll.Accept()
- if err != errFake {
- t.Fatalf("Accept error = %v; want errFake", err)
- }
- }
- donec <- true
- }()
- select {
- case <-donec:
- case <-time.After(5 * time.Second):
- t.Fatal("timeout. deadlock?")
- }
-}
diff --git a/src/vendor/github.com/alexedwards/stack/LICENSE b/vendor/github.com/alexedwards/stack/LICENSE
index f25a33b..f25a33b 100644
--- a/src/vendor/github.com/alexedwards/stack/LICENSE
+++ b/vendor/github.com/alexedwards/stack/LICENSE
diff --git a/src/vendor/github.com/alexedwards/stack/context.go b/vendor/github.com/alexedwards/stack/context.go
index 07afe21..07afe21 100644
--- a/src/vendor/github.com/alexedwards/stack/context.go
+++ b/vendor/github.com/alexedwards/stack/context.go
diff --git a/src/vendor/github.com/alexedwards/stack/stack.go b/vendor/github.com/alexedwards/stack/stack.go
index 47c42b2..47c42b2 100644
--- a/src/vendor/github.com/alexedwards/stack/stack.go
+++ b/vendor/github.com/alexedwards/stack/stack.go
diff --git a/vendor/github.com/codegangsta/inject/LICENSE b/vendor/github.com/codegangsta/inject/LICENSE
new file mode 100644
index 0000000..eb68a0e
--- /dev/null
+++ b/vendor/github.com/codegangsta/inject/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Jeremy Saenz
+
+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/codegangsta/inject/inject.go b/vendor/github.com/codegangsta/inject/inject.go
new file mode 100644
index 0000000..3ff713c
--- /dev/null
+++ b/vendor/github.com/codegangsta/inject/inject.go
@@ -0,0 +1,187 @@
+// Package inject provides utilities for mapping and injecting dependencies in various ways.
+package inject
+
+import (
+ "fmt"
+ "reflect"
+)
+
+// Injector represents an interface for mapping and injecting dependencies into structs
+// and function arguments.
+type Injector interface {
+ Applicator
+ Invoker
+ TypeMapper
+ // SetParent sets the parent of the injector. If the injector cannot find a
+ // dependency in its Type map it will check its parent before returning an
+ // error.
+ SetParent(Injector)
+}
+
+// Applicator represents an interface for mapping dependencies to a struct.
+type Applicator interface {
+ // Maps dependencies in the Type map to each field in the struct
+ // that is tagged with 'inject'. Returns an error if the injection
+ // fails.
+ Apply(interface{}) error
+}
+
+// Invoker represents an interface for calling functions via reflection.
+type Invoker interface {
+ // Invoke attempts to call the interface{} provided as a function,
+ // providing dependencies for function arguments based on Type. Returns
+ // a slice of reflect.Value representing the returned values of the function.
+ // Returns an error if the injection fails.
+ Invoke(interface{}) ([]reflect.Value, error)
+}
+
+// TypeMapper represents an interface for mapping interface{} values based on type.
+type TypeMapper interface {
+ // Maps the interface{} value based on its immediate type from reflect.TypeOf.
+ Map(interface{}) TypeMapper
+ // Maps the interface{} value based on the pointer of an Interface provided.
+ // This is really only useful for mapping a value as an interface, as interfaces
+ // cannot at this time be referenced directly without a pointer.
+ MapTo(interface{}, interface{}) TypeMapper
+ // Provides a possibility to directly insert a mapping based on type and value.
+ // This makes it possible to directly map type arguments not possible to instantiate
+ // with reflect like unidirectional channels.
+ Set(reflect.Type, reflect.Value) TypeMapper
+ // Returns the Value that is mapped to the current type. Returns a zeroed Value if
+ // the Type has not been mapped.
+ Get(reflect.Type) reflect.Value
+}
+
+type injector struct {
+ values map[reflect.Type]reflect.Value
+ parent Injector
+}
+
+// InterfaceOf dereferences a pointer to an Interface type.
+// It panics if value is not an pointer to an interface.
+func InterfaceOf(value interface{}) reflect.Type {
+ t := reflect.TypeOf(value)
+
+ for t.Kind() == reflect.Ptr {
+ t = t.Elem()
+ }
+
+ if t.Kind() != reflect.Interface {
+ panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")
+ }
+
+ return t
+}
+
+// New returns a new Injector.
+func New() Injector {
+ return &injector{
+ values: make(map[reflect.Type]reflect.Value),
+ }
+}
+
+// Invoke attempts to call the interface{} provided as a function,
+// providing dependencies for function arguments based on Type.
+// Returns a slice of reflect.Value representing the returned values of the function.
+// Returns an error if the injection fails.
+// It panics if f is not a function
+func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
+ t := reflect.TypeOf(f)
+
+ var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
+ for i := 0; i < t.NumIn(); i++ {
+ argType := t.In(i)
+ val := inj.Get(argType)
+ if !val.IsValid() {
+ return nil, fmt.Errorf("Value not found for type %v", argType)
+ }
+
+ in[i] = val
+ }
+
+ return reflect.ValueOf(f).Call(in), nil
+}
+
+// Maps dependencies in the Type map to each field in the struct
+// that is tagged with 'inject'.
+// Returns an error if the injection fails.
+func (inj *injector) Apply(val interface{}) error {
+ v := reflect.ValueOf(val)
+
+ for v.Kind() == reflect.Ptr {
+ v = v.Elem()
+ }
+
+ if v.Kind() != reflect.Struct {
+ return nil // Should not panic here ?
+ }
+
+ t := v.Type()
+
+ for i := 0; i < v.NumField(); i++ {
+ f := v.Field(i)
+ structField := t.Field(i)
+ if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {
+ ft := f.Type()
+ v := inj.Get(ft)
+ if !v.IsValid() {
+ return fmt.Errorf("Value not found for type %v", ft)
+ }
+
+ f.Set(v)
+ }
+
+ }
+
+ return nil
+}
+
+// Maps the concrete value of val to its dynamic type using reflect.TypeOf,
+// It returns the TypeMapper registered in.
+func (i *injector) Map(val interface{}) TypeMapper {
+ i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
+ return i
+}
+
+func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
+ i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
+ return i
+}
+
+// Maps the given reflect.Type to the given reflect.Value and returns
+// the Typemapper the mapping has been registered in.
+func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
+ i.values[typ] = val
+ return i
+}
+
+func (i *injector) Get(t reflect.Type) reflect.Value {
+ val := i.values[t]
+
+ if val.IsValid() {
+ return val
+ }
+
+ // no concrete types found, try to find implementors
+ // if t is an interface
+ if t.Kind() == reflect.Interface {
+ for k, v := range i.values {
+ if k.Implements(t) {
+ val = v
+ break
+ }
+ }
+ }
+
+ // Still no type found, try to look it up on the parent
+ if !val.IsValid() && i.parent != nil {
+ val = i.parent.Get(t)
+ }
+
+ return val
+
+}
+
+func (i *injector) SetParent(parent Injector) {
+ i.parent = parent
+}
diff --git a/vendor/github.com/codegangsta/negroni/LICENSE b/vendor/github.com/codegangsta/negroni/LICENSE
new file mode 100644
index 0000000..08b5e20
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Jeremy Saenz
+
+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/codegangsta/negroni/doc.go b/vendor/github.com/codegangsta/negroni/doc.go
new file mode 100644
index 0000000..add1ed9
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/doc.go
@@ -0,0 +1,25 @@
+// Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers.
+//
+// If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit.
+//
+// For a full guide visit http://github.com/urfave/negroni
+//
+// package main
+//
+// import (
+// "github.com/urfave/negroni"
+// "net/http"
+// "fmt"
+// )
+//
+// func main() {
+// mux := http.NewServeMux()
+// mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+// fmt.Fprintf(w, "Welcome to the home page!")
+// })
+//
+// n := negroni.Classic()
+// n.UseHandler(mux)
+// n.Run(":3000")
+// }
+package negroni
diff --git a/vendor/github.com/codegangsta/negroni/logger.go b/vendor/github.com/codegangsta/negroni/logger.go
new file mode 100644
index 0000000..04cd53b
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/logger.go
@@ -0,0 +1,35 @@
+package negroni
+
+import (
+ "log"
+ "net/http"
+ "os"
+ "time"
+)
+
+// ALogger interface
+type ALogger interface {
+ Println(v ...interface{})
+ Printf(format string, v ...interface{})
+}
+
+// Logger is a middleware handler that logs the request as it goes in and the response as it goes out.
+type Logger struct {
+ // ALogger implements just enough log.Logger interface to be compatible with other implementations
+ ALogger
+}
+
+// NewLogger returns a new Logger instance
+func NewLogger() *Logger {
+ return &Logger{log.New(os.Stdout, "[negroni] ", 0)}
+}
+
+func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ start := time.Now()
+ l.Printf("Started %s %s", r.Method, r.URL.Path)
+
+ next(rw, r)
+
+ res := rw.(ResponseWriter)
+ l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start))
+}
diff --git a/vendor/github.com/codegangsta/negroni/negroni.go b/vendor/github.com/codegangsta/negroni/negroni.go
new file mode 100644
index 0000000..9c7c187
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/negroni.go
@@ -0,0 +1,133 @@
+package negroni
+
+import (
+ "log"
+ "net/http"
+ "os"
+)
+
+// Handler handler is an interface that objects can implement to be registered to serve as middleware
+// in the Negroni middleware stack.
+// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc
+// passed in.
+//
+// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked.
+type Handler interface {
+ ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+}
+
+// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.
+// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
+type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+
+func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ h(rw, r, next)
+}
+
+type middleware struct {
+ handler Handler
+ next *middleware
+}
+
+func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
+}
+
+// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni
+// middleware. The next http.HandlerFunc is automatically called after the Handler
+// is executed.
+func Wrap(handler http.Handler) Handler {
+ return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ handler.ServeHTTP(rw, r)
+ next(rw, r)
+ })
+}
+
+// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler.
+// Negroni middleware is evaluated in the order that they are added to the stack using
+// the Use and UseHandler methods.
+type Negroni struct {
+ middleware middleware
+ handlers []Handler
+}
+
+// New returns a new Negroni instance with no middleware preconfigured.
+func New(handlers ...Handler) *Negroni {
+ return &Negroni{
+ handlers: handlers,
+ middleware: build(handlers),
+ }
+}
+
+// Classic returns a new Negroni instance with the default middleware already
+// in the stack.
+//
+// Recovery - Panic Recovery Middleware
+// Logger - Request/Response Logging
+// Static - Static File Serving
+func Classic() *Negroni {
+ return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public")))
+}
+
+func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ n.middleware.ServeHTTP(NewResponseWriter(rw), r)
+}
+
+// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
+func (n *Negroni) Use(handler Handler) {
+ if handler == nil {
+ panic("handler cannot be nil")
+ }
+
+ n.handlers = append(n.handlers, handler)
+ n.middleware = build(n.handlers)
+}
+
+// UseFunc adds a Negroni-style handler function onto the middleware stack.
+func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
+ n.Use(HandlerFunc(handlerFunc))
+}
+
+// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
+func (n *Negroni) UseHandler(handler http.Handler) {
+ n.Use(Wrap(handler))
+}
+
+// UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack.
+func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) {
+ n.UseHandler(http.HandlerFunc(handlerFunc))
+}
+
+// Run is a convenience function that runs the negroni stack as an HTTP
+// server. The addr string takes the same format as http.ListenAndServe.
+func (n *Negroni) Run(addr string) {
+ l := log.New(os.Stdout, "[negroni] ", 0)
+ l.Printf("listening on %s", addr)
+ l.Fatal(http.ListenAndServe(addr, n))
+}
+
+// Returns a list of all the handlers in the current Negroni middleware chain.
+func (n *Negroni) Handlers() []Handler {
+ return n.handlers
+}
+
+func build(handlers []Handler) middleware {
+ var next middleware
+
+ if len(handlers) == 0 {
+ return voidMiddleware()
+ } else if len(handlers) > 1 {
+ next = build(handlers[1:])
+ } else {
+ next = voidMiddleware()
+ }
+
+ return middleware{handlers[0], &next}
+}
+
+func voidMiddleware() middleware {
+ return middleware{
+ HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),
+ &middleware{},
+ }
+}
diff --git a/vendor/github.com/codegangsta/negroni/recovery.go b/vendor/github.com/codegangsta/negroni/recovery.go
new file mode 100644
index 0000000..8396cb1
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/recovery.go
@@ -0,0 +1,65 @@
+package negroni
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "runtime"
+ "runtime/debug"
+)
+
+// Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one.
+type Recovery struct {
+ Logger ALogger
+ PrintStack bool
+ ErrorHandlerFunc func(interface{})
+ StackAll bool
+ StackSize int
+}
+
+// NewRecovery returns a new instance of Recovery
+func NewRecovery() *Recovery {
+ return &Recovery{
+ Logger: log.New(os.Stdout, "[negroni] ", 0),
+ PrintStack: true,
+ StackAll: false,
+ StackSize: 1024 * 8,
+ }
+}
+
+func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ defer func() {
+ if err := recover(); err != nil {
+ if rw.Header().Get("Content-Type") == "" {
+ rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ }
+
+ rw.WriteHeader(http.StatusInternalServerError)
+
+ stack := make([]byte, rec.StackSize)
+ stack = stack[:runtime.Stack(stack, rec.StackAll)]
+
+ f := "PANIC: %s\n%s"
+ rec.Logger.Printf(f, err, stack)
+
+ if rec.PrintStack {
+ fmt.Fprintf(rw, f, err, stack)
+ }
+
+ if rec.ErrorHandlerFunc != nil {
+ func() {
+ defer func() {
+ if err := recover(); err != nil {
+ rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack())
+ rec.Logger.Printf("%s\n", debug.Stack())
+ }
+ }()
+ rec.ErrorHandlerFunc(err)
+ }()
+ }
+ }
+ }()
+
+ next(rw, r)
+}
diff --git a/vendor/github.com/codegangsta/negroni/response_writer.go b/vendor/github.com/codegangsta/negroni/response_writer.go
new file mode 100644
index 0000000..bfb83a6
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/response_writer.go
@@ -0,0 +1,113 @@
+package negroni
+
+import (
+ "bufio"
+ "fmt"
+ "net"
+ "net/http"
+)
+
+// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
+// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
+// if the functionality calls for it.
+type ResponseWriter interface {
+ http.ResponseWriter
+ http.Flusher
+ // Status returns the status code of the response or 200 if the response has
+ // not been written (as this is the default response code in net/http)
+ Status() int
+ // Written returns whether or not the ResponseWriter has been written.
+ Written() bool
+ // Size returns the size of the response body.
+ Size() int
+ // Before allows for a function to be called before the ResponseWriter has been written to. This is
+ // useful for setting headers or any other operations that must happen before a response has been written.
+ Before(func(ResponseWriter))
+}
+
+type beforeFunc func(ResponseWriter)
+
+// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
+func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
+ nrw := &responseWriter{
+ ResponseWriter: rw,
+ }
+
+ if _, ok := rw.(http.CloseNotifier); ok {
+ return &responseWriterCloseNotifer{nrw}
+ }
+
+ return nrw
+}
+
+type responseWriter struct {
+ http.ResponseWriter
+ status int
+ size int
+ beforeFuncs []beforeFunc
+}
+
+func (rw *responseWriter) WriteHeader(s int) {
+ rw.status = s
+ rw.callBefore()
+ rw.ResponseWriter.WriteHeader(s)
+}
+
+func (rw *responseWriter) Write(b []byte) (int, error) {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ size, err := rw.ResponseWriter.Write(b)
+ rw.size += size
+ return size, err
+}
+
+func (rw *responseWriter) Status() int {
+ return rw.status
+}
+
+func (rw *responseWriter) Size() int {
+ return rw.size
+}
+
+func (rw *responseWriter) Written() bool {
+ return rw.status != 0
+}
+
+func (rw *responseWriter) Before(before func(ResponseWriter)) {
+ rw.beforeFuncs = append(rw.beforeFuncs, before)
+}
+
+func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ hijacker, ok := rw.ResponseWriter.(http.Hijacker)
+ if !ok {
+ return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
+ }
+ return hijacker.Hijack()
+}
+
+func (rw *responseWriter) callBefore() {
+ for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
+ rw.beforeFuncs[i](rw)
+ }
+}
+
+func (rw *responseWriter) Flush() {
+ flusher, ok := rw.ResponseWriter.(http.Flusher)
+ if ok {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ flusher.Flush()
+ }
+}
+
+type responseWriterCloseNotifer struct {
+ *responseWriter
+}
+
+func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool {
+ return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
diff --git a/vendor/github.com/codegangsta/negroni/static.go b/vendor/github.com/codegangsta/negroni/static.go
new file mode 100644
index 0000000..34be967
--- /dev/null
+++ b/vendor/github.com/codegangsta/negroni/static.go
@@ -0,0 +1,88 @@
+package negroni
+
+import (
+ "net/http"
+ "path"
+ "strings"
+)
+
+// Static is a middleware handler that serves static files in the given
+// directory/filesystem. If the file does not exist on the filesystem, it
+// passes along to the next middleware in the chain. If you desire "fileserver"
+// type behavior where it returns a 404 for unfound files, you should consider
+// using http.FileServer from the Go stdlib.
+type Static struct {
+ // Dir is the directory to serve static files from
+ Dir http.FileSystem
+ // Prefix is the optional prefix used to serve the static directory content
+ Prefix string
+ // IndexFile defines which file to serve as index if it exists.
+ IndexFile string
+}
+
+// NewStatic returns a new instance of Static
+func NewStatic(directory http.FileSystem) *Static {
+ return &Static{
+ Dir: directory,
+ Prefix: "",
+ IndexFile: "index.html",
+ }
+}
+
+func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ if r.Method != "GET" && r.Method != "HEAD" {
+ next(rw, r)
+ return
+ }
+ file := r.URL.Path
+ // if we have a prefix, filter requests by stripping the prefix
+ if s.Prefix != "" {
+ if !strings.HasPrefix(file, s.Prefix) {
+ next(rw, r)
+ return
+ }
+ file = file[len(s.Prefix):]
+ if file != "" && file[0] != '/' {
+ next(rw, r)
+ return
+ }
+ }
+ f, err := s.Dir.Open(file)
+ if err != nil {
+ // discard the error?
+ next(rw, r)
+ return
+ }
+ defer f.Close()
+
+ fi, err := f.Stat()
+ if err != nil {
+ next(rw, r)
+ return
+ }
+
+ // try to serve index file
+ if fi.IsDir() {
+ // redirect if missing trailing slash
+ if !strings.HasSuffix(r.URL.Path, "/") {
+ http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound)
+ return
+ }
+
+ file = path.Join(file, s.IndexFile)
+ f, err = s.Dir.Open(file)
+ if err != nil {
+ next(rw, r)
+ return
+ }
+ defer f.Close()
+
+ fi, err = f.Stat()
+ if err != nil || fi.IsDir() {
+ next(rw, r)
+ return
+ }
+ }
+
+ http.ServeContent(rw, r, file, fi.ModTime(), f)
+}
diff --git a/vendor/github.com/go-martini/martini/LICENSE b/vendor/github.com/go-martini/martini/LICENSE
new file mode 100644
index 0000000..d3fefb8
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Jeremy Saenz
+
+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/go-martini/martini/env.go b/vendor/github.com/go-martini/martini/env.go
new file mode 100644
index 0000000..54d5857
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/env.go
@@ -0,0 +1,31 @@
+package martini
+
+import (
+ "os"
+)
+
+// Envs
+const (
+ Dev string = "development"
+ Prod string = "production"
+ Test string = "test"
+)
+
+// Env is the environment that Martini is executing in. The MARTINI_ENV is read on initialization to set this variable.
+var Env = Dev
+var Root string
+
+func setENV(e string) {
+ if len(e) > 0 {
+ Env = e
+ }
+}
+
+func init() {
+ setENV(os.Getenv("MARTINI_ENV"))
+ var err error
+ Root, err = os.Getwd()
+ if err != nil {
+ panic(err)
+ }
+}
diff --git a/vendor/github.com/go-martini/martini/go_version.go b/vendor/github.com/go-martini/martini/go_version.go
new file mode 100644
index 0000000..bd271a8
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/go_version.go
@@ -0,0 +1,7 @@
+// +build !go1.1
+
+package martini
+
+func MartiniDoesNotSupportGo1Point0() {
+ "Martini requires Go 1.1 or greater."
+}
diff --git a/vendor/github.com/go-martini/martini/logger.go b/vendor/github.com/go-martini/martini/logger.go
new file mode 100644
index 0000000..d01107c
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/logger.go
@@ -0,0 +1,29 @@
+package martini
+
+import (
+ "log"
+ "net/http"
+ "time"
+)
+
+// Logger returns a middleware handler that logs the request as it goes in and the response as it goes out.
+func Logger() Handler {
+ return func(res http.ResponseWriter, req *http.Request, c Context, log *log.Logger) {
+ start := time.Now()
+
+ addr := req.Header.Get("X-Real-IP")
+ if addr == "" {
+ addr = req.Header.Get("X-Forwarded-For")
+ if addr == "" {
+ addr = req.RemoteAddr
+ }
+ }
+
+ log.Printf("Started %s %s for %s", req.Method, req.URL.Path, addr)
+
+ rw := res.(ResponseWriter)
+ c.Next()
+
+ log.Printf("Completed %v %s in %v\n", rw.Status(), http.StatusText(rw.Status()), time.Since(start))
+ }
+}
diff --git a/vendor/github.com/go-martini/martini/martini.go b/vendor/github.com/go-martini/martini/martini.go
new file mode 100644
index 0000000..0ce4f3d
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/martini.go
@@ -0,0 +1,189 @@
+// Package martini is a powerful package for quickly writing modular web applications/services in Golang.
+//
+// For a full guide visit http://github.com/go-martini/martini
+//
+// package main
+//
+// import "github.com/go-martini/martini"
+//
+// func main() {
+// m := martini.Classic()
+//
+// m.Get("/", func() string {
+// return "Hello world!"
+// })
+//
+// m.Run()
+// }
+package martini
+
+import (
+ "log"
+ "net/http"
+ "os"
+ "reflect"
+
+ "github.com/codegangsta/inject"
+)
+
+// Martini represents the top level web application. inject.Injector methods can be invoked to map services on a global level.
+type Martini struct {
+ inject.Injector
+ handlers []Handler
+ action Handler
+ logger *log.Logger
+}
+
+// New creates a bare bones Martini instance. Use this method if you want to have full control over the middleware that is used.
+func New() *Martini {
+ m := &Martini{Injector: inject.New(), action: func() {}, logger: log.New(os.Stdout, "[martini] ", 0)}
+ m.Map(m.logger)
+ m.Map(defaultReturnHandler())
+ return m
+}
+
+// Handlers sets the entire middleware stack with the given Handlers. This will clear any current middleware handlers.
+// Will panic if any of the handlers is not a callable function
+func (m *Martini) Handlers(handlers ...Handler) {
+ m.handlers = make([]Handler, 0)
+ for _, handler := range handlers {
+ m.Use(handler)
+ }
+}
+
+// Action sets the handler that will be called after all the middleware has been invoked. This is set to martini.Router in a martini.Classic().
+func (m *Martini) Action(handler Handler) {
+ validateHandler(handler)
+ m.action = handler
+}
+
+// Logger sets the logger
+func (m *Martini) Logger(logger *log.Logger) {
+ m.logger = logger
+ m.Map(m.logger)
+}
+
+// Use adds a middleware Handler to the stack. Will panic if the handler is not a callable func. Middleware Handlers are invoked in the order that they are added.
+func (m *Martini) Use(handler Handler) {
+ validateHandler(handler)
+
+ m.handlers = append(m.handlers, handler)
+}
+
+// ServeHTTP is the HTTP Entry point for a Martini instance. Useful if you want to control your own HTTP server.
+func (m *Martini) ServeHTTP(res http.ResponseWriter, req *http.Request) {
+ m.createContext(res, req).run()
+}
+
+// Run the http server on a given host and port.
+func (m *Martini) RunOnAddr(addr string) {
+ // TODO: Should probably be implemented using a new instance of http.Server in place of
+ // calling http.ListenAndServer directly, so that it could be stored in the martini struct for later use.
+ // This would also allow to improve testing when a custom host and port are passed.
+
+ logger := m.Injector.Get(reflect.TypeOf(m.logger)).Interface().(*log.Logger)
+ logger.Printf("listening on %s (%s)\n", addr, Env)
+ logger.Fatalln(http.ListenAndServe(addr, m))
+}
+
+// Run the http server. Listening on os.GetEnv("PORT") or 3000 by default.
+func (m *Martini) Run() {
+ port := os.Getenv("PORT")
+ if len(port) == 0 {
+ port = "3000"
+ }
+
+ host := os.Getenv("HOST")
+
+ m.RunOnAddr(host + ":" + port)
+}
+
+func (m *Martini) createContext(res http.ResponseWriter, req *http.Request) *context {
+ c := &context{inject.New(), m.handlers, m.action, NewResponseWriter(res), 0}
+ c.SetParent(m)
+ c.MapTo(c, (*Context)(nil))
+ c.MapTo(c.rw, (*http.ResponseWriter)(nil))
+ c.Map(req)
+ return c
+}
+
+// ClassicMartini represents a Martini with some reasonable defaults. Embeds the router functions for convenience.
+type ClassicMartini struct {
+ *Martini
+ Router
+}
+
+// Classic creates a classic Martini with some basic default middleware - martini.Logger, martini.Recovery and martini.Static.
+// Classic also maps martini.Routes as a service.
+func Classic() *ClassicMartini {
+ r := NewRouter()
+ m := New()
+ m.Use(Logger())
+ m.Use(Recovery())
+ m.Use(Static("public"))
+ m.MapTo(r, (*Routes)(nil))
+ m.Action(r.Handle)
+ return &ClassicMartini{m, r}
+}
+
+// Handler can be any callable function. Martini attempts to inject services into the handler's argument list.
+// Martini will panic if an argument could not be fullfilled via dependency injection.
+type Handler interface{}
+
+func validateHandler(handler Handler) {
+ if reflect.TypeOf(handler).Kind() != reflect.Func {
+ panic("martini handler must be a callable func")
+ }
+}
+
+// Context represents a request context. Services can be mapped on the request level from this interface.
+type Context interface {
+ inject.Injector
+ // Next is an optional function that Middleware Handlers can call to yield the until after
+ // the other Handlers have been executed. This works really well for any operations that must
+ // happen after an http request
+ Next()
+ // Written returns whether or not the response for this context has been written.
+ Written() bool
+}
+
+type context struct {
+ inject.Injector
+ handlers []Handler
+ action Handler
+ rw ResponseWriter
+ index int
+}
+
+func (c *context) handler() Handler {
+ if c.index < len(c.handlers) {
+ return c.handlers[c.index]
+ }
+ if c.index == len(c.handlers) {
+ return c.action
+ }
+ panic("invalid index for context handler")
+}
+
+func (c *context) Next() {
+ c.index += 1
+ c.run()
+}
+
+func (c *context) Written() bool {
+ return c.rw.Written()
+}
+
+func (c *context) run() {
+ for c.index <= len(c.handlers) {
+ _, err := c.Invoke(c.handler())
+ if err != nil {
+ panic(err)
+ }
+ c.index += 1
+
+ if c.Written() {
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/go-martini/martini/recovery.go b/vendor/github.com/go-martini/martini/recovery.go
new file mode 100644
index 0000000..fe0d918
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/recovery.go
@@ -0,0 +1,144 @@
+package martini
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "net/http"
+ "runtime"
+
+ "github.com/codegangsta/inject"
+)
+
+const (
+ panicHtml = `<html>
+<head><title>PANIC: %s</title>
+<style type="text/css">
+html, body {
+ font-family: "Roboto", sans-serif;
+ color: #333333;
+ background-color: #ea5343;
+ margin: 0px;
+}
+h1 {
+ color: #d04526;
+ background-color: #ffffff;
+ padding: 20px;
+ border-bottom: 1px dashed #2b3848;
+}
+pre {
+ margin: 20px;
+ padding: 20px;
+ border: 2px solid #2b3848;
+ background-color: #ffffff;
+}
+</style>
+</head><body>
+<h1>PANIC</h1>
+<pre style="font-weight: bold;">%s</pre>
+<pre>%s</pre>
+</body>
+</html>`
+)
+
+var (
+ dunno = []byte("???")
+ centerDot = []byte("·")
+ dot = []byte(".")
+ slash = []byte("/")
+)
+
+// stack returns a nicely formated stack frame, skipping skip frames
+func stack(skip int) []byte {
+ buf := new(bytes.Buffer) // the returned data
+ // As we loop, we open files and read them. These variables record the currently
+ // loaded file.
+ var lines [][]byte
+ var lastFile string
+ for i := skip; ; i++ { // Skip the expected number of frames
+ pc, file, line, ok := runtime.Caller(i)
+ if !ok {
+ break
+ }
+ // Print this much at least. If we can't find the source, it won't show.
+ fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
+ if file != lastFile {
+ data, err := ioutil.ReadFile(file)
+ if err != nil {
+ continue
+ }
+ lines = bytes.Split(data, []byte{'\n'})
+ lastFile = file
+ }
+ fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
+ }
+ return buf.Bytes()
+}
+
+// source returns a space-trimmed slice of the n'th line.
+func source(lines [][]byte, n int) []byte {
+ n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
+ if n < 0 || n >= len(lines) {
+ return dunno
+ }
+ return bytes.TrimSpace(lines[n])
+}
+
+// function returns, if possible, the name of the function containing the PC.
+func function(pc uintptr) []byte {
+ fn := runtime.FuncForPC(pc)
+ if fn == nil {
+ return dunno
+ }
+ name := []byte(fn.Name())
+ // The name includes the path name to the package, which is unnecessary
+ // since the file name is already included. Plus, it has center dots.
+ // That is, we see
+ // runtime/debug.*T·ptrmethod
+ // and want
+ // *T.ptrmethod
+ // Also the package path might contains dot (e.g. code.google.com/...),
+ // so first eliminate the path prefix
+ if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
+ name = name[lastslash+1:]
+ }
+ if period := bytes.Index(name, dot); period >= 0 {
+ name = name[period+1:]
+ }
+ name = bytes.Replace(name, centerDot, dot, -1)
+ return name
+}
+
+// Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
+// While Martini is in development mode, Recovery will also output the panic as HTML.
+func Recovery() Handler {
+ return func(c Context, log *log.Logger) {
+ defer func() {
+ if err := recover(); err != nil {
+ stack := stack(3)
+ log.Printf("PANIC: %s\n%s", err, stack)
+
+ // Lookup the current responsewriter
+ val := c.Get(inject.InterfaceOf((*http.ResponseWriter)(nil)))
+ res := val.Interface().(http.ResponseWriter)
+
+ // respond with panic message while in development mode
+ var body []byte
+ if Env == Dev {
+ res.Header().Set("Content-Type", "text/html")
+ body = []byte(fmt.Sprintf(panicHtml, err, err, stack))
+ } else {
+ body = []byte("500 Internal Server Error")
+ }
+
+ res.WriteHeader(http.StatusInternalServerError)
+ if nil != body {
+ res.Write(body)
+ }
+ }
+ }()
+
+ c.Next()
+ }
+}
diff --git a/vendor/github.com/go-martini/martini/response_writer.go b/vendor/github.com/go-martini/martini/response_writer.go
new file mode 100644
index 0000000..12574b1
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/response_writer.go
@@ -0,0 +1,107 @@
+package martini
+
+import (
+ "bufio"
+ "fmt"
+ "net"
+ "net/http"
+)
+
+// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
+// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
+// if the functionality calls for it.
+type ResponseWriter interface {
+ http.ResponseWriter
+ http.Flusher
+ http.Hijacker
+ // Status returns the status code of the response or 0 if the response has not been written.
+ Status() int
+ // Written returns whether or not the ResponseWriter has been written.
+ Written() bool
+ // Size returns the size of the response body.
+ Size() int
+ // Before allows for a function to be called before the ResponseWriter has been written to. This is
+ // useful for setting headers or any other operations that must happen before a response has been written.
+ Before(BeforeFunc)
+}
+
+// BeforeFunc is a function that is called before the ResponseWriter has been written to.
+type BeforeFunc func(ResponseWriter)
+
+// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
+func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
+ newRw := responseWriter{rw, 0, 0, nil}
+ if cn, ok := rw.(http.CloseNotifier); ok {
+ return &closeNotifyResponseWriter{newRw, cn}
+ }
+ return &newRw
+}
+
+type responseWriter struct {
+ http.ResponseWriter
+ status int
+ size int
+ beforeFuncs []BeforeFunc
+}
+
+func (rw *responseWriter) WriteHeader(s int) {
+ rw.callBefore()
+ rw.ResponseWriter.WriteHeader(s)
+ rw.status = s
+}
+
+func (rw *responseWriter) Write(b []byte) (int, error) {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ size, err := rw.ResponseWriter.Write(b)
+ rw.size += size
+ return size, err
+}
+
+func (rw *responseWriter) Status() int {
+ return rw.status
+}
+
+func (rw *responseWriter) Size() int {
+ return rw.size
+}
+
+func (rw *responseWriter) Written() bool {
+ return rw.status != 0
+}
+
+func (rw *responseWriter) Before(before BeforeFunc) {
+ rw.beforeFuncs = append(rw.beforeFuncs, before)
+}
+
+func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ hijacker, ok := rw.ResponseWriter.(http.Hijacker)
+ if !ok {
+ return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
+ }
+ return hijacker.Hijack()
+}
+
+func (rw *responseWriter) callBefore() {
+ for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
+ rw.beforeFuncs[i](rw)
+ }
+}
+
+func (rw *responseWriter) Flush() {
+ flusher, ok := rw.ResponseWriter.(http.Flusher)
+ if ok {
+ flusher.Flush()
+ }
+}
+
+type closeNotifyResponseWriter struct {
+ responseWriter
+ closeNotifier http.CloseNotifier
+}
+
+func (rw *closeNotifyResponseWriter) CloseNotify() <-chan bool {
+ return rw.closeNotifier.CloseNotify()
+}
diff --git a/vendor/github.com/go-martini/martini/return_handler.go b/vendor/github.com/go-martini/martini/return_handler.go
new file mode 100644
index 0000000..4ea8f34
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/return_handler.go
@@ -0,0 +1,43 @@
+package martini
+
+import (
+ "github.com/codegangsta/inject"
+ "net/http"
+ "reflect"
+)
+
+// ReturnHandler is a service that Martini provides that is called
+// when a route handler returns something. The ReturnHandler is
+// responsible for writing to the ResponseWriter based on the values
+// that are passed into this function.
+type ReturnHandler func(Context, []reflect.Value)
+
+func defaultReturnHandler() ReturnHandler {
+ return func(ctx Context, vals []reflect.Value) {
+ rv := ctx.Get(inject.InterfaceOf((*http.ResponseWriter)(nil)))
+ res := rv.Interface().(http.ResponseWriter)
+ var responseVal reflect.Value
+ if len(vals) > 1 && vals[0].Kind() == reflect.Int {
+ res.WriteHeader(int(vals[0].Int()))
+ responseVal = vals[1]
+ } else if len(vals) > 0 {
+ responseVal = vals[0]
+ }
+ if canDeref(responseVal) {
+ responseVal = responseVal.Elem()
+ }
+ if isByteSlice(responseVal) {
+ res.Write(responseVal.Bytes())
+ } else {
+ res.Write([]byte(responseVal.String()))
+ }
+ }
+}
+
+func isByteSlice(val reflect.Value) bool {
+ return val.Kind() == reflect.Slice && val.Type().Elem().Kind() == reflect.Uint8
+}
+
+func canDeref(val reflect.Value) bool {
+ return val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr
+}
diff --git a/vendor/github.com/go-martini/martini/router.go b/vendor/github.com/go-martini/martini/router.go
new file mode 100644
index 0000000..3abbabb
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/router.go
@@ -0,0 +1,425 @@
+package martini
+
+import (
+ "fmt"
+ "net/http"
+ "reflect"
+ "regexp"
+ "strconv"
+ "sync"
+)
+
+// Params is a map of name/value pairs for named routes. An instance of martini.Params is available to be injected into any route handler.
+type Params map[string]string
+
+// Router is Martini's de-facto routing interface. Supports HTTP verbs, stacked handlers, and dependency injection.
+type Router interface {
+ Routes
+
+ // Group adds a group where related routes can be added.
+ Group(string, func(Router), ...Handler)
+ // Get adds a route for a HTTP GET request to the specified matching pattern.
+ Get(string, ...Handler) Route
+ // Patch adds a route for a HTTP PATCH request to the specified matching pattern.
+ Patch(string, ...Handler) Route
+ // Post adds a route for a HTTP POST request to the specified matching pattern.
+ Post(string, ...Handler) Route
+ // Put adds a route for a HTTP PUT request to the specified matching pattern.
+ Put(string, ...Handler) Route
+ // Delete adds a route for a HTTP DELETE request to the specified matching pattern.
+ Delete(string, ...Handler) Route
+ // Options adds a route for a HTTP OPTIONS request to the specified matching pattern.
+ Options(string, ...Handler) Route
+ // Head adds a route for a HTTP HEAD request to the specified matching pattern.
+ Head(string, ...Handler) Route
+ // Any adds a route for any HTTP method request to the specified matching pattern.
+ Any(string, ...Handler) Route
+ // AddRoute adds a route for a given HTTP method request to the specified matching pattern.
+ AddRoute(string, string, ...Handler) Route
+
+ // NotFound sets the handlers that are called when a no route matches a request. Throws a basic 404 by default.
+ NotFound(...Handler)
+
+ // Handle is the entry point for routing. This is used as a martini.Handler
+ Handle(http.ResponseWriter, *http.Request, Context)
+}
+
+type router struct {
+ routes []*route
+ notFounds []Handler
+ groups []group
+ routesLock sync.RWMutex
+}
+
+type group struct {
+ pattern string
+ handlers []Handler
+}
+
+// NewRouter creates a new Router instance.
+// If you aren't using ClassicMartini, then you can add Routes as a
+// service with:
+//
+// m := martini.New()
+// r := martini.NewRouter()
+// m.MapTo(r, (*martini.Routes)(nil))
+//
+// If you are using ClassicMartini, then this is done for you.
+func NewRouter() Router {
+ return &router{notFounds: []Handler{http.NotFound}, groups: make([]group, 0)}
+}
+
+func (r *router) Group(pattern string, fn func(Router), h ...Handler) {
+ r.groups = append(r.groups, group{pattern, h})
+ fn(r)
+ r.groups = r.groups[:len(r.groups)-1]
+}
+
+func (r *router) Get(pattern string, h ...Handler) Route {
+ return r.addRoute("GET", pattern, h)
+}
+
+func (r *router) Patch(pattern string, h ...Handler) Route {
+ return r.addRoute("PATCH", pattern, h)
+}
+
+func (r *router) Post(pattern string, h ...Handler) Route {
+ return r.addRoute("POST", pattern, h)
+}
+
+func (r *router) Put(pattern string, h ...Handler) Route {
+ return r.addRoute("PUT", pattern, h)
+}
+
+func (r *router) Delete(pattern string, h ...Handler) Route {
+ return r.addRoute("DELETE", pattern, h)
+}
+
+func (r *router) Options(pattern string, h ...Handler) Route {
+ return r.addRoute("OPTIONS", pattern, h)
+}
+
+func (r *router) Head(pattern string, h ...Handler) Route {
+ return r.addRoute("HEAD", pattern, h)
+}
+
+func (r *router) Any(pattern string, h ...Handler) Route {
+ return r.addRoute("*", pattern, h)
+}
+
+func (r *router) AddRoute(method, pattern string, h ...Handler) Route {
+ return r.addRoute(method, pattern, h)
+}
+
+func (r *router) Handle(res http.ResponseWriter, req *http.Request, context Context) {
+ bestMatch := NoMatch
+ var bestVals map[string]string
+ var bestRoute *route
+ for _, route := range r.getRoutes() {
+ match, vals := route.Match(req.Method, req.URL.Path)
+ if match.BetterThan(bestMatch) {
+ bestMatch = match
+ bestVals = vals
+ bestRoute = route
+ if match == ExactMatch {
+ break
+ }
+ }
+ }
+ if bestMatch != NoMatch {
+ params := Params(bestVals)
+ context.Map(params)
+ bestRoute.Handle(context, res)
+ return
+ }
+
+ // no routes exist, 404
+ c := &routeContext{context, 0, r.notFounds}
+ context.MapTo(c, (*Context)(nil))
+ c.run()
+}
+
+func (r *router) NotFound(handler ...Handler) {
+ r.notFounds = handler
+}
+
+func (r *router) addRoute(method string, pattern string, handlers []Handler) *route {
+ if len(r.groups) > 0 {
+ groupPattern := ""
+ h := make([]Handler, 0)
+ for _, g := range r.groups {
+ groupPattern += g.pattern
+ h = append(h, g.handlers...)
+ }
+
+ pattern = groupPattern + pattern
+ h = append(h, handlers...)
+ handlers = h
+ }
+
+ route := newRoute(method, pattern, handlers)
+ route.Validate()
+ r.appendRoute(route)
+ return route
+}
+
+func (r *router) appendRoute(rt *route) {
+ r.routesLock.Lock()
+ defer r.routesLock.Unlock()
+ r.routes = append(r.routes, rt)
+}
+
+func (r *router) getRoutes() []*route {
+ r.routesLock.RLock()
+ defer r.routesLock.RUnlock()
+ return r.routes[:]
+}
+
+func (r *router) findRoute(name string) *route {
+ for _, route := range r.getRoutes() {
+ if route.name == name {
+ return route
+ }
+ }
+
+ return nil
+}
+
+// Route is an interface representing a Route in Martini's routing layer.
+type Route interface {
+ // URLWith returns a rendering of the Route's url with the given string params.
+ URLWith([]string) string
+ // Name sets a name for the route.
+ Name(string)
+ // GetName returns the name of the route.
+ GetName() string
+ // Pattern returns the pattern of the route.
+ Pattern() string
+ // Method returns the method of the route.
+ Method() string
+}
+
+type route struct {
+ method string
+ regex *regexp.Regexp
+ handlers []Handler
+ pattern string
+ name string
+}
+
+var routeReg1 = regexp.MustCompile(`:[^/#?()\.\\]+`)
+var routeReg2 = regexp.MustCompile(`\*\*`)
+
+func newRoute(method string, pattern string, handlers []Handler) *route {
+ route := route{method, nil, handlers, pattern, ""}
+ pattern = routeReg1.ReplaceAllStringFunc(pattern, func(m string) string {
+ return fmt.Sprintf(`(?P<%s>[^/#?]+)`, m[1:])
+ })
+ var index int
+ pattern = routeReg2.ReplaceAllStringFunc(pattern, func(m string) string {
+ index++
+ return fmt.Sprintf(`(?P<_%d>[^#?]*)`, index)
+ })
+ pattern += `\/?`
+ route.regex = regexp.MustCompile(pattern)
+ return &route
+}
+
+type RouteMatch int
+
+const (
+ NoMatch RouteMatch = iota
+ StarMatch
+ OverloadMatch
+ ExactMatch
+)
+
+//Higher number = better match
+func (r RouteMatch) BetterThan(o RouteMatch) bool {
+ return r > o
+}
+
+func (r route) MatchMethod(method string) RouteMatch {
+ switch {
+ case method == r.method:
+ return ExactMatch
+ case method == "HEAD" && r.method == "GET":
+ return OverloadMatch
+ case r.method == "*":
+ return StarMatch
+ default:
+ return NoMatch
+ }
+}
+
+func (r route) Match(method string, path string) (RouteMatch, map[string]string) {
+ // add Any method matching support
+ match := r.MatchMethod(method)
+ if match == NoMatch {
+ return match, nil
+ }
+
+ matches := r.regex.FindStringSubmatch(path)
+ if len(matches) > 0 && matches[0] == path {
+ params := make(map[string]string)
+ for i, name := range r.regex.SubexpNames() {
+ if len(name) > 0 {
+ params[name] = matches[i]
+ }
+ }
+ return match, params
+ }
+ return NoMatch, nil
+}
+
+func (r *route) Validate() {
+ for _, handler := range r.handlers {
+ validateHandler(handler)
+ }
+}
+
+func (r *route) Handle(c Context, res http.ResponseWriter) {
+ context := &routeContext{c, 0, r.handlers}
+ c.MapTo(context, (*Context)(nil))
+ c.MapTo(r, (*Route)(nil))
+ context.run()
+}
+
+var urlReg = regexp.MustCompile(`:[^/#?()\.\\]+|\(\?P<[a-zA-Z0-9]+>.*\)`)
+
+// URLWith returns the url pattern replacing the parameters for its values
+func (r *route) URLWith(args []string) string {
+ if len(args) > 0 {
+ argCount := len(args)
+ i := 0
+ url := urlReg.ReplaceAllStringFunc(r.pattern, func(m string) string {
+ var val interface{}
+ if i < argCount {
+ val = args[i]
+ } else {
+ val = m
+ }
+ i += 1
+ return fmt.Sprintf(`%v`, val)
+ })
+
+ return url
+ }
+ return r.pattern
+}
+
+func (r *route) Name(name string) {
+ r.name = name
+}
+
+func (r *route) GetName() string {
+ return r.name
+}
+
+func (r *route) Pattern() string {
+ return r.pattern
+}
+
+func (r *route) Method() string {
+ return r.method
+}
+
+// Routes is a helper service for Martini's routing layer.
+type Routes interface {
+ // URLFor returns a rendered URL for the given route. Optional params can be passed to fulfill named parameters in the route.
+ URLFor(name string, params ...interface{}) string
+ // MethodsFor returns an array of methods available for the path
+ MethodsFor(path string) []string
+ // All returns an array with all the routes in the router.
+ All() []Route
+}
+
+// URLFor returns the url for the given route name.
+func (r *router) URLFor(name string, params ...interface{}) string {
+ route := r.findRoute(name)
+
+ if route == nil {
+ panic("route not found")
+ }
+
+ var args []string
+ for _, param := range params {
+ switch v := param.(type) {
+ case int:
+ args = append(args, strconv.FormatInt(int64(v), 10))
+ case string:
+ args = append(args, v)
+ default:
+ if v != nil {
+ panic("Arguments passed to URLFor must be integers or strings")
+ }
+ }
+ }
+
+ return route.URLWith(args)
+}
+
+func (r *router) All() []Route {
+ routes := r.getRoutes()
+ var ri = make([]Route, len(routes))
+
+ for i, route := range routes {
+ ri[i] = Route(route)
+ }
+
+ return ri
+}
+
+func hasMethod(methods []string, method string) bool {
+ for _, v := range methods {
+ if v == method {
+ return true
+ }
+ }
+ return false
+}
+
+// MethodsFor returns all methods available for path
+func (r *router) MethodsFor(path string) []string {
+ methods := []string{}
+ for _, route := range r.getRoutes() {
+ matches := route.regex.FindStringSubmatch(path)
+ if len(matches) > 0 && matches[0] == path && !hasMethod(methods, route.method) {
+ methods = append(methods, route.method)
+ }
+ }
+ return methods
+}
+
+type routeContext struct {
+ Context
+ index int
+ handlers []Handler
+}
+
+func (r *routeContext) Next() {
+ r.index += 1
+ r.run()
+}
+
+func (r *routeContext) run() {
+ for r.index < len(r.handlers) {
+ handler := r.handlers[r.index]
+ vals, err := r.Invoke(handler)
+ if err != nil {
+ panic(err)
+ }
+ r.index += 1
+
+ // if the handler returned something, write it to the http response
+ if len(vals) > 0 {
+ ev := r.Get(reflect.TypeOf(ReturnHandler(nil)))
+ handleReturn := ev.Interface().(ReturnHandler)
+ handleReturn(r, vals)
+ }
+
+ if r.Written() {
+ return
+ }
+ }
+}
diff --git a/vendor/github.com/go-martini/martini/static.go b/vendor/github.com/go-martini/martini/static.go
new file mode 100644
index 0000000..51af6cf
--- /dev/null
+++ b/vendor/github.com/go-martini/martini/static.go
@@ -0,0 +1,135 @@
+package martini
+
+import (
+ "log"
+ "net/http"
+ "net/url"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+// StaticOptions is a struct for specifying configuration options for the martini.Static middleware.
+type StaticOptions struct {
+ // Prefix is the optional prefix used to serve the static directory content
+ Prefix string
+ // SkipLogging will disable [Static] log messages when a static file is served.
+ SkipLogging bool
+ // IndexFile defines which file to serve as index if it exists.
+ IndexFile string
+ // Expires defines which user-defined function to use for producing a HTTP Expires Header
+ // https://developers.google.com/speed/docs/insights/LeverageBrowserCaching
+ Expires func() string
+ // Fallback defines a default URL to serve when the requested resource was
+ // not found.
+ Fallback string
+ // Exclude defines a pattern for URLs this handler should never process.
+ Exclude string
+}
+
+func prepareStaticOptions(options []StaticOptions) StaticOptions {
+ var opt StaticOptions
+ if len(options) > 0 {
+ opt = options[0]
+ }
+
+ // Defaults
+ if len(opt.IndexFile) == 0 {
+ opt.IndexFile = "index.html"
+ }
+ // Normalize the prefix if provided
+ if opt.Prefix != "" {
+ // Ensure we have a leading '/'
+ if opt.Prefix[0] != '/' {
+ opt.Prefix = "/" + opt.Prefix
+ }
+ // Remove any trailing '/'
+ opt.Prefix = strings.TrimRight(opt.Prefix, "/")
+ }
+ return opt
+}
+
+// Static returns a middleware handler that serves static files in the given directory.
+func Static(directory string, staticOpt ...StaticOptions) Handler {
+ if !filepath.IsAbs(directory) {
+ directory = filepath.Join(Root, directory)
+ }
+ dir := http.Dir(directory)
+ opt := prepareStaticOptions(staticOpt)
+
+ return func(res http.ResponseWriter, req *http.Request, log *log.Logger) {
+ if req.Method != "GET" && req.Method != "HEAD" {
+ return
+ }
+ if opt.Exclude != "" && strings.HasPrefix(req.URL.Path, opt.Exclude) {
+ return
+ }
+ file := req.URL.Path
+ // if we have a prefix, filter requests by stripping the prefix
+ if opt.Prefix != "" {
+ if !strings.HasPrefix(file, opt.Prefix) {
+ return
+ }
+ file = file[len(opt.Prefix):]
+ if file != "" && file[0] != '/' {
+ return
+ }
+ }
+ f, err := dir.Open(file)
+ if err != nil {
+ // try any fallback before giving up
+ if opt.Fallback != "" {
+ file = opt.Fallback // so that logging stays true
+ f, err = dir.Open(opt.Fallback)
+ }
+
+ if err != nil {
+ // discard the error?
+ return
+ }
+ }
+ defer f.Close()
+
+ fi, err := f.Stat()
+ if err != nil {
+ return
+ }
+
+ // try to serve index file
+ if fi.IsDir() {
+ // redirect if missing trailing slash
+ if !strings.HasSuffix(req.URL.Path, "/") {
+ dest := url.URL{
+ Path: req.URL.Path + "/",
+ RawQuery: req.URL.RawQuery,
+ Fragment: req.URL.Fragment,
+ }
+ http.Redirect(res, req, dest.String(), http.StatusFound)
+ return
+ }
+
+ file = path.Join(file, opt.IndexFile)
+ f, err = dir.Open(file)
+ if err != nil {
+ return
+ }
+ defer f.Close()
+
+ fi, err = f.Stat()
+ if err != nil || fi.IsDir() {
+ return
+ }
+ }
+
+ if !opt.SkipLogging {
+ log.Println("[Static] Serving " + file)
+ }
+
+ // Add an Expires header to the static content
+ if opt.Expires != nil {
+ res.Header().Set("Expires", opt.Expires())
+ }
+
+ http.ServeContent(res, req, file, fi.ModTime(), f)
+ }
+}
diff --git a/src/vendor/github.com/julienschmidt/httprouter/LICENSE b/vendor/github.com/julienschmidt/httprouter/LICENSE
index b829abc..b829abc 100644
--- a/src/vendor/github.com/julienschmidt/httprouter/LICENSE
+++ b/vendor/github.com/julienschmidt/httprouter/LICENSE
diff --git a/src/vendor/github.com/julienschmidt/httprouter/path.go b/vendor/github.com/julienschmidt/httprouter/path.go
index 486134d..486134d 100644
--- a/src/vendor/github.com/julienschmidt/httprouter/path.go
+++ b/vendor/github.com/julienschmidt/httprouter/path.go
diff --git a/src/vendor/github.com/julienschmidt/httprouter/router.go b/vendor/github.com/julienschmidt/httprouter/router.go
index 8b5ff34..bb17330 100644
--- a/src/vendor/github.com/julienschmidt/httprouter/router.go
+++ b/vendor/github.com/julienschmidt/httprouter/router.go
@@ -138,6 +138,10 @@ type Router struct {
// handler.
HandleMethodNotAllowed bool
+ // If enabled, the router automatically replies to OPTIONS requests.
+ // Custom OPTIONS handlers take priority over automatic replies.
+ HandleOPTIONS bool
+
// Configurable http.Handler which is called when no matching route is
// found. If it is not set, http.NotFound is used.
NotFound http.Handler
@@ -145,6 +149,8 @@ type Router struct {
// Configurable http.Handler which is called when a request
// cannot be routed and HandleMethodNotAllowed is true.
// If it is not set, http.Error with http.StatusMethodNotAllowed is used.
+ // The "Allow" header with allowed request methods is set before the handler
+ // is called.
MethodNotAllowed http.Handler
// Function to handle panics recovered from http handlers.
@@ -165,6 +171,7 @@ func New() *Router {
RedirectTrailingSlash: true,
RedirectFixedPath: true,
HandleMethodNotAllowed: true,
+ HandleOPTIONS: true,
}
}
@@ -286,15 +293,53 @@ func (r *Router) Lookup(method, path string) (Handle, Params, bool) {
return nil, nil, false
}
+func (r *Router) allowed(path, reqMethod string) (allow string) {
+ if path == "*" { // server-wide
+ for method := range r.trees {
+ if method == "OPTIONS" {
+ continue
+ }
+
+ // add request method to list of allowed methods
+ if len(allow) == 0 {
+ allow = method
+ } else {
+ allow += ", " + method
+ }
+ }
+ } else { // specific path
+ for method := range r.trees {
+ // Skip the requested method - we already tried this one
+ if method == reqMethod || method == "OPTIONS" {
+ continue
+ }
+
+ handle, _, _ := r.trees[method].getValue(path)
+ if handle != nil {
+ // add request method to list of allowed methods
+ if len(allow) == 0 {
+ allow = method
+ } else {
+ allow += ", " + method
+ }
+ }
+ }
+ }
+ if len(allow) > 0 {
+ allow += ", OPTIONS"
+ }
+ return
+}
+
// ServeHTTP makes the router implement the http.Handler interface.
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if r.PanicHandler != nil {
defer r.recv(w, req)
}
- if root := r.trees[req.Method]; root != nil {
- path := req.URL.Path
+ path := req.URL.Path
+ if root := r.trees[req.Method]; root != nil {
if handle, ps, tsr := root.getValue(path); handle != nil {
handle(w, req, ps)
return
@@ -331,16 +376,19 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
}
- // Handle 405
- if r.HandleMethodNotAllowed {
- for method := range r.trees {
- // Skip the requested method - we already tried this one
- if method == req.Method {
- continue
+ if req.Method == "OPTIONS" {
+ // Handle OPTIONS requests
+ if r.HandleOPTIONS {
+ if allow := r.allowed(path, req.Method); len(allow) > 0 {
+ w.Header().Set("Allow", allow)
+ return
}
-
- handle, _, _ := r.trees[method].getValue(req.URL.Path)
- if handle != nil {
+ }
+ } else {
+ // Handle 405
+ if r.HandleMethodNotAllowed {
+ if allow := r.allowed(path, req.Method); len(allow) > 0 {
+ w.Header().Set("Allow", allow)
if r.MethodNotAllowed != nil {
r.MethodNotAllowed.ServeHTTP(w, req)
} else {
diff --git a/src/vendor/github.com/julienschmidt/httprouter/tree.go b/vendor/github.com/julienschmidt/httprouter/tree.go
index faf5fdc..474da00 100644
--- a/src/vendor/github.com/julienschmidt/httprouter/tree.go
+++ b/vendor/github.com/julienschmidt/httprouter/tree.go
@@ -7,6 +7,7 @@ package httprouter
import (
"strings"
"unicode"
+ "unicode/utf8"
)
func min(a, b int) int {
@@ -59,9 +60,7 @@ func (n *node) incrementChildPrio(pos int) int {
newPos := pos
for newPos > 0 && n.children[newPos-1].priority < prio {
// swap node positions
- tmpN := n.children[newPos-1]
- n.children[newPos-1] = n.children[newPos]
- n.children[newPos] = tmpN
+ n.children[newPos-1], n.children[newPos] = n.children[newPos], n.children[newPos-1]
newPos--
}
@@ -106,6 +105,7 @@ func (n *node) addRoute(path string, handle Handle) {
child := node{
path: n.path[i:],
wildChild: n.wildChild,
+ nType: static,
indices: n.indices,
children: n.children,
handle: n.handle,
@@ -142,16 +142,20 @@ func (n *node) addRoute(path string, handle Handle) {
numParams--
// Check if the wildcard matches
- if len(path) >= len(n.path) && n.path == path[:len(n.path)] {
- // check for longer wildcard, e.g. :name and :names
- if len(n.path) >= len(path) || path[len(n.path)] == '/' {
- continue walk
- }
+ if len(path) >= len(n.path) && n.path == path[:len(n.path)] &&
+ // Check for longer wildcard, e.g. :name and :names
+ (len(n.path) >= len(path) || path[len(n.path)] == '/') {
+ continue walk
+ } else {
+ // Wildcard conflict
+ pathSeg := strings.SplitN(path, "/", 2)[0]
+ prefix := fullPath[:strings.Index(fullPath, pathSeg)] + n.path
+ panic("'" + pathSeg +
+ "' in new path '" + fullPath +
+ "' conflicts with existing wildcard '" + n.path +
+ "' in existing prefix '" + prefix +
+ "'")
}
-
- panic("path segment '" + path +
- "' conflicts with existing wildcard '" + n.path +
- "' in path '" + fullPath + "'")
}
c := path[0]
@@ -319,7 +323,7 @@ func (n *node) insertChild(numParams uint8, path, fullPath string, handle Handle
// made if a handle exists with an extra (without the) trailing slash for the
// given path.
func (n *node) getValue(path string) (handle Handle, p Params, tsr bool) {
-walk: // Outer loop for walking the tree
+walk: // outer loop for walking the tree
for {
if len(path) > len(n.path) {
if path[:len(n.path)] == n.path {
@@ -446,34 +450,117 @@ walk: // Outer loop for walking the tree
// It returns the case-corrected path and a bool indicating whether the lookup
// was successful.
func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPath []byte, found bool) {
- ciPath = make([]byte, 0, len(path)+1) // preallocate enough memory
+ return n.findCaseInsensitivePathRec(
+ path,
+ strings.ToLower(path),
+ make([]byte, 0, len(path)+1), // preallocate enough memory for new path
+ [4]byte{}, // empty rune buffer
+ fixTrailingSlash,
+ )
+}
+
+// shift bytes in array by n bytes left
+func shiftNRuneBytes(rb [4]byte, n int) [4]byte {
+ switch n {
+ case 0:
+ return rb
+ case 1:
+ return [4]byte{rb[1], rb[2], rb[3], 0}
+ case 2:
+ return [4]byte{rb[2], rb[3]}
+ case 3:
+ return [4]byte{rb[3]}
+ default:
+ return [4]byte{}
+ }
+}
- // Outer loop for walking the tree
- for len(path) >= len(n.path) && strings.ToLower(path[:len(n.path)]) == strings.ToLower(n.path) {
- path = path[len(n.path):]
+// recursive case-insensitive lookup function used by n.findCaseInsensitivePath
+func (n *node) findCaseInsensitivePathRec(path, loPath string, ciPath []byte, rb [4]byte, fixTrailingSlash bool) ([]byte, bool) {
+ loNPath := strings.ToLower(n.path)
+
+walk: // outer loop for walking the tree
+ for len(loPath) >= len(loNPath) && (len(loNPath) == 0 || loPath[1:len(loNPath)] == loNPath[1:]) {
+ // add common path to result
ciPath = append(ciPath, n.path...)
- if len(path) > 0 {
+ if path = path[len(n.path):]; len(path) > 0 {
+ loOld := loPath
+ loPath = loPath[len(loNPath):]
+
// If this node does not have a wildcard (param or catchAll) child,
// we can just look up the next child node and continue to walk down
// the tree
if !n.wildChild {
- r := unicode.ToLower(rune(path[0]))
- for i, index := range n.indices {
- // must use recursive approach since both index and
- // ToLower(index) could exist. We must check both.
- if r == unicode.ToLower(index) {
- out, found := n.children[i].findCaseInsensitivePath(path, fixTrailingSlash)
- if found {
- return append(ciPath, out...), true
+ // skip rune bytes already processed
+ rb = shiftNRuneBytes(rb, len(loNPath))
+
+ if rb[0] != 0 {
+ // old rune not finished
+ for i := 0; i < len(n.indices); i++ {
+ if n.indices[i] == rb[0] {
+ // continue with child node
+ n = n.children[i]
+ loNPath = strings.ToLower(n.path)
+ continue walk
+ }
+ }
+ } else {
+ // process a new rune
+ var rv rune
+
+ // find rune start
+ // runes are up to 4 byte long,
+ // -4 would definitely be another rune
+ var off int
+ for max := min(len(loNPath), 3); off < max; off++ {
+ if i := len(loNPath) - off; utf8.RuneStart(loOld[i]) {
+ // read rune from cached lowercase path
+ rv, _ = utf8.DecodeRuneInString(loOld[i:])
+ break
+ }
+ }
+
+ // calculate lowercase bytes of current rune
+ utf8.EncodeRune(rb[:], rv)
+ // skipp already processed bytes
+ rb = shiftNRuneBytes(rb, off)
+
+ for i := 0; i < len(n.indices); i++ {
+ // lowercase matches
+ if n.indices[i] == rb[0] {
+ // must use a recursive approach since both the
+ // uppercase byte and the lowercase byte might exist
+ // as an index
+ if out, found := n.children[i].findCaseInsensitivePathRec(
+ path, loPath, ciPath, rb, fixTrailingSlash,
+ ); found {
+ return out, true
+ }
+ break
+ }
+ }
+
+ // same for uppercase rune, if it differs
+ if up := unicode.ToUpper(rv); up != rv {
+ utf8.EncodeRune(rb[:], up)
+ rb = shiftNRuneBytes(rb, off)
+
+ for i := 0; i < len(n.indices); i++ {
+ // uppercase matches
+ if n.indices[i] == rb[0] {
+ // continue with child node
+ n = n.children[i]
+ loNPath = strings.ToLower(n.path)
+ continue walk
+ }
}
}
}
// Nothing found. We can recommend to redirect to the same URL
// without a trailing slash if a leaf exists for that path
- found = (fixTrailingSlash && path == "/" && n.handle != nil)
- return
+ return ciPath, (fixTrailingSlash && path == "/" && n.handle != nil)
}
n = n.children[0]
@@ -491,8 +578,11 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
// we need to go deeper!
if k < len(path) {
if len(n.children) > 0 {
- path = path[k:]
+ // continue with child node
n = n.children[0]
+ loNPath = strings.ToLower(n.path)
+ loPath = loPath[k:]
+ path = path[k:]
continue
}
@@ -500,7 +590,7 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
if fixTrailingSlash && len(path) == k+1 {
return ciPath, true
}
- return
+ return ciPath, false
}
if n.handle != nil {
@@ -513,7 +603,7 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
return append(ciPath, '/'), true
}
}
- return
+ return ciPath, false
case catchAll:
return append(ciPath, path...), true
@@ -538,11 +628,11 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
(n.nType == catchAll && n.children[0].handle != nil) {
return append(ciPath, '/'), true
}
- return
+ return ciPath, false
}
}
}
- return
+ return ciPath, false
}
}
@@ -552,11 +642,10 @@ func (n *node) findCaseInsensitivePath(path string, fixTrailingSlash bool) (ciPa
if path == "/" {
return ciPath, true
}
- if len(path)+1 == len(n.path) && n.path[len(path)] == '/' &&
- strings.ToLower(path) == strings.ToLower(n.path[:len(path)]) &&
- n.handle != nil {
+ if len(loPath)+1 == len(loNPath) && loNPath[len(loPath)] == '/' &&
+ loPath[1:] == loNPath[1:len(loPath)] && n.handle != nil {
return append(ciPath, n.path...), true
}
}
- return
+ return ciPath, false
}
diff --git a/src/vendor/github.com/justinas/alice/LICENSE b/vendor/github.com/justinas/alice/LICENSE
index 0d0d352..0d0d352 100644
--- a/src/vendor/github.com/justinas/alice/LICENSE
+++ b/vendor/github.com/justinas/alice/LICENSE
diff --git a/src/vendor/github.com/justinas/alice/chain.go b/vendor/github.com/justinas/alice/chain.go
index d281ad3..da0e2b5 100644
--- a/src/vendor/github.com/justinas/alice/chain.go
+++ b/vendor/github.com/justinas/alice/chain.go
@@ -21,10 +21,7 @@ type Chain struct {
// New serves no other function,
// constructors are only called upon a call to Then().
func New(constructors ...Constructor) Chain {
- c := Chain{}
- c.constructors = append(c.constructors, constructors...)
-
- return c
+ return Chain{append(([]Constructor)(nil), constructors...)}
}
// Then chains the middleware and returns the final http.Handler.
@@ -46,18 +43,15 @@ func New(constructors ...Constructor) Chain {
//
// Then() treats nil as http.DefaultServeMux.
func (c Chain) Then(h http.Handler) http.Handler {
- var final http.Handler
- if h != nil {
- final = h
- } else {
- final = http.DefaultServeMux
+ if h == nil {
+ h = http.DefaultServeMux
}
- for i := len(c.constructors) - 1; i >= 0; i-- {
- final = c.constructors[i](final)
+ for i := range c.constructors {
+ h = c.constructors[len(c.constructors)-1-i](h)
}
- return final
+ return h
}
// ThenFunc works identically to Then, but takes
@@ -72,7 +66,7 @@ func (c Chain) ThenFunc(fn http.HandlerFunc) http.Handler {
if fn == nil {
return c.Then(nil)
}
- return c.Then(http.HandlerFunc(fn))
+ return c.Then(fn)
}
// Append extends a chain, adding the specified constructors
@@ -85,12 +79,11 @@ func (c Chain) ThenFunc(fn http.HandlerFunc) http.Handler {
// // requests in stdChain go m1 -> m2
// // requests in extChain go m1 -> m2 -> m3 -> m4
func (c Chain) Append(constructors ...Constructor) Chain {
- newCons := make([]Constructor, len(c.constructors)+len(constructors))
- copy(newCons, c.constructors)
- copy(newCons[len(c.constructors):], constructors)
+ newCons := make([]Constructor, 0, len(c.constructors)+len(constructors))
+ newCons = append(newCons, c.constructors...)
+ newCons = append(newCons, constructors...)
- newChain := New(newCons...)
- return newChain
+ return Chain{newCons}
}
// Extend extends a chain by adding the specified chain
diff --git a/vendor/github.com/martini-contrib/render/LICENSE b/vendor/github.com/martini-contrib/render/LICENSE
new file mode 100644
index 0000000..eb68a0e
--- /dev/null
+++ b/vendor/github.com/martini-contrib/render/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013 Jeremy Saenz
+
+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/martini-contrib/render/render.go b/vendor/github.com/martini-contrib/render/render.go
new file mode 100644
index 0000000..0cacb97
--- /dev/null
+++ b/vendor/github.com/martini-contrib/render/render.go
@@ -0,0 +1,386 @@
+// Package render is a middleware for Martini that provides easy JSON serialization and HTML template rendering.
+//
+// package main
+//
+// import (
+// "encoding/xml"
+//
+// "github.com/go-martini/martini"
+// "github.com/martini-contrib/render"
+// )
+//
+// type Greeting struct {
+// XMLName xml.Name `xml:"greeting"`
+// One string `xml:"one,attr"`
+// Two string `xml:"two,attr"`
+// }
+//
+// func main() {
+// m := martini.Classic()
+// m.Use(render.Renderer()) // reads "templates" directory by default
+//
+// m.Get("/html", func(r render.Render) {
+// r.HTML(200, "mytemplate", nil)
+// })
+//
+// m.Get("/json", func(r render.Render) {
+// r.JSON(200, "hello world")
+// })
+//
+// m.Get("/xml", func(r render.Render) {
+// r.XML(200, Greeting{One: "hello", Two: "world"})
+// })
+//
+// m.Run()
+// }
+package render
+
+import (
+ "bytes"
+ "encoding/json"
+ "encoding/xml"
+ "fmt"
+ "html/template"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/oxtoacart/bpool"
+
+ "github.com/go-martini/martini"
+)
+
+const (
+ ContentType = "Content-Type"
+ ContentLength = "Content-Length"
+ ContentBinary = "application/octet-stream"
+ ContentText = "text/plain"
+ ContentJSON = "application/json"
+ ContentHTML = "text/html"
+ ContentXHTML = "application/xhtml+xml"
+ ContentXML = "text/xml"
+ defaultCharset = "UTF-8"
+)
+
+// Provides a temporary buffer to execute templates into and catch errors.
+var bufpool *bpool.BufferPool
+
+// Included helper functions for use when rendering html
+var helperFuncs = template.FuncMap{
+ "yield": func() (string, error) {
+ return "", fmt.Errorf("yield called with no layout defined")
+ },
+ "current": func() (string, error) {
+ return "", nil
+ },
+}
+
+// Render is a service that can be injected into a Martini handler. Render provides functions for easily writing JSON and
+// HTML templates out to a http Response.
+type Render interface {
+ // JSON writes the given status and JSON serialized version of the given value to the http.ResponseWriter.
+ JSON(status int, v interface{})
+ // HTML renders a html template specified by the name and writes the result and given status to the http.ResponseWriter.
+ HTML(status int, name string, v interface{}, htmlOpt ...HTMLOptions)
+ // XML writes the given status and XML serialized version of the given value to the http.ResponseWriter.
+ XML(status int, v interface{})
+ // Data writes the raw byte array to the http.ResponseWriter.
+ Data(status int, v []byte)
+ // Text writes the given status and plain text to the http.ResponseWriter.
+ Text(status int, v string)
+ // Error is a convenience function that writes an http status to the http.ResponseWriter.
+ Error(status int)
+ // Status is an alias for Error (writes an http status to the http.ResponseWriter)
+ Status(status int)
+ // Redirect is a convienience function that sends an HTTP redirect. If status is omitted, uses 302 (Found)
+ Redirect(location string, status ...int)
+ // Template returns the internal *template.Template used to render the HTML
+ Template() *template.Template
+ // Header exposes the header struct from http.ResponseWriter.
+ Header() http.Header
+}
+
+// Delims represents a set of Left and Right delimiters for HTML template rendering
+type Delims struct {
+ // Left delimiter, defaults to {{
+ Left string
+ // Right delimiter, defaults to }}
+ Right string
+}
+
+// Options is a struct for specifying configuration options for the render.Renderer middleware
+type Options struct {
+ // Directory to load templates. Default is "templates"
+ Directory string
+ // Layout template name. Will not render a layout if "". Defaults to "".
+ Layout string
+ // Extensions to parse template files from. Defaults to [".tmpl"]
+ Extensions []string
+ // Funcs is a slice of FuncMaps to apply to the template upon compilation. This is useful for helper functions. Defaults to [].
+ Funcs []template.FuncMap
+ // Delims sets the action delimiters to the specified strings in the Delims struct.
+ Delims Delims
+ // Appends the given charset to the Content-Type header. Default is "UTF-8".
+ Charset string
+ // Outputs human readable JSON
+ IndentJSON bool
+ // Outputs human readable XML
+ IndentXML bool
+ // Prefixes the JSON output with the given bytes.
+ PrefixJSON []byte
+ // Prefixes the XML output with the given bytes.
+ PrefixXML []byte
+ // Allows changing of output to XHTML instead of HTML. Default is "text/html"
+ HTMLContentType string
+}
+
+// HTMLOptions is a struct for overriding some rendering Options for specific HTML call
+type HTMLOptions struct {
+ // Layout template name. Overrides Options.Layout.
+ Layout string
+}
+
+// Renderer is a Middleware that maps a render.Render service into the Martini handler chain. An single variadic render.Options
+// struct can be optionally provided to configure HTML rendering. The default directory for templates is "templates" and the default
+// file extension is ".tmpl".
+//
+// If MARTINI_ENV is set to "" or "development" then templates will be recompiled on every request. For more performance, set the
+// MARTINI_ENV environment variable to "production"
+func Renderer(options ...Options) martini.Handler {
+ opt := prepareOptions(options)
+ cs := prepareCharset(opt.Charset)
+ t := compile(opt)
+ bufpool = bpool.NewBufferPool(64)
+ return func(res http.ResponseWriter, req *http.Request, c martini.Context) {
+ var tc *template.Template
+ if martini.Env == martini.Dev {
+ // recompile for easy development
+ tc = compile(opt)
+ } else {
+ // use a clone of the initial template
+ tc, _ = t.Clone()
+ }
+ c.MapTo(&renderer{res, req, tc, opt, cs}, (*Render)(nil))
+ }
+}
+
+func prepareCharset(charset string) string {
+ if len(charset) != 0 {
+ return "; charset=" + charset
+ }
+
+ return "; charset=" + defaultCharset
+}
+
+func prepareOptions(options []Options) Options {
+ var opt Options
+ if len(options) > 0 {
+ opt = options[0]
+ }
+
+ // Defaults
+ if len(opt.Directory) == 0 {
+ opt.Directory = "templates"
+ }
+ if len(opt.Extensions) == 0 {
+ opt.Extensions = []string{".tmpl"}
+ }
+ if len(opt.HTMLContentType) == 0 {
+ opt.HTMLContentType = ContentHTML
+ }
+
+ return opt
+}
+
+func compile(options Options) *template.Template {
+ dir := options.Directory
+ t := template.New(dir)
+ t.Delims(options.Delims.Left, options.Delims.Right)
+ // parse an initial template in case we don't have any
+ template.Must(t.Parse("Martini"))
+
+ filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
+ r, err := filepath.Rel(dir, path)
+ if err != nil {
+ return err
+ }
+
+ ext := getExt(r)
+
+ for _, extension := range options.Extensions {
+ if ext == extension {
+
+ buf, err := ioutil.ReadFile(path)
+ if err != nil {
+ panic(err)
+ }
+
+ name := (r[0 : len(r)-len(ext)])
+ tmpl := t.New(filepath.ToSlash(name))
+
+ // add our funcmaps
+ for _, funcs := range options.Funcs {
+ tmpl.Funcs(funcs)
+ }
+
+ // Bomb out if parse fails. We don't want any silent server starts.
+ template.Must(tmpl.Funcs(helperFuncs).Parse(string(buf)))
+ break
+ }
+ }
+
+ return nil
+ })
+
+ return t
+}
+
+func getExt(s string) string {
+ if strings.Index(s, ".") == -1 {
+ return ""
+ }
+ return "." + strings.Join(strings.Split(s, ".")[1:], ".")
+}
+
+type renderer struct {
+ http.ResponseWriter
+ req *http.Request
+ t *template.Template
+ opt Options
+ compiledCharset string
+}
+
+func (r *renderer) JSON(status int, v interface{}) {
+ var result []byte
+ var err error
+ if r.opt.IndentJSON {
+ result, err = json.MarshalIndent(v, "", " ")
+ } else {
+ result, err = json.Marshal(v)
+ }
+ if err != nil {
+ http.Error(r, err.Error(), 500)
+ return
+ }
+
+ // json rendered fine, write out the result
+ r.Header().Set(ContentType, ContentJSON+r.compiledCharset)
+ r.WriteHeader(status)
+ if len(r.opt.PrefixJSON) > 0 {
+ r.Write(r.opt.PrefixJSON)
+ }
+ r.Write(result)
+}
+
+func (r *renderer) HTML(status int, name string, binding interface{}, htmlOpt ...HTMLOptions) {
+ opt := r.prepareHTMLOptions(htmlOpt)
+ // assign a layout if there is one
+ if len(opt.Layout) > 0 {
+ r.addYield(name, binding)
+ name = opt.Layout
+ }
+
+ buf, err := r.execute(name, binding)
+ if err != nil {
+ http.Error(r, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // template rendered fine, write out the result
+ r.Header().Set(ContentType, r.opt.HTMLContentType+r.compiledCharset)
+ r.WriteHeader(status)
+ io.Copy(r, buf)
+ bufpool.Put(buf)
+}
+
+func (r *renderer) XML(status int, v interface{}) {
+ var result []byte
+ var err error
+ if r.opt.IndentXML {
+ result, err = xml.MarshalIndent(v, "", " ")
+ } else {
+ result, err = xml.Marshal(v)
+ }
+ if err != nil {
+ http.Error(r, err.Error(), 500)
+ return
+ }
+
+ // XML rendered fine, write out the result
+ r.Header().Set(ContentType, ContentXML+r.compiledCharset)
+ r.WriteHeader(status)
+ if len(r.opt.PrefixXML) > 0 {
+ r.Write(r.opt.PrefixXML)
+ }
+ r.Write(result)
+}
+
+func (r *renderer) Data(status int, v []byte) {
+ if r.Header().Get(ContentType) == "" {
+ r.Header().Set(ContentType, ContentBinary)
+ }
+ r.WriteHeader(status)
+ r.Write(v)
+}
+
+func (r *renderer) Text(status int, v string) {
+ if r.Header().Get(ContentType) == "" {
+ r.Header().Set(ContentType, ContentText+r.compiledCharset)
+ }
+ r.WriteHeader(status)
+ r.Write([]byte(v))
+}
+
+// Error writes the given HTTP status to the current ResponseWriter
+func (r *renderer) Error(status int) {
+ r.WriteHeader(status)
+}
+
+func (r *renderer) Status(status int) {
+ r.WriteHeader(status)
+}
+
+func (r *renderer) Redirect(location string, status ...int) {
+ code := http.StatusFound
+ if len(status) == 1 {
+ code = status[0]
+ }
+
+ http.Redirect(r, r.req, location, code)
+}
+
+func (r *renderer) Template() *template.Template {
+ return r.t
+}
+
+func (r *renderer) execute(name string, binding interface{}) (*bytes.Buffer, error) {
+ buf := bufpool.Get()
+ return buf, r.t.ExecuteTemplate(buf, name, binding)
+}
+
+func (r *renderer) addYield(name string, binding interface{}) {
+ funcs := template.FuncMap{
+ "yield": func() (template.HTML, error) {
+ buf, err := r.execute(name, binding)
+ // return safe html here since we are rendering our own template
+ return template.HTML(buf.String()), err
+ },
+ "current": func() (string, error) {
+ return name, nil
+ },
+ }
+ r.t.Funcs(funcs)
+}
+
+func (r *renderer) prepareHTMLOptions(htmlOpt []HTMLOptions) HTMLOptions {
+ if len(htmlOpt) > 0 {
+ return htmlOpt[0]
+ }
+
+ return HTMLOptions{
+ Layout: r.opt.Layout,
+ }
+}
diff --git a/vendor/github.com/oxtoacart/bpool/LICENSE b/vendor/github.com/oxtoacart/bpool/LICENSE
new file mode 100644
index 0000000..f94e97c
--- /dev/null
+++ b/vendor/github.com/oxtoacart/bpool/LICENSE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2014 Percy Wegmann
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/vendor/github.com/oxtoacart/bpool/bpool.go b/vendor/github.com/oxtoacart/bpool/bpool.go
new file mode 100644
index 0000000..6232a38
--- /dev/null
+++ b/vendor/github.com/oxtoacart/bpool/bpool.go
@@ -0,0 +1,6 @@
+/*
+Package bpool implements leaky pools of byte arrays and Buffers as bounded
+channels. It is based on the leaky buffer example from the Effective Go
+documentation: http://golang.org/doc/effective_go.html#leaky_buffer
+*/
+package bpool
diff --git a/vendor/github.com/oxtoacart/bpool/bufferpool.go b/vendor/github.com/oxtoacart/bpool/bufferpool.go
new file mode 100644
index 0000000..8c8ac64
--- /dev/null
+++ b/vendor/github.com/oxtoacart/bpool/bufferpool.go
@@ -0,0 +1,40 @@
+package bpool
+
+import (
+ "bytes"
+)
+
+// BufferPool implements a pool of bytes.Buffers in the form of a bounded
+// channel.
+type BufferPool struct {
+ c chan *bytes.Buffer
+}
+
+// NewBufferPool creates a new BufferPool bounded to the given size.
+func NewBufferPool(size int) (bp *BufferPool) {
+ return &BufferPool{
+ c: make(chan *bytes.Buffer, size),
+ }
+}
+
+// Get gets a Buffer from the BufferPool, or creates a new one if none are
+// available in the pool.
+func (bp *BufferPool) Get() (b *bytes.Buffer) {
+ select {
+ case b = <-bp.c:
+ // reuse existing buffer
+ default:
+ // create new buffer
+ b = bytes.NewBuffer([]byte{})
+ }
+ return
+}
+
+// Put returns the given Buffer to the BufferPool.
+func (bp *BufferPool) Put(b *bytes.Buffer) {
+ b.Reset()
+ select {
+ case bp.c <- b:
+ default: // Discard the buffer if the pool is full.
+ }
+}
diff --git a/vendor/github.com/oxtoacart/bpool/bytepool.go b/vendor/github.com/oxtoacart/bpool/bytepool.go
new file mode 100644
index 0000000..ef3898a
--- /dev/null
+++ b/vendor/github.com/oxtoacart/bpool/bytepool.go
@@ -0,0 +1,45 @@
+package bpool
+
+// BytePool implements a leaky pool of []byte in the form of a bounded
+// channel.
+type BytePool struct {
+ c chan []byte
+ w int
+}
+
+// NewBytePool creates a new BytePool bounded to the given maxSize, with new
+// byte arrays sized based on width.
+func NewBytePool(maxSize int, width int) (bp *BytePool) {
+ return &BytePool{
+ c: make(chan []byte, maxSize),
+ w: width,
+ }
+}
+
+// Get gets a []byte from the BytePool, or creates a new one if none are
+// available in the pool.
+func (bp *BytePool) Get() (b []byte) {
+ select {
+ case b = <-bp.c:
+ // reuse existing buffer
+ default:
+ // create new buffer
+ b = make([]byte, bp.w)
+ }
+ return
+}
+
+// Put returns the given Buffer to the BytePool.
+func (bp *BytePool) Put(b []byte) {
+ select {
+ case bp.c <- b:
+ // buffer went back into pool
+ default:
+ // buffer didn't go back into pool, just discard
+ }
+}
+
+// Width returns the width of the byte arrays in this pool.
+func (bp *BytePool) Width() (n int) {
+ return bp.w
+}
diff --git a/vendor/github.com/oxtoacart/bpool/sizedbufferpool.go b/vendor/github.com/oxtoacart/bpool/sizedbufferpool.go
new file mode 100644
index 0000000..8519aca
--- /dev/null
+++ b/vendor/github.com/oxtoacart/bpool/sizedbufferpool.go
@@ -0,0 +1,60 @@
+package bpool
+
+import (
+ "bytes"
+)
+
+// SizedBufferPool implements a pool of bytes.Buffers in the form of a bounded
+// channel. Buffers are pre-allocated to the requested size.
+type SizedBufferPool struct {
+ c chan *bytes.Buffer
+ a int
+}
+
+// SizedBufferPool creates a new BufferPool bounded to the given size.
+// size defines the number of buffers to be retained in the pool and alloc sets
+// the initial capacity of new buffers to minimize calls to make().
+//
+// The value of alloc should seek to provide a buffer that is representative of
+// most data written to the the buffer (i.e. 95th percentile) without being
+// overly large (which will increase static memory consumption). You may wish to
+// track the capacity of your last N buffers (i.e. using an []int) prior to
+// returning them to the pool as input into calculating a suitable alloc value.
+func NewSizedBufferPool(size int, alloc int) (bp *SizedBufferPool) {
+ return &SizedBufferPool{
+ c: make(chan *bytes.Buffer, size),
+ a: alloc,
+ }
+}
+
+// Get gets a Buffer from the SizedBufferPool, or creates a new one if none are
+// available in the pool. Buffers have a pre-allocated capacity.
+func (bp *SizedBufferPool) Get() (b *bytes.Buffer) {
+ select {
+ case b = <-bp.c:
+ // reuse existing buffer
+ default:
+ // create new buffer
+ b = bytes.NewBuffer(make([]byte, 0, bp.a))
+ }
+ return
+}
+
+// Put returns the given Buffer to the SizedBufferPool.
+func (bp *SizedBufferPool) Put(b *bytes.Buffer) {
+ b.Reset()
+
+ // Release buffers over our maximum capacity and re-create a pre-sized
+ // buffer to replace it.
+ // Note that the cap(b.Bytes()) provides the capacity from the read off-set
+ // only, but as we've called b.Reset() the full capacity of the underlying
+ // byte slice is returned.
+ if cap(b.Bytes()) > bp.a {
+ b = bytes.NewBuffer(make([]byte, 0, bp.a))
+ }
+
+ select {
+ case bp.c <- b:
+ default: // Discard the buffer if the pool is full.
+ }
+}
diff --git a/src/vendor/github.com/rs/cors/LICENSE b/vendor/github.com/rs/cors/LICENSE
index d8e2df5..d8e2df5 100644
--- a/src/vendor/github.com/rs/cors/LICENSE
+++ b/vendor/github.com/rs/cors/LICENSE
diff --git a/src/vendor/github.com/rs/cors/cors.go b/vendor/github.com/rs/cors/cors.go
index 6616061..4bb22d8 100644
--- a/src/vendor/github.com/rs/cors/cors.go
+++ b/vendor/github.com/rs/cors/cors.go
@@ -181,6 +181,8 @@ func (c *Cors) Handler(h http.Handler) http.Handler {
// headers (see #1)
if c.optionPassthrough {
h.ServeHTTP(w, r)
+ } else {
+ w.WriteHeader(http.StatusOK)
}
} else {
c.logf("Handler: Actual request")
@@ -202,6 +204,8 @@ func (c *Cors) HandlerC(h xhandler.HandlerC) xhandler.HandlerC {
// headers (see #1)
if c.optionPassthrough {
h.ServeHTTPC(ctx, w, r)
+ } else {
+ w.WriteHeader(http.StatusOK)
}
} else {
c.logf("Handler: Actual request")
@@ -233,6 +237,8 @@ func (c *Cors) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.Handl
// headers (see #1)
if c.optionPassthrough {
next(w, r)
+ } else {
+ w.WriteHeader(http.StatusOK)
}
} else {
c.logf("ServeHTTP: Actual request")
diff --git a/src/vendor/github.com/rs/cors/examples/alice/server.go b/vendor/github.com/rs/cors/examples/alice/server.go
index 0a3e15c..0a3e15c 100644
--- a/src/vendor/github.com/rs/cors/examples/alice/server.go
+++ b/vendor/github.com/rs/cors/examples/alice/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/default/server.go b/vendor/github.com/rs/cors/examples/default/server.go
index ccb5e1b..ccb5e1b 100644
--- a/src/vendor/github.com/rs/cors/examples/default/server.go
+++ b/vendor/github.com/rs/cors/examples/default/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/goji/server.go b/vendor/github.com/rs/cors/examples/goji/server.go
index 1fb4073..1fb4073 100644
--- a/src/vendor/github.com/rs/cors/examples/goji/server.go
+++ b/vendor/github.com/rs/cors/examples/goji/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/martini/server.go b/vendor/github.com/rs/cors/examples/martini/server.go
index 081af32..081af32 100644
--- a/src/vendor/github.com/rs/cors/examples/martini/server.go
+++ b/vendor/github.com/rs/cors/examples/martini/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/negroni/server.go b/vendor/github.com/rs/cors/examples/negroni/server.go
index 3cb33bf..3cb33bf 100644
--- a/src/vendor/github.com/rs/cors/examples/negroni/server.go
+++ b/vendor/github.com/rs/cors/examples/negroni/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/nethttp/server.go b/vendor/github.com/rs/cors/examples/nethttp/server.go
index eaa775e..eaa775e 100644
--- a/src/vendor/github.com/rs/cors/examples/nethttp/server.go
+++ b/vendor/github.com/rs/cors/examples/nethttp/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/openbar/server.go b/vendor/github.com/rs/cors/examples/openbar/server.go
index 0940423..0940423 100644
--- a/src/vendor/github.com/rs/cors/examples/openbar/server.go
+++ b/vendor/github.com/rs/cors/examples/openbar/server.go
diff --git a/src/vendor/github.com/rs/cors/examples/xhandler/server.go b/vendor/github.com/rs/cors/examples/xhandler/server.go
index 649a1c7..649a1c7 100644
--- a/src/vendor/github.com/rs/cors/examples/xhandler/server.go
+++ b/vendor/github.com/rs/cors/examples/xhandler/server.go
diff --git a/src/vendor/github.com/rs/cors/utils.go b/vendor/github.com/rs/cors/utils.go
index cd24831..c7a0aa0 100644
--- a/src/vendor/github.com/rs/cors/utils.go
+++ b/vendor/github.com/rs/cors/utils.go
@@ -51,7 +51,7 @@ func parseHeaderList(headerList string) []string {
} else {
h = append(h, b)
}
- } else if b == '-' || (b >= '0' && b <= '9') {
+ } else if b == '-' || b == '_' || (b >= '0' && b <= '9') {
h = append(h, b)
}
@@ -63,7 +63,7 @@ func parseHeaderList(headerList string) []string {
upper = true
}
} else {
- upper = b == '-'
+ upper = b == '-' || b == '_'
}
}
return headers
diff --git a/src/vendor/github.com/rs/xhandler/LICENSE b/vendor/github.com/rs/xhandler/LICENSE
index 47c5e9d..47c5e9d 100644
--- a/src/vendor/github.com/rs/xhandler/LICENSE
+++ b/vendor/github.com/rs/xhandler/LICENSE
diff --git a/src/vendor/github.com/rs/xhandler/chain.go b/vendor/github.com/rs/xhandler/chain.go
index 042274d..3e4bd35 100644
--- a/src/vendor/github.com/rs/xhandler/chain.go
+++ b/vendor/github.com/rs/xhandler/chain.go
@@ -6,19 +6,47 @@ import (
"golang.org/x/net/context"
)
-// Chain is an helper to chain middleware handlers together for an easier
+// Chain is a helper for chaining middleware handlers together for easier
// management.
type Chain []func(next HandlerC) HandlerC
+// Add appends a variable number of additional middleware handlers
+// to the middleware chain. Middleware handlers can either be
+// context-aware or non-context aware handlers with the appropriate
+// function signatures.
+func (c *Chain) Add(f ...interface{}) {
+ for _, h := range f {
+ switch v := h.(type) {
+ case func(http.Handler) http.Handler:
+ c.Use(v)
+ case func(HandlerC) HandlerC:
+ c.UseC(v)
+ default:
+ panic("Adding invalid handler to the middleware chain")
+ }
+ }
+}
+
+// With creates a new middleware chain from an existing chain,
+// extending it with additional middleware. Middleware handlers
+// can either be context-aware or non-context aware handlers
+// with the appropriate function signatures.
+func (c *Chain) With(f ...interface{}) *Chain {
+ n := make(Chain, len(*c))
+ copy(n, *c)
+ n.Add(f...)
+ return &n
+}
+
// UseC appends a context-aware handler to the middleware chain.
func (c *Chain) UseC(f func(next HandlerC) HandlerC) {
*c = append(*c, f)
}
// Use appends a standard http.Handler to the middleware chain without
-// lossing track of the context when inserted between two context aware handlers.
+// losing track of the context when inserted between two context aware handlers.
//
-// Caveat: the f function will be called on each request so you are better to put
+// Caveat: the f function will be called on each request so you are better off putting
// any initialization sequence outside of this function.
func (c *Chain) Use(f func(next http.Handler) http.Handler) {
xf := func(next HandlerC) HandlerC {
@@ -33,14 +61,14 @@ func (c *Chain) Use(f func(next http.Handler) http.Handler) {
}
// Handler wraps the provided final handler with all the middleware appended to
-// the chain and return a new standard http.Handler instance.
+// the chain and returns a new standard http.Handler instance.
// The context.Background() context is injected automatically.
func (c Chain) Handler(xh HandlerC) http.Handler {
ctx := context.Background()
return c.HandlerCtx(ctx, xh)
}
-// HandlerFC is an helper to provide a function (HandlerFuncC) to Handler().
+// HandlerFC is a helper to provide a function (HandlerFuncC) to Handler().
//
// HandlerFC is equivalent to:
// c.Handler(xhandler.HandlerFuncC(xhc))
@@ -49,8 +77,8 @@ func (c Chain) HandlerFC(xhf HandlerFuncC) http.Handler {
return c.HandlerCtx(ctx, HandlerFuncC(xhf))
}
-// HandlerH is an helper to provide a standard http handler (http.HandlerFunc)
-// to Handler(). Your final handler won't have access the context though.
+// HandlerH is a helper to provide a standard http handler (http.HandlerFunc)
+// to Handler(). Your final handler won't have access to the context though.
func (c Chain) HandlerH(h http.Handler) http.Handler {
ctx := context.Background()
return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
@@ -58,9 +86,9 @@ func (c Chain) HandlerH(h http.Handler) http.Handler {
}))
}
-// HandlerF is an helper to provide a standard http handler function
+// HandlerF is a helper to provide a standard http handler function
// (http.HandlerFunc) to Handler(). Your final handler won't have access
-// the context though.
+// to the context though.
func (c Chain) HandlerF(hf http.HandlerFunc) http.Handler {
ctx := context.Background()
return c.HandlerCtx(ctx, HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
@@ -69,7 +97,7 @@ func (c Chain) HandlerF(hf http.HandlerFunc) http.Handler {
}
// HandlerCtx wraps the provided final handler with all the middleware appended to
-// the chain and return a new standard http.Handler instance.
+// the chain and returns a new standard http.Handler instance.
func (c Chain) HandlerCtx(ctx context.Context, xh HandlerC) http.Handler {
return New(ctx, c.HandlerC(xh))
}
diff --git a/src/vendor/github.com/rs/xhandler/middleware.go b/vendor/github.com/rs/xhandler/middleware.go
index 5de1364..7ad8fba 100644
--- a/src/vendor/github.com/rs/xhandler/middleware.go
+++ b/vendor/github.com/rs/xhandler/middleware.go
@@ -7,8 +7,8 @@ import (
"golang.org/x/net/context"
)
-// CloseHandler returns a Handler cancelling the context when the client
-// connection close unexpectedly.
+// CloseHandler returns a Handler, cancelling the context when the client
+// connection closes unexpectedly.
func CloseHandler(next HandlerC) HandlerC {
return HandlerFuncC(func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
// Cancel the context if the client closes the connection
@@ -33,7 +33,7 @@ func CloseHandler(next HandlerC) HandlerC {
// TimeoutHandler returns a Handler which adds a timeout to the context.
//
-// Child handlers have the responsability to obey the context deadline and to return
+// Child handlers have the responsability of obeying the context deadline and to return
// an appropriate error (or not) response in case of timeout.
func TimeoutHandler(timeout time.Duration) func(next HandlerC) HandlerC {
return func(next HandlerC) HandlerC {
diff --git a/src/vendor/github.com/rs/xhandler/xhandler.go b/vendor/github.com/rs/xhandler/xhandler.go
index 0dfcddf..bc832cb 100644
--- a/src/vendor/github.com/rs/xhandler/xhandler.go
+++ b/vendor/github.com/rs/xhandler/xhandler.go
@@ -8,7 +8,7 @@
// the connection unexpectedly.
//
// You may create net/context aware middlewares pretty much the same way as
-// you would do with http.Handler.
+// you would with http.Handler.
package xhandler // import "github.com/rs/xhandler"
import (
@@ -23,7 +23,7 @@ type HandlerC interface {
}
// HandlerFuncC type is an adapter to allow the use of ordinary functions
-// as a xhandler.Handler. If f is a function with the appropriate signature,
+// as an xhandler.Handler. If f is a function with the appropriate signature,
// xhandler.HandlerFuncC(f) is a xhandler.Handler object that calls f.
type HandlerFuncC func(context.Context, http.ResponseWriter, *http.Request)
diff --git a/src/vendor/github.com/stretchr/graceful/LICENSE b/vendor/github.com/stretchr/graceful/LICENSE
index a4f2f28..a4f2f28 100644
--- a/src/vendor/github.com/stretchr/graceful/LICENSE
+++ b/vendor/github.com/stretchr/graceful/LICENSE
diff --git a/vendor/github.com/stretchr/graceful/graceful.go b/vendor/github.com/stretchr/graceful/graceful.go
new file mode 100644
index 0000000..07c9904
--- /dev/null
+++ b/vendor/github.com/stretchr/graceful/graceful.go
@@ -0,0 +1,484 @@
+package graceful
+
+import (
+ "crypto/tls"
+ "log"
+ "net"
+ "net/http"
+ "os"
+ "sync"
+ "time"
+)
+
+// Server wraps an http.Server with graceful connection handling.
+// It may be used directly in the same way as http.Server, or may
+// be constructed with the global functions in this package.
+//
+// Example:
+// srv := &graceful.Server{
+// Timeout: 5 * time.Second,
+// Server: &http.Server{Addr: ":1234", Handler: handler},
+// }
+// srv.ListenAndServe()
+type Server struct {
+ *http.Server
+
+ // Timeout is the duration to allow outstanding requests to survive
+ // before forcefully terminating them.
+ Timeout time.Duration
+
+ // Limit the number of outstanding requests
+ ListenLimit int
+
+ // TCPKeepAlive sets the TCP keep-alive timeouts on accepted
+ // connections. It prunes dead TCP connections ( e.g. closing
+ // laptop mid-download)
+ TCPKeepAlive time.Duration
+
+ // ConnState specifies an optional callback function that is
+ // called when a client connection changes state. This is a proxy
+ // to the underlying http.Server's ConnState, and the original
+ // must not be set directly.
+ ConnState func(net.Conn, http.ConnState)
+
+ // BeforeShutdown is an optional callback function that is called
+ // before the listener is closed. Returns true if shutdown is allowed
+ BeforeShutdown func() bool
+
+ // ShutdownInitiated is an optional callback function that is called
+ // when shutdown is initiated. It can be used to notify the client
+ // side of long lived connections (e.g. websockets) to reconnect.
+ ShutdownInitiated func()
+
+ // NoSignalHandling prevents graceful from automatically shutting down
+ // on SIGINT and SIGTERM. If set to true, you must shut down the server
+ // manually with Stop().
+ NoSignalHandling bool
+
+ // Logger used to notify of errors on startup and on stop.
+ Logger *log.Logger
+
+ // LogFunc can be assigned with a logging function of your choice, allowing
+ // you to use whatever logging approach you would like
+ LogFunc func(format string, args ...interface{})
+
+ // Interrupted is true if the server is handling a SIGINT or SIGTERM
+ // signal and is thus shutting down.
+ Interrupted bool
+
+ // interrupt signals the listener to stop serving connections,
+ // and the server to shut down.
+ interrupt chan os.Signal
+
+ // stopLock is used to protect against concurrent calls to Stop
+ stopLock sync.Mutex
+
+ // stopChan is the channel on which callers may block while waiting for
+ // the server to stop.
+ stopChan chan struct{}
+
+ // chanLock is used to protect access to the various channel constructors.
+ chanLock sync.RWMutex
+
+ // connections holds all connections managed by graceful
+ connections map[net.Conn]struct{}
+
+ // idleConnections holds all idle connections managed by graceful
+ idleConnections map[net.Conn]struct{}
+}
+
+// Run serves the http.Handler with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func Run(addr string, timeout time.Duration, n http.Handler) {
+ srv := &Server{
+ Timeout: timeout,
+ TCPKeepAlive: 3 * time.Minute,
+ Server: &http.Server{Addr: addr, Handler: n},
+ // Logger: DefaultLogger(),
+ }
+
+ if err := srv.ListenAndServe(); err != nil {
+ if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
+ srv.logf("%s", err)
+ os.Exit(1)
+ }
+ }
+
+}
+
+// RunWithErr is an alternative version of Run function which can return error.
+//
+// Unlike Run this version will not exit the program if an error is encountered but will
+// return it instead.
+func RunWithErr(addr string, timeout time.Duration, n http.Handler) error {
+ srv := &Server{
+ Timeout: timeout,
+ TCPKeepAlive: 3 * time.Minute,
+ Server: &http.Server{Addr: addr, Handler: n},
+ Logger: DefaultLogger(),
+ }
+
+ return srv.ListenAndServe()
+}
+
+// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func ListenAndServe(server *http.Server, timeout time.Duration) error {
+ srv := &Server{Timeout: timeout, Server: server, Logger: DefaultLogger()}
+ return srv.ListenAndServe()
+}
+
+// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled.
+func (srv *Server) ListenAndServe() error {
+ // Create the listener so we can control their lifetime
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":http"
+ }
+ conn, err := srv.newTCPListener(addr)
+ if err != nil {
+ return err
+ }
+
+ return srv.Serve(conn)
+}
+
+// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func ListenAndServeTLS(server *http.Server, certFile, keyFile string, timeout time.Duration) error {
+ srv := &Server{Timeout: timeout, Server: server, Logger: DefaultLogger()}
+ return srv.ListenAndServeTLS(certFile, keyFile)
+}
+
+// ListenTLS is a convenience method that creates an https listener using the
+// provided cert and key files. Use this method if you need access to the
+// listener object directly. When ready, pass it to the Serve method.
+func (srv *Server) ListenTLS(certFile, keyFile string) (net.Listener, error) {
+ // Create the listener ourselves so we can control its lifetime
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":https"
+ }
+
+ config := &tls.Config{}
+ if srv.TLSConfig != nil {
+ *config = *srv.TLSConfig
+ }
+
+ var err error
+ config.Certificates = make([]tls.Certificate, 1)
+ config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return nil, err
+ }
+
+ // Enable http2
+ enableHTTP2ForTLSConfig(config)
+
+ conn, err := srv.newTCPListener(addr)
+ if err != nil {
+ return nil, err
+ }
+
+ srv.TLSConfig = config
+
+ tlsListener := tls.NewListener(conn, config)
+ return tlsListener, nil
+}
+
+// Enable HTTP2ForTLSConfig explicitly enables http/2 for a TLS Config. This is due to changes in Go 1.7 where
+// http servers are no longer automatically configured to enable http/2 if the server's TLSConfig is set.
+// See https://github.com/golang/go/issues/15908
+func enableHTTP2ForTLSConfig(t *tls.Config) {
+
+ if TLSConfigHasHTTP2Enabled(t) {
+ return
+ }
+
+ t.NextProtos = append(t.NextProtos, "h2")
+}
+
+// TLSConfigHasHTTP2Enabled checks to see if a given TLS Config has http2 enabled.
+func TLSConfigHasHTTP2Enabled(t *tls.Config) bool {
+ for _, value := range t.NextProtos {
+ if value == "h2" {
+ return true
+ }
+ }
+ return false
+}
+
+// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled.
+func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
+ l, err := srv.ListenTLS(certFile, keyFile)
+ if err != nil {
+ return err
+ }
+
+ return srv.Serve(l)
+}
+
+// ListenAndServeTLSConfig can be used with an existing TLS config and is equivalent to
+// http.Server.ListenAndServeTLS with graceful shutdown enabled,
+func (srv *Server) ListenAndServeTLSConfig(config *tls.Config) error {
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":https"
+ }
+
+ conn, err := srv.newTCPListener(addr)
+ if err != nil {
+ return err
+ }
+
+ srv.TLSConfig = config
+
+ tlsListener := tls.NewListener(conn, config)
+ return srv.Serve(tlsListener)
+}
+
+// Serve is equivalent to http.Server.Serve with graceful shutdown enabled.
+//
+// timeout is the duration to wait until killing active requests and stopping the server.
+// If timeout is 0, the server never times out. It waits for all active requests to finish.
+func Serve(server *http.Server, l net.Listener, timeout time.Duration) error {
+ srv := &Server{Timeout: timeout, Server: server, Logger: DefaultLogger()}
+
+ return srv.Serve(l)
+}
+
+// Serve is equivalent to http.Server.Serve with graceful shutdown enabled.
+func (srv *Server) Serve(listener net.Listener) error {
+
+ if srv.ListenLimit != 0 {
+ listener = LimitListener(listener, srv.ListenLimit)
+ }
+
+ // Make our stopchan
+ srv.StopChan()
+
+ // Track connection state
+ add := make(chan net.Conn)
+ idle := make(chan net.Conn)
+ active := make(chan net.Conn)
+ remove := make(chan net.Conn)
+
+ srv.Server.ConnState = func(conn net.Conn, state http.ConnState) {
+ switch state {
+ case http.StateNew:
+ add <- conn
+ case http.StateActive:
+ active <- conn
+ case http.StateIdle:
+ idle <- conn
+ case http.StateClosed, http.StateHijacked:
+ remove <- conn
+ }
+
+ srv.stopLock.Lock()
+ defer srv.stopLock.Unlock()
+
+ if srv.ConnState != nil {
+ srv.ConnState(conn, state)
+ }
+ }
+
+ // Manage open connections
+ shutdown := make(chan chan struct{})
+ kill := make(chan struct{})
+ go srv.manageConnections(add, idle, active, remove, shutdown, kill)
+
+ interrupt := srv.interruptChan()
+ // Set up the interrupt handler
+ if !srv.NoSignalHandling {
+ signalNotify(interrupt)
+ }
+ quitting := make(chan struct{})
+ go srv.handleInterrupt(interrupt, quitting, listener)
+
+ // Serve with graceful listener.
+ // Execution blocks here until listener.Close() is called, above.
+ err := srv.Server.Serve(listener)
+ if err != nil {
+ // If the underlying listening is closed, Serve returns an error
+ // complaining about listening on a closed socket. This is expected, so
+ // let's ignore the error if we are the ones who explicitly closed the
+ // socket.
+ select {
+ case <-quitting:
+ err = nil
+ default:
+ }
+ }
+
+ srv.shutdown(shutdown, kill)
+
+ return err
+}
+
+// Stop instructs the type to halt operations and close
+// the stop channel when it is finished.
+//
+// timeout is grace period for which to wait before shutting
+// down the server. The timeout value passed here will override the
+// timeout given when constructing the server, as this is an explicit
+// command to stop the server.
+func (srv *Server) Stop(timeout time.Duration) {
+ srv.stopLock.Lock()
+ defer srv.stopLock.Unlock()
+
+ srv.Timeout = timeout
+ sendSignalInt(srv.interruptChan())
+}
+
+// StopChan gets the stop channel which will block until
+// stopping has completed, at which point it is closed.
+// Callers should never close the stop channel.
+func (srv *Server) StopChan() <-chan struct{} {
+ srv.chanLock.Lock()
+ defer srv.chanLock.Unlock()
+
+ if srv.stopChan == nil {
+ srv.stopChan = make(chan struct{})
+ }
+ return srv.stopChan
+}
+
+// DefaultLogger returns the logger used by Run, RunWithErr, ListenAndServe, ListenAndServeTLS and Serve.
+// The logger outputs to STDERR by default.
+func DefaultLogger() *log.Logger {
+ return log.New(os.Stderr, "[graceful] ", 0)
+}
+
+func (srv *Server) manageConnections(add, idle, active, remove chan net.Conn, shutdown chan chan struct{}, kill chan struct{}) {
+ var done chan struct{}
+ srv.connections = map[net.Conn]struct{}{}
+ srv.idleConnections = map[net.Conn]struct{}{}
+ for {
+ select {
+ case conn := <-add:
+ srv.connections[conn] = struct{}{}
+ case conn := <-idle:
+ srv.idleConnections[conn] = struct{}{}
+ case conn := <-active:
+ delete(srv.idleConnections, conn)
+ case conn := <-remove:
+ delete(srv.connections, conn)
+ delete(srv.idleConnections, conn)
+ if done != nil && len(srv.connections) == 0 {
+ done <- struct{}{}
+ return
+ }
+ case done = <-shutdown:
+ if len(srv.connections) == 0 && len(srv.idleConnections) == 0 {
+ done <- struct{}{}
+ return
+ }
+ // a shutdown request has been received. if we have open idle
+ // connections, we must close all of them now. this prevents idle
+ // connections from holding the server open while waiting for them to
+ // hit their idle timeout.
+ for k := range srv.idleConnections {
+ if err := k.Close(); err != nil {
+ srv.logf("[ERROR] %s", err)
+ }
+ }
+ case <-kill:
+ srv.stopLock.Lock()
+ defer srv.stopLock.Unlock()
+
+ srv.Server.ConnState = nil
+ for k := range srv.connections {
+ if err := k.Close(); err != nil {
+ srv.logf("[ERROR] %s", err)
+ }
+ }
+ return
+ }
+ }
+}
+
+func (srv *Server) interruptChan() chan os.Signal {
+ srv.chanLock.Lock()
+ defer srv.chanLock.Unlock()
+
+ if srv.interrupt == nil {
+ srv.interrupt = make(chan os.Signal, 1)
+ }
+
+ return srv.interrupt
+}
+
+func (srv *Server) handleInterrupt(interrupt chan os.Signal, quitting chan struct{}, listener net.Listener) {
+ for _ = range interrupt {
+ if srv.Interrupted {
+ srv.logf("already shutting down")
+ continue
+ }
+ srv.logf("shutdown initiated")
+ srv.Interrupted = true
+ if srv.BeforeShutdown != nil {
+ if !srv.BeforeShutdown() {
+ srv.Interrupted = false
+ continue
+ }
+ }
+
+ close(quitting)
+ srv.SetKeepAlivesEnabled(false)
+ if err := listener.Close(); err != nil {
+ srv.logf("[ERROR] %s", err)
+ }
+
+ if srv.ShutdownInitiated != nil {
+ srv.ShutdownInitiated()
+ }
+ }
+}
+
+func (srv *Server) logf(format string, args ...interface{}) {
+ if srv.LogFunc != nil {
+ srv.LogFunc(format, args...)
+ } else if srv.Logger != nil {
+ srv.Logger.Printf(format, args...)
+ }
+}
+
+func (srv *Server) shutdown(shutdown chan chan struct{}, kill chan struct{}) {
+ // Request done notification
+ done := make(chan struct{})
+ shutdown <- done
+
+ if srv.Timeout > 0 {
+ select {
+ case <-done:
+ case <-time.After(srv.Timeout):
+ close(kill)
+ }
+ } else {
+ <-done
+ }
+ // Close the stopChan to wake up any blocked goroutines.
+ srv.chanLock.Lock()
+ if srv.stopChan != nil {
+ close(srv.stopChan)
+ }
+ srv.chanLock.Unlock()
+}
+
+func (srv *Server) newTCPListener(addr string) (net.Listener, error) {
+ conn, err := net.Listen("tcp", addr)
+ if err != nil {
+ return conn, err
+ }
+ if srv.TCPKeepAlive != 0 {
+ conn = keepAliveListener{conn, srv.TCPKeepAlive}
+ }
+ return conn, nil
+}
diff --git a/vendor/github.com/stretchr/graceful/keepalive_listener.go b/vendor/github.com/stretchr/graceful/keepalive_listener.go
new file mode 100644
index 0000000..1484bc2
--- /dev/null
+++ b/vendor/github.com/stretchr/graceful/keepalive_listener.go
@@ -0,0 +1,32 @@
+package graceful
+
+import (
+ "net"
+ "time"
+)
+
+type keepAliveConn interface {
+ SetKeepAlive(bool) error
+ SetKeepAlivePeriod(d time.Duration) error
+}
+
+// keepAliveListener sets TCP keep-alive timeouts on accepted
+// connections. It's used by ListenAndServe and ListenAndServeTLS so
+// dead TCP connections (e.g. closing laptop mid-download) eventually
+// go away.
+type keepAliveListener struct {
+ net.Listener
+ keepAlivePeriod time.Duration
+}
+
+func (ln keepAliveListener) Accept() (net.Conn, error) {
+ c, err := ln.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+
+ kac := c.(keepAliveConn)
+ kac.SetKeepAlive(true)
+ kac.SetKeepAlivePeriod(ln.keepAlivePeriod)
+ return c, nil
+}
diff --git a/vendor/github.com/stretchr/graceful/limit_listen.go b/vendor/github.com/stretchr/graceful/limit_listen.go
new file mode 100644
index 0000000..ce32ce9
--- /dev/null
+++ b/vendor/github.com/stretchr/graceful/limit_listen.go
@@ -0,0 +1,77 @@
+// Copyright 2013 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package graceful
+
+import (
+ "errors"
+ "net"
+ "sync"
+ "time"
+)
+
+// ErrNotTCP indicates that network connection is not a TCP connection.
+var ErrNotTCP = errors.New("only tcp connections have keepalive")
+
+// LimitListener returns a Listener that accepts at most n simultaneous
+// connections from the provided Listener.
+func LimitListener(l net.Listener, n int) net.Listener {
+ return &limitListener{l, make(chan struct{}, n)}
+}
+
+type limitListener struct {
+ net.Listener
+ sem chan struct{}
+}
+
+func (l *limitListener) acquire() { l.sem <- struct{}{} }
+func (l *limitListener) release() { <-l.sem }
+
+func (l *limitListener) Accept() (net.Conn, error) {
+ l.acquire()
+ c, err := l.Listener.Accept()
+ if err != nil {
+ l.release()
+ return nil, err
+ }
+ return &limitListenerConn{Conn: c, release: l.release}, nil
+}
+
+type limitListenerConn struct {
+ net.Conn
+ releaseOnce sync.Once
+ release func()
+}
+
+func (l *limitListenerConn) Close() error {
+ err := l.Conn.Close()
+ l.releaseOnce.Do(l.release)
+ return err
+}
+
+func (l *limitListenerConn) SetKeepAlive(doKeepAlive bool) error {
+ tcpc, ok := l.Conn.(*net.TCPConn)
+ if !ok {
+ return ErrNotTCP
+ }
+ return tcpc.SetKeepAlive(doKeepAlive)
+}
+
+func (l *limitListenerConn) SetKeepAlivePeriod(d time.Duration) error {
+ tcpc, ok := l.Conn.(*net.TCPConn)
+ if !ok {
+ return ErrNotTCP
+ }
+ return tcpc.SetKeepAlivePeriod(d)
+}
diff --git a/vendor/github.com/stretchr/graceful/signal.go b/vendor/github.com/stretchr/graceful/signal.go
new file mode 100644
index 0000000..9550978
--- /dev/null
+++ b/vendor/github.com/stretchr/graceful/signal.go
@@ -0,0 +1,17 @@
+//+build !appengine
+
+package graceful
+
+import (
+ "os"
+ "os/signal"
+ "syscall"
+)
+
+func signalNotify(interrupt chan<- os.Signal) {
+ signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM)
+}
+
+func sendSignalInt(interrupt chan<- os.Signal) {
+ interrupt <- syscall.SIGINT
+}
diff --git a/vendor/github.com/stretchr/graceful/signal_appengine.go b/vendor/github.com/stretchr/graceful/signal_appengine.go
new file mode 100644
index 0000000..6b776f0
--- /dev/null
+++ b/vendor/github.com/stretchr/graceful/signal_appengine.go
@@ -0,0 +1,13 @@
+//+build appengine
+
+package graceful
+
+import "os"
+
+func signalNotify(interrupt chan<- os.Signal) {
+ // Does not notify in the case of AppEngine.
+}
+
+func sendSignalInt(interrupt chan<- os.Signal) {
+ // Does not send in the case of AppEngine.
+}
diff --git a/src/vendor/github.com/stretchr/graceful/tests/main.go b/vendor/github.com/stretchr/graceful/tests/main.go
index 8c8fa20..9380ae6 100644
--- a/src/vendor/github.com/stretchr/graceful/tests/main.go
+++ b/vendor/github.com/stretchr/graceful/tests/main.go
@@ -4,8 +4,8 @@ import (
"fmt"
"sync"
- "github.com/codegangsta/negroni"
- "github.com/tylerb/graceful"
+ "github.com/urfave/negroni"
+ "gopkg.in/tylerb/graceful.v1"
)
func main() {
diff --git a/vendor/github.com/urfave/negroni/LICENSE b/vendor/github.com/urfave/negroni/LICENSE
new file mode 100644
index 0000000..08b5e20
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Jeremy Saenz
+
+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/urfave/negroni/doc.go b/vendor/github.com/urfave/negroni/doc.go
new file mode 100644
index 0000000..add1ed9
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/doc.go
@@ -0,0 +1,25 @@
+// Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers.
+//
+// If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit.
+//
+// For a full guide visit http://github.com/urfave/negroni
+//
+// package main
+//
+// import (
+// "github.com/urfave/negroni"
+// "net/http"
+// "fmt"
+// )
+//
+// func main() {
+// mux := http.NewServeMux()
+// mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
+// fmt.Fprintf(w, "Welcome to the home page!")
+// })
+//
+// n := negroni.Classic()
+// n.UseHandler(mux)
+// n.Run(":3000")
+// }
+package negroni
diff --git a/vendor/github.com/urfave/negroni/logger.go b/vendor/github.com/urfave/negroni/logger.go
new file mode 100644
index 0000000..04cd53b
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/logger.go
@@ -0,0 +1,35 @@
+package negroni
+
+import (
+ "log"
+ "net/http"
+ "os"
+ "time"
+)
+
+// ALogger interface
+type ALogger interface {
+ Println(v ...interface{})
+ Printf(format string, v ...interface{})
+}
+
+// Logger is a middleware handler that logs the request as it goes in and the response as it goes out.
+type Logger struct {
+ // ALogger implements just enough log.Logger interface to be compatible with other implementations
+ ALogger
+}
+
+// NewLogger returns a new Logger instance
+func NewLogger() *Logger {
+ return &Logger{log.New(os.Stdout, "[negroni] ", 0)}
+}
+
+func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ start := time.Now()
+ l.Printf("Started %s %s", r.Method, r.URL.Path)
+
+ next(rw, r)
+
+ res := rw.(ResponseWriter)
+ l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start))
+}
diff --git a/vendor/github.com/urfave/negroni/negroni.go b/vendor/github.com/urfave/negroni/negroni.go
new file mode 100644
index 0000000..9c7c187
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/negroni.go
@@ -0,0 +1,133 @@
+package negroni
+
+import (
+ "log"
+ "net/http"
+ "os"
+)
+
+// Handler handler is an interface that objects can implement to be registered to serve as middleware
+// in the Negroni middleware stack.
+// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc
+// passed in.
+//
+// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked.
+type Handler interface {
+ ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+}
+
+// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers.
+// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
+type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)
+
+func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ h(rw, r, next)
+}
+
+type middleware struct {
+ handler Handler
+ next *middleware
+}
+
+func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ m.handler.ServeHTTP(rw, r, m.next.ServeHTTP)
+}
+
+// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni
+// middleware. The next http.HandlerFunc is automatically called after the Handler
+// is executed.
+func Wrap(handler http.Handler) Handler {
+ return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ handler.ServeHTTP(rw, r)
+ next(rw, r)
+ })
+}
+
+// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler.
+// Negroni middleware is evaluated in the order that they are added to the stack using
+// the Use and UseHandler methods.
+type Negroni struct {
+ middleware middleware
+ handlers []Handler
+}
+
+// New returns a new Negroni instance with no middleware preconfigured.
+func New(handlers ...Handler) *Negroni {
+ return &Negroni{
+ handlers: handlers,
+ middleware: build(handlers),
+ }
+}
+
+// Classic returns a new Negroni instance with the default middleware already
+// in the stack.
+//
+// Recovery - Panic Recovery Middleware
+// Logger - Request/Response Logging
+// Static - Static File Serving
+func Classic() *Negroni {
+ return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public")))
+}
+
+func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
+ n.middleware.ServeHTTP(NewResponseWriter(rw), r)
+}
+
+// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
+func (n *Negroni) Use(handler Handler) {
+ if handler == nil {
+ panic("handler cannot be nil")
+ }
+
+ n.handlers = append(n.handlers, handler)
+ n.middleware = build(n.handlers)
+}
+
+// UseFunc adds a Negroni-style handler function onto the middleware stack.
+func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) {
+ n.Use(HandlerFunc(handlerFunc))
+}
+
+// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni.
+func (n *Negroni) UseHandler(handler http.Handler) {
+ n.Use(Wrap(handler))
+}
+
+// UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack.
+func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) {
+ n.UseHandler(http.HandlerFunc(handlerFunc))
+}
+
+// Run is a convenience function that runs the negroni stack as an HTTP
+// server. The addr string takes the same format as http.ListenAndServe.
+func (n *Negroni) Run(addr string) {
+ l := log.New(os.Stdout, "[negroni] ", 0)
+ l.Printf("listening on %s", addr)
+ l.Fatal(http.ListenAndServe(addr, n))
+}
+
+// Returns a list of all the handlers in the current Negroni middleware chain.
+func (n *Negroni) Handlers() []Handler {
+ return n.handlers
+}
+
+func build(handlers []Handler) middleware {
+ var next middleware
+
+ if len(handlers) == 0 {
+ return voidMiddleware()
+ } else if len(handlers) > 1 {
+ next = build(handlers[1:])
+ } else {
+ next = voidMiddleware()
+ }
+
+ return middleware{handlers[0], &next}
+}
+
+func voidMiddleware() middleware {
+ return middleware{
+ HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}),
+ &middleware{},
+ }
+}
diff --git a/vendor/github.com/urfave/negroni/recovery.go b/vendor/github.com/urfave/negroni/recovery.go
new file mode 100644
index 0000000..8396cb1
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/recovery.go
@@ -0,0 +1,65 @@
+package negroni
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "os"
+ "runtime"
+ "runtime/debug"
+)
+
+// Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one.
+type Recovery struct {
+ Logger ALogger
+ PrintStack bool
+ ErrorHandlerFunc func(interface{})
+ StackAll bool
+ StackSize int
+}
+
+// NewRecovery returns a new instance of Recovery
+func NewRecovery() *Recovery {
+ return &Recovery{
+ Logger: log.New(os.Stdout, "[negroni] ", 0),
+ PrintStack: true,
+ StackAll: false,
+ StackSize: 1024 * 8,
+ }
+}
+
+func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ defer func() {
+ if err := recover(); err != nil {
+ if rw.Header().Get("Content-Type") == "" {
+ rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
+ }
+
+ rw.WriteHeader(http.StatusInternalServerError)
+
+ stack := make([]byte, rec.StackSize)
+ stack = stack[:runtime.Stack(stack, rec.StackAll)]
+
+ f := "PANIC: %s\n%s"
+ rec.Logger.Printf(f, err, stack)
+
+ if rec.PrintStack {
+ fmt.Fprintf(rw, f, err, stack)
+ }
+
+ if rec.ErrorHandlerFunc != nil {
+ func() {
+ defer func() {
+ if err := recover(); err != nil {
+ rec.Logger.Printf("provided ErrorHandlerFunc panic'd: %s, trace:\n%s", err, debug.Stack())
+ rec.Logger.Printf("%s\n", debug.Stack())
+ }
+ }()
+ rec.ErrorHandlerFunc(err)
+ }()
+ }
+ }
+ }()
+
+ next(rw, r)
+}
diff --git a/vendor/github.com/urfave/negroni/response_writer.go b/vendor/github.com/urfave/negroni/response_writer.go
new file mode 100644
index 0000000..bfb83a6
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/response_writer.go
@@ -0,0 +1,113 @@
+package negroni
+
+import (
+ "bufio"
+ "fmt"
+ "net"
+ "net/http"
+)
+
+// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about
+// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter
+// if the functionality calls for it.
+type ResponseWriter interface {
+ http.ResponseWriter
+ http.Flusher
+ // Status returns the status code of the response or 200 if the response has
+ // not been written (as this is the default response code in net/http)
+ Status() int
+ // Written returns whether or not the ResponseWriter has been written.
+ Written() bool
+ // Size returns the size of the response body.
+ Size() int
+ // Before allows for a function to be called before the ResponseWriter has been written to. This is
+ // useful for setting headers or any other operations that must happen before a response has been written.
+ Before(func(ResponseWriter))
+}
+
+type beforeFunc func(ResponseWriter)
+
+// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter
+func NewResponseWriter(rw http.ResponseWriter) ResponseWriter {
+ nrw := &responseWriter{
+ ResponseWriter: rw,
+ }
+
+ if _, ok := rw.(http.CloseNotifier); ok {
+ return &responseWriterCloseNotifer{nrw}
+ }
+
+ return nrw
+}
+
+type responseWriter struct {
+ http.ResponseWriter
+ status int
+ size int
+ beforeFuncs []beforeFunc
+}
+
+func (rw *responseWriter) WriteHeader(s int) {
+ rw.status = s
+ rw.callBefore()
+ rw.ResponseWriter.WriteHeader(s)
+}
+
+func (rw *responseWriter) Write(b []byte) (int, error) {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ size, err := rw.ResponseWriter.Write(b)
+ rw.size += size
+ return size, err
+}
+
+func (rw *responseWriter) Status() int {
+ return rw.status
+}
+
+func (rw *responseWriter) Size() int {
+ return rw.size
+}
+
+func (rw *responseWriter) Written() bool {
+ return rw.status != 0
+}
+
+func (rw *responseWriter) Before(before func(ResponseWriter)) {
+ rw.beforeFuncs = append(rw.beforeFuncs, before)
+}
+
+func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ hijacker, ok := rw.ResponseWriter.(http.Hijacker)
+ if !ok {
+ return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
+ }
+ return hijacker.Hijack()
+}
+
+func (rw *responseWriter) callBefore() {
+ for i := len(rw.beforeFuncs) - 1; i >= 0; i-- {
+ rw.beforeFuncs[i](rw)
+ }
+}
+
+func (rw *responseWriter) Flush() {
+ flusher, ok := rw.ResponseWriter.(http.Flusher)
+ if ok {
+ if !rw.Written() {
+ // The status will be StatusOK if WriteHeader has not been called yet
+ rw.WriteHeader(http.StatusOK)
+ }
+ flusher.Flush()
+ }
+}
+
+type responseWriterCloseNotifer struct {
+ *responseWriter
+}
+
+func (rw *responseWriterCloseNotifer) CloseNotify() <-chan bool {
+ return rw.ResponseWriter.(http.CloseNotifier).CloseNotify()
+}
diff --git a/vendor/github.com/urfave/negroni/static.go b/vendor/github.com/urfave/negroni/static.go
new file mode 100644
index 0000000..34be967
--- /dev/null
+++ b/vendor/github.com/urfave/negroni/static.go
@@ -0,0 +1,88 @@
+package negroni
+
+import (
+ "net/http"
+ "path"
+ "strings"
+)
+
+// Static is a middleware handler that serves static files in the given
+// directory/filesystem. If the file does not exist on the filesystem, it
+// passes along to the next middleware in the chain. If you desire "fileserver"
+// type behavior where it returns a 404 for unfound files, you should consider
+// using http.FileServer from the Go stdlib.
+type Static struct {
+ // Dir is the directory to serve static files from
+ Dir http.FileSystem
+ // Prefix is the optional prefix used to serve the static directory content
+ Prefix string
+ // IndexFile defines which file to serve as index if it exists.
+ IndexFile string
+}
+
+// NewStatic returns a new instance of Static
+func NewStatic(directory http.FileSystem) *Static {
+ return &Static{
+ Dir: directory,
+ Prefix: "",
+ IndexFile: "index.html",
+ }
+}
+
+func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
+ if r.Method != "GET" && r.Method != "HEAD" {
+ next(rw, r)
+ return
+ }
+ file := r.URL.Path
+ // if we have a prefix, filter requests by stripping the prefix
+ if s.Prefix != "" {
+ if !strings.HasPrefix(file, s.Prefix) {
+ next(rw, r)
+ return
+ }
+ file = file[len(s.Prefix):]
+ if file != "" && file[0] != '/' {
+ next(rw, r)
+ return
+ }
+ }
+ f, err := s.Dir.Open(file)
+ if err != nil {
+ // discard the error?
+ next(rw, r)
+ return
+ }
+ defer f.Close()
+
+ fi, err := f.Stat()
+ if err != nil {
+ next(rw, r)
+ return
+ }
+
+ // try to serve index file
+ if fi.IsDir() {
+ // redirect if missing trailing slash
+ if !strings.HasSuffix(r.URL.Path, "/") {
+ http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound)
+ return
+ }
+
+ file = path.Join(file, s.IndexFile)
+ f, err = s.Dir.Open(file)
+ if err != nil {
+ next(rw, r)
+ return
+ }
+ defer f.Close()
+
+ fi, err = f.Stat()
+ if err != nil || fi.IsDir() {
+ next(rw, r)
+ return
+ }
+ }
+
+ http.ServeContent(rw, r, file, fi.ModTime(), f)
+}
diff --git a/vendor/github.com/zenazn/goji/LICENSE b/vendor/github.com/zenazn/goji/LICENSE
new file mode 100644
index 0000000..446aba0
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014, 2015, 2016 Carl Jackson (carl@avtok.com)
+
+MIT License
+
+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/zenazn/goji/bind/bind.go b/vendor/github.com/zenazn/goji/bind/bind.go
new file mode 100644
index 0000000..43d11dd
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/bind/bind.go
@@ -0,0 +1,155 @@
+/*
+Package bind provides a convenient way to bind to sockets. It exposes a flag in
+the default flag set named "bind" which provides syntax to bind TCP and UNIX
+sockets. It also supports binding to arbitrary file descriptors passed by a
+parent (for instance, systemd), and for binding to Einhorn sockets (including
+Einhorn ACK support).
+
+If the value passed to bind contains a colon, as in ":8000" or "127.0.0.1:9001",
+it will be treated as a TCP address. If it begins with a "/" or a ".", it will
+be treated as a path to a UNIX socket. If it begins with the string "fd@", as in
+"fd@3", it will be treated as a file descriptor (useful for use with systemd,
+for instance). If it begins with the string "einhorn@", as in "einhorn@0", the
+corresponding einhorn socket will be used.
+
+If an option is not explicitly passed, the implementation will automatically
+select between using "einhorn@0", "fd@3", and ":8000", depending on whether
+Einhorn or systemd (or neither) is detected.
+
+This package is a teensy bit magical, and goes out of its way to Do The Right
+Thing in many situations, including in both development and production. If
+you're looking for something less magical, you'd probably be better off just
+calling net.Listen() the old-fashioned way.
+*/
+package bind
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "strconv"
+ "strings"
+ "sync"
+)
+
+var bind string
+
+func init() {
+ einhornInit()
+ systemdInit()
+}
+
+// DefaultBind specifies the fallback used for WithFlag() if it is
+// unable to discover an environment hint (after checking $GOJI_BIND,
+// Einhorn, systemd, and $PORT).
+//
+// If DefaultBind is overridden, it must be set before calling
+// WithFlag().
+var DefaultBind = ":8000"
+
+// WithFlag adds a standard flag to the global flag instance that
+// allows configuration of the default socket. Users who call
+// Default() must call this function before flags are parsed, for
+// example in an init() block.
+//
+// When selecting the default bind string, this function will examine
+// its environment for hints about what port to bind to, selecting the
+// GOJI_BIND environment variable, Einhorn, systemd, the PORT
+// environment variable, and the value of DefaultBind, in order. In
+// most cases, this means that the default behavior of the default
+// socket will be reasonable for use in your circumstance.
+func WithFlag() {
+ s := Sniff()
+ if s == "" {
+ s = DefaultBind
+ }
+ flag.StringVar(&bind, "bind", s,
+ `Address to bind on. If this value has a colon, as in ":8000" or
+ "127.0.0.1:9001", it will be treated as a TCP address. If it
+ begins with a "/" or a ".", it will be treated as a path to a
+ UNIX socket. If it begins with the string "fd@", as in "fd@3",
+ it will be treated as a file descriptor (useful for use with
+ systemd, for instance). If it begins with the string "einhorn@",
+ as in "einhorn@0", the corresponding einhorn socket will be
+ used. If an option is not explicitly passed, the implementation
+ will automatically select among "einhorn@0" (Einhorn), "fd@3"
+ (systemd), and ":8000" (fallback) based on its environment.`)
+}
+
+// Sniff attempts to select a sensible default bind string by examining its
+// environment. It examines the GOJI_BIND environment variable, Einhorn,
+// systemd, and the PORT environment variable, in that order, selecting the
+// first plausible option. It returns the empty string if no sensible default
+// could be extracted from the environment.
+func Sniff() string {
+ if bind := os.Getenv("GOJI_BIND"); bind != "" {
+ return bind
+ } else if usingEinhorn() {
+ return "einhorn@0"
+ } else if usingSystemd() {
+ return "fd@3"
+ } else if port := os.Getenv("PORT"); port != "" {
+ return ":" + port
+ }
+ return ""
+}
+
+func listenTo(bind string) (net.Listener, error) {
+ if strings.Contains(bind, ":") {
+ return net.Listen("tcp", bind)
+ } else if strings.HasPrefix(bind, ".") || strings.HasPrefix(bind, "/") {
+ return net.Listen("unix", bind)
+ } else if strings.HasPrefix(bind, "fd@") {
+ fd, err := strconv.Atoi(bind[3:])
+ if err != nil {
+ return nil, fmt.Errorf("error while parsing fd %v: %v",
+ bind, err)
+ }
+ f := os.NewFile(uintptr(fd), bind)
+ defer f.Close()
+ return net.FileListener(f)
+ } else if strings.HasPrefix(bind, "einhorn@") {
+ fd, err := strconv.Atoi(bind[8:])
+ if err != nil {
+ return nil, fmt.Errorf(
+ "error while parsing einhorn %v: %v", bind, err)
+ }
+ return einhornBind(fd)
+ }
+
+ return nil, fmt.Errorf("error while parsing bind arg %v", bind)
+}
+
+// Socket parses and binds to the specified address. If Socket encounters an
+// error while parsing or binding to the given socket it will exit by calling
+// log.Fatal.
+func Socket(bind string) net.Listener {
+ l, err := listenTo(bind)
+ if err != nil {
+ log.Fatal(err)
+ }
+ return l
+}
+
+// Default parses and binds to the default socket as given to us by the flag
+// module. If there was an error parsing or binding to that socket, Default will
+// exit by calling `log.Fatal`.
+func Default() net.Listener {
+ return Socket(bind)
+}
+
+// I'm not sure why you'd ever want to call Ready() more than once, but we may
+// as well be safe against it...
+var ready sync.Once
+
+// Ready notifies the environment (for now, just Einhorn) that the process is
+// ready to receive traffic. Should be called at the last possible moment to
+// maximize the chances that a faulty process exits before signaling that it's
+// ready.
+func Ready() {
+ ready.Do(func() {
+ einhornAck()
+ })
+}
diff --git a/vendor/github.com/zenazn/goji/bind/einhorn.go b/vendor/github.com/zenazn/goji/bind/einhorn.go
new file mode 100644
index 0000000..e695c0e
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/bind/einhorn.go
@@ -0,0 +1,91 @@
+// +build !windows
+
+package bind
+
+import (
+ "fmt"
+ "log"
+ "net"
+ "os"
+ "strconv"
+ "syscall"
+)
+
+const tooBigErr = "bind: einhorn@%d not found (einhorn only passed %d fds)"
+const bindErr = "bind: could not bind einhorn@%d: not running under einhorn"
+const einhornErr = "bind: einhorn environment initialization error"
+const ackErr = "bind: error ACKing to einhorn: %v"
+
+var einhornNumFds int
+
+func envInt(val string) (int, error) {
+ return strconv.Atoi(os.Getenv(val))
+}
+
+// Unfortunately this can't be a normal init function, because their execution
+// order is undefined, and we need to run before the init() in bind.go.
+func einhornInit() {
+ mpid, err := envInt("EINHORN_MASTER_PID")
+ if err != nil || mpid != os.Getppid() {
+ return
+ }
+
+ einhornNumFds, err = envInt("EINHORN_FD_COUNT")
+ if err != nil {
+ einhornNumFds = 0
+ return
+ }
+
+ // Prevent einhorn's fds from leaking to our children
+ for i := 0; i < einhornNumFds; i++ {
+ syscall.CloseOnExec(einhornFdMap(i))
+ }
+}
+
+func usingEinhorn() bool {
+ return einhornNumFds > 0
+}
+
+func einhornFdMap(n int) int {
+ name := fmt.Sprintf("EINHORN_FD_%d", n)
+ fno, err := envInt(name)
+ if err != nil {
+ log.Fatal(einhornErr)
+ }
+ return fno
+}
+
+func einhornBind(n int) (net.Listener, error) {
+ if !usingEinhorn() {
+ return nil, fmt.Errorf(bindErr, n)
+ }
+ if n >= einhornNumFds || n < 0 {
+ return nil, fmt.Errorf(tooBigErr, n, einhornNumFds)
+ }
+
+ fno := einhornFdMap(n)
+ f := os.NewFile(uintptr(fno), fmt.Sprintf("einhorn@%d", n))
+ defer f.Close()
+ return net.FileListener(f)
+}
+
+// Fun story: this is actually YAML, not JSON.
+const ackMsg = `{"command": "worker:ack", "pid": %d}` + "\n"
+
+func einhornAck() {
+ if !usingEinhorn() {
+ return
+ }
+ log.Print("bind: ACKing to einhorn")
+
+ ctl, err := net.Dial("unix", os.Getenv("EINHORN_SOCK_PATH"))
+ if err != nil {
+ log.Fatalf(ackErr, err)
+ }
+ defer ctl.Close()
+
+ _, err = fmt.Fprintf(ctl, ackMsg, os.Getpid())
+ if err != nil {
+ log.Fatalf(ackErr, err)
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/bind/einhorn_stub.go b/vendor/github.com/zenazn/goji/bind/einhorn_stub.go
new file mode 100644
index 0000000..093707f
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/bind/einhorn_stub.go
@@ -0,0 +1,12 @@
+// +build windows
+
+package bind
+
+import (
+ "net"
+)
+
+func einhornInit() {}
+func einhornAck() {}
+func einhornBind(fd int) (net.Listener, error) { return nil, nil }
+func usingEinhorn() bool { return false }
diff --git a/vendor/github.com/zenazn/goji/bind/systemd.go b/vendor/github.com/zenazn/goji/bind/systemd.go
new file mode 100644
index 0000000..e7cd8e4
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/bind/systemd.go
@@ -0,0 +1,36 @@
+// +build !windows
+
+package bind
+
+import (
+ "os"
+ "syscall"
+)
+
+const systemdMinFd = 3
+
+var systemdNumFds int
+
+// Unfortunately this can't be a normal init function, because their execution
+// order is undefined, and we need to run before the init() in bind.go.
+func systemdInit() {
+ pid, err := envInt("LISTEN_PID")
+ if err != nil || pid != os.Getpid() {
+ return
+ }
+
+ systemdNumFds, err = envInt("LISTEN_FDS")
+ if err != nil {
+ systemdNumFds = 0
+ return
+ }
+
+ // Prevent fds from leaking to our children
+ for i := 0; i < systemdNumFds; i++ {
+ syscall.CloseOnExec(systemdMinFd + i)
+ }
+}
+
+func usingSystemd() bool {
+ return systemdNumFds > 0
+}
diff --git a/vendor/github.com/zenazn/goji/bind/systemd_stub.go b/vendor/github.com/zenazn/goji/bind/systemd_stub.go
new file mode 100644
index 0000000..4ad4d20
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/bind/systemd_stub.go
@@ -0,0 +1,6 @@
+// +build windows
+
+package bind
+
+func systemdInit() {}
+func usingSystemd() bool { return false }
diff --git a/vendor/github.com/zenazn/goji/default.go b/vendor/github.com/zenazn/goji/default.go
new file mode 100644
index 0000000..540e792
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/default.go
@@ -0,0 +1,102 @@
+package goji
+
+import (
+ "github.com/zenazn/goji/web"
+ "github.com/zenazn/goji/web/middleware"
+)
+
+// The default web.Mux.
+var DefaultMux *web.Mux
+
+func init() {
+ DefaultMux = web.New()
+
+ DefaultMux.Use(middleware.RequestID)
+ DefaultMux.Use(middleware.Logger)
+ DefaultMux.Use(middleware.Recoverer)
+ DefaultMux.Use(middleware.AutomaticOptions)
+}
+
+// Use appends the given middleware to the default Mux's middleware stack. See
+// the documentation for web.Mux.Use for more information.
+func Use(middleware web.MiddlewareType) {
+ DefaultMux.Use(middleware)
+}
+
+// Insert the given middleware into the default Mux's middleware stack. See the
+// documentation for web.Mux.Insert for more information.
+func Insert(middleware, before web.MiddlewareType) error {
+ return DefaultMux.Insert(middleware, before)
+}
+
+// Abandon removes the given middleware from the default Mux's middleware stack.
+// See the documentation for web.Mux.Abandon for more information.
+func Abandon(middleware web.MiddlewareType) error {
+ return DefaultMux.Abandon(middleware)
+}
+
+// Handle adds a route to the default Mux. See the documentation for web.Mux for
+// more information about what types this function accepts.
+func Handle(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Handle(pattern, handler)
+}
+
+// Connect adds a CONNECT route to the default Mux. See the documentation for
+// web.Mux for more information about what types this function accepts.
+func Connect(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Connect(pattern, handler)
+}
+
+// Delete adds a DELETE route to the default Mux. See the documentation for
+// web.Mux for more information about what types this function accepts.
+func Delete(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Delete(pattern, handler)
+}
+
+// Get adds a GET route to the default Mux. See the documentation for web.Mux for
+// more information about what types this function accepts.
+func Get(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Get(pattern, handler)
+}
+
+// Head adds a HEAD route to the default Mux. See the documentation for web.Mux
+// for more information about what types this function accepts.
+func Head(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Head(pattern, handler)
+}
+
+// Options adds a OPTIONS route to the default Mux. See the documentation for
+// web.Mux for more information about what types this function accepts.
+func Options(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Options(pattern, handler)
+}
+
+// Patch adds a PATCH route to the default Mux. See the documentation for web.Mux
+// for more information about what types this function accepts.
+func Patch(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Patch(pattern, handler)
+}
+
+// Post adds a POST route to the default Mux. See the documentation for web.Mux
+// for more information about what types this function accepts.
+func Post(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Post(pattern, handler)
+}
+
+// Put adds a PUT route to the default Mux. See the documentation for web.Mux for
+// more information about what types this function accepts.
+func Put(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Put(pattern, handler)
+}
+
+// Trace adds a TRACE route to the default Mux. See the documentation for
+// web.Mux for more information about what types this function accepts.
+func Trace(pattern web.PatternType, handler web.HandlerType) {
+ DefaultMux.Trace(pattern, handler)
+}
+
+// NotFound sets the NotFound handler for the default Mux. See the documentation
+// for web.Mux.NotFound for more information.
+func NotFound(handler web.HandlerType) {
+ DefaultMux.NotFound(handler)
+}
diff --git a/vendor/github.com/zenazn/goji/example/main.go b/vendor/github.com/zenazn/goji/example/main.go
new file mode 100644
index 0000000..b2bcf6f
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/example/main.go
@@ -0,0 +1,177 @@
+// Command example is a sample application built with Goji. Its goal is to give
+// you a taste for what Goji looks like in the real world by artificially using
+// all of its features.
+//
+// In particular, this is a complete working site for gritter.com, a site where
+// users can post 140-character "greets". Any resemblance to real websites,
+// alive or dead, is purely coincidental.
+package main
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "regexp"
+ "strconv"
+ "time"
+
+ "github.com/goji/param"
+ "github.com/zenazn/goji"
+ "github.com/zenazn/goji/web"
+ "github.com/zenazn/goji/web/middleware"
+)
+
+// Note: the code below cuts a lot of corners to make the example app simple.
+
+func main() {
+ // Add routes to the global handler
+ goji.Get("/", Root)
+ // Fully backwards compatible with net/http's Handlers
+ goji.Get("/greets", http.RedirectHandler("/", 301))
+ // Use your favorite HTTP verbs
+ goji.Post("/greets", NewGreet)
+ // Use Sinatra-style patterns in your URLs
+ goji.Get("/users/:name", GetUser)
+ // Goji also supports regular expressions with named capture groups.
+ goji.Get(regexp.MustCompile(`^/greets/(?P<id>\d+)$`), GetGreet)
+
+ // Middleware can be used to inject behavior into your app. The
+ // middleware for this application are defined in middleware.go, but you
+ // can put them wherever you like.
+ goji.Use(PlainText)
+
+ // If the patterns ends with "/*", the path is treated as a prefix, and
+ // can be used to implement sub-routes.
+ admin := web.New()
+ goji.Handle("/admin/*", admin)
+
+ // The standard SubRouter middleware helps make writing sub-routers
+ // easy. Ordinarily, Goji does not manipulate the request's URL.Path,
+ // meaning you'd have to repeat "/admin/" in each of the following
+ // routes. This middleware allows you to cut down on the repetition by
+ // eliminating the shared, already-matched prefix.
+ admin.Use(middleware.SubRouter)
+ // You can also easily attach extra middleware to sub-routers that are
+ // not present on the parent router. This one, for instance, presents a
+ // password prompt to users of the admin endpoints.
+ admin.Use(SuperSecure)
+
+ admin.Get("/", AdminRoot)
+ admin.Get("/finances", AdminFinances)
+
+ // Goji's routing, like Sinatra's, is exact: no effort is made to
+ // normalize trailing slashes.
+ goji.Get("/admin", http.RedirectHandler("/admin/", 301))
+
+ // Use a custom 404 handler
+ goji.NotFound(NotFound)
+
+ // Sometimes requests take a long time.
+ goji.Get("/waitforit", WaitForIt)
+
+ // Call Serve() at the bottom of your main() function, and it'll take
+ // care of everything else for you, including binding to a socket (with
+ // automatic support for systemd and Einhorn) and supporting graceful
+ // shutdown on SIGINT. Serve() is appropriate for both development and
+ // production.
+ goji.Serve()
+}
+
+// Root route (GET "/"). Print a list of greets.
+func Root(w http.ResponseWriter, r *http.Request) {
+ // In the real world you'd probably use a template or something.
+ io.WriteString(w, "Gritter\n======\n\n")
+ for i := len(Greets) - 1; i >= 0; i-- {
+ Greets[i].Write(w)
+ }
+}
+
+// NewGreet creates a new greet (POST "/greets"). Creates a greet and redirects
+// you to the created greet.
+//
+// To post a new greet, try this at a shell:
+// $ now=$(date +'%Y-%m-%dT%H:%M:%SZ')
+// $ curl -i -d "user=carl&message=Hello+World&time=$now" localhost:8000/greets
+func NewGreet(w http.ResponseWriter, r *http.Request) {
+ var greet Greet
+
+ // Parse the POST body into the Greet struct. The format is the same as
+ // is emitted by (e.g.) jQuery.param.
+ r.ParseForm()
+ err := param.Parse(r.Form, &greet)
+
+ if err != nil || len(greet.Message) > 140 {
+ http.Error(w, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ // We make no effort to prevent races against other insertions.
+ Greets = append(Greets, greet)
+ url := fmt.Sprintf("/greets/%d", len(Greets)-1)
+ http.Redirect(w, r, url, http.StatusCreated)
+}
+
+// GetUser finds a given user and her greets (GET "/user/:name")
+func GetUser(c web.C, w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "Gritter\n======\n\n")
+ handle := c.URLParams["name"]
+ user, ok := Users[handle]
+ if !ok {
+ http.Error(w, http.StatusText(404), 404)
+ return
+ }
+
+ user.Write(w, handle)
+
+ io.WriteString(w, "\nGreets:\n")
+ for i := len(Greets) - 1; i >= 0; i-- {
+ if Greets[i].User == handle {
+ Greets[i].Write(w)
+ }
+ }
+}
+
+// GetGreet finds a particular greet by ID (GET "/greets/\d+"). Does no bounds
+// checking, so will probably panic.
+func GetGreet(c web.C, w http.ResponseWriter, r *http.Request) {
+ id, err := strconv.Atoi(c.URLParams["id"])
+ if err != nil {
+ http.Error(w, http.StatusText(404), 404)
+ return
+ }
+ // This will panic if id is too big. Try it out!
+ greet := Greets[id]
+
+ io.WriteString(w, "Gritter\n======\n\n")
+ greet.Write(w)
+}
+
+// WaitForIt is a particularly slow handler (GET "/waitforit"). Try loading this
+// endpoint and initiating a graceful shutdown (Ctrl-C) or Einhorn reload. The
+// old server will stop accepting new connections and will attempt to kill
+// outstanding idle (keep-alive) connections, but will patiently stick around
+// for this endpoint to finish. How kind of it!
+func WaitForIt(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "This is going to be legend... (wait for it)\n")
+ if fl, ok := w.(http.Flusher); ok {
+ fl.Flush()
+ }
+ time.Sleep(15 * time.Second)
+ io.WriteString(w, "...dary! Legendary!\n")
+}
+
+// AdminRoot is root (GET "/admin/root"). Much secret. Very administrate. Wow.
+func AdminRoot(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "Gritter\n======\n\nSuper secret admin page!\n")
+}
+
+// AdminFinances would answer the question 'How are we doing?'
+// (GET "/admin/finances")
+func AdminFinances(w http.ResponseWriter, r *http.Request) {
+ io.WriteString(w, "Gritter\n======\n\nWe're broke! :(\n")
+}
+
+// NotFound is a 404 handler.
+func NotFound(w http.ResponseWriter, r *http.Request) {
+ http.Error(w, "Umm... have you tried turning it off and on again?", 404)
+}
diff --git a/vendor/github.com/zenazn/goji/example/middleware.go b/vendor/github.com/zenazn/goji/example/middleware.go
new file mode 100644
index 0000000..9652ebb
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/example/middleware.go
@@ -0,0 +1,47 @@
+package main
+
+import (
+ "encoding/base64"
+ "net/http"
+ "strings"
+
+ "github.com/zenazn/goji/web"
+)
+
+// PlainText sets the content-type of responses to text/plain.
+func PlainText(h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Set("Content-Type", "text/plain")
+ h.ServeHTTP(w, r)
+ }
+ return http.HandlerFunc(fn)
+}
+
+// Nobody will ever guess this!
+const Password = "admin:admin"
+
+// SuperSecure is HTTP Basic Auth middleware for super-secret admin page. Shhhh!
+func SuperSecure(c *web.C, h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ auth := r.Header.Get("Authorization")
+ if !strings.HasPrefix(auth, "Basic ") {
+ pleaseAuth(w)
+ return
+ }
+
+ password, err := base64.StdEncoding.DecodeString(auth[6:])
+ if err != nil || string(password) != Password {
+ pleaseAuth(w)
+ return
+ }
+
+ h.ServeHTTP(w, r)
+ }
+ return http.HandlerFunc(fn)
+}
+
+func pleaseAuth(w http.ResponseWriter) {
+ w.Header().Set("WWW-Authenticate", `Basic realm="Gritter"`)
+ w.WriteHeader(http.StatusUnauthorized)
+ w.Write([]byte("Go away!\n"))
+}
diff --git a/vendor/github.com/zenazn/goji/example/models.go b/vendor/github.com/zenazn/goji/example/models.go
new file mode 100644
index 0000000..4c34c08
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/example/models.go
@@ -0,0 +1,49 @@
+package main
+
+import (
+ "fmt"
+ "io"
+ "time"
+)
+
+// A Greet is a 140-character micro-blogpost that has no resemblance whatsoever
+// to the noise a bird makes.
+type Greet struct {
+ User string `param:"user"`
+ Message string `param:"message"`
+ Time time.Time `param:"time"`
+}
+
+// Store all our greets in a big list in memory, because, let's be honest, who's
+// actually going to use a service that only allows you to post 140-character
+// messages?
+var Greets = []Greet{
+ {"carl", "Welcome to Gritter!", time.Now()},
+ {"alice", "Wanna know a secret?", time.Now()},
+ {"bob", "Okay!", time.Now()},
+ {"eve", "I'm listening...", time.Now()},
+}
+
+// Write out a representation of the greet
+func (g Greet) Write(w io.Writer) {
+ fmt.Fprintf(w, "%s\n@%s at %s\n---\n", g.Message, g.User,
+ g.Time.Format(time.UnixDate))
+}
+
+// A User is a person. It may even be someone you know. Or a rabbit. Hard to say
+// from here.
+type User struct {
+ Name, Bio string
+}
+
+// All the users we know about! There aren't very many...
+var Users = map[string]User{
+ "alice": {"Alice in Wonderland", "Eating mushrooms"},
+ "bob": {"Bob the Builder", "Making children dumber"},
+ "carl": {"Carl Jackson", "Duct tape aficionado"},
+}
+
+// Write out the user
+func (u User) Write(w io.Writer, handle string) {
+ fmt.Fprintf(w, "%s (@%s)\n%s\n", u.Name, handle, u.Bio)
+}
diff --git a/vendor/github.com/zenazn/goji/goji.go b/vendor/github.com/zenazn/goji/goji.go
new file mode 100644
index 0000000..ab278cd
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/goji.go
@@ -0,0 +1,36 @@
+/*
+Package goji provides an out-of-box web server with reasonable defaults.
+
+Example:
+ package main
+
+ import (
+ "fmt"
+ "net/http"
+
+ "github.com/zenazn/goji"
+ "github.com/zenazn/goji/web"
+ )
+
+ func hello(c web.C, w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, "Hello, %s!", c.URLParams["name"])
+ }
+
+ func main() {
+ goji.Get("/hello/:name", hello)
+ goji.Serve()
+ }
+
+This package exists purely as a convenience to programmers who want to get
+started as quickly as possible. It draws almost all of its code from goji's
+subpackages, the most interesting of which is goji/web, and where most of the
+documentation for the web framework lives.
+
+A side effect of this package's ease-of-use is the fact that it is opinionated.
+If you don't like (or have outgrown) its opinions, it should be straightforward
+to use the APIs of goji's subpackages to reimplement things to your liking. Both
+methods of using this library are equally well supported.
+
+Goji requires Go 1.2 or newer.
+*/
+package goji
diff --git a/vendor/github.com/zenazn/goji/graceful/clone.go b/vendor/github.com/zenazn/goji/graceful/clone.go
new file mode 100644
index 0000000..a9027e5
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/clone.go
@@ -0,0 +1,11 @@
+// +build !go1.6
+
+package graceful
+
+import "crypto/tls"
+
+// see clone16.go
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ c := *cfg
+ return &c
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/clone16.go b/vendor/github.com/zenazn/goji/graceful/clone16.go
new file mode 100644
index 0000000..810b3a2
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/clone16.go
@@ -0,0 +1,34 @@
+// +build go1.6
+
+package graceful
+
+import "crypto/tls"
+
+// cloneTLSConfig was taken from the Go standard library's net/http package. We
+// need it because tls.Config objects now contain a sync.Once.
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+ if cfg == nil {
+ return &tls.Config{}
+ }
+ return &tls.Config{
+ Rand: cfg.Rand,
+ Time: cfg.Time,
+ Certificates: cfg.Certificates,
+ NameToCertificate: cfg.NameToCertificate,
+ GetCertificate: cfg.GetCertificate,
+ RootCAs: cfg.RootCAs,
+ NextProtos: cfg.NextProtos,
+ ServerName: cfg.ServerName,
+ ClientAuth: cfg.ClientAuth,
+ ClientCAs: cfg.ClientCAs,
+ InsecureSkipVerify: cfg.InsecureSkipVerify,
+ CipherSuites: cfg.CipherSuites,
+ PreferServerCipherSuites: cfg.PreferServerCipherSuites,
+ SessionTicketsDisabled: cfg.SessionTicketsDisabled,
+ SessionTicketKey: cfg.SessionTicketKey,
+ ClientSessionCache: cfg.ClientSessionCache,
+ MinVersion: cfg.MinVersion,
+ MaxVersion: cfg.MaxVersion,
+ CurvePreferences: cfg.CurvePreferences,
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/einhorn.go b/vendor/github.com/zenazn/goji/graceful/einhorn.go
new file mode 100644
index 0000000..082d1c4
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/einhorn.go
@@ -0,0 +1,21 @@
+// +build !windows
+
+package graceful
+
+import (
+ "os"
+ "strconv"
+ "syscall"
+)
+
+func init() {
+ // This is a little unfortunate: goji/bind already knows whether we're
+ // running under einhorn, but we don't want to introduce a dependency
+ // between the two packages. Since the check is short enough, inlining
+ // it here seems "fine."
+ mpid, err := strconv.Atoi(os.Getenv("EINHORN_MASTER_PID"))
+ if err != nil || mpid != os.Getppid() {
+ return
+ }
+ stdSignals = append(stdSignals, syscall.SIGUSR2)
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/graceful.go b/vendor/github.com/zenazn/goji/graceful/graceful.go
new file mode 100644
index 0000000..ff9b186
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/graceful.go
@@ -0,0 +1,62 @@
+/*
+Package graceful implements graceful shutdown for HTTP servers by closing idle
+connections after receiving a signal. By default, this package listens for
+interrupts (i.e., SIGINT), but when it detects that it is running under Einhorn
+it will additionally listen for SIGUSR2 as well, giving your application
+automatic support for graceful restarts/code upgrades.
+*/
+package graceful
+
+import (
+ "net"
+ "runtime"
+ "sync/atomic"
+
+ "github.com/zenazn/goji/graceful/listener"
+)
+
+// WrapListener wraps an arbitrary net.Listener for use with graceful shutdowns.
+// In the background, it uses the listener sub-package to Wrap the listener in
+// Deadline mode. If another mode of operation is desired, you should call
+// listener.Wrap yourself: this function is smart enough to not double-wrap
+// listeners.
+func WrapListener(l net.Listener) net.Listener {
+ if lt, ok := l.(*listener.T); ok {
+ appendListener(lt)
+ return lt
+ }
+
+ lt := listener.Wrap(l, listener.Deadline)
+ appendListener(lt)
+ return lt
+}
+
+func appendListener(l *listener.T) {
+ mu.Lock()
+ defer mu.Unlock()
+
+ listeners = append(listeners, l)
+}
+
+const errClosing = "use of closed network connection"
+
+// During graceful shutdown, calls to Accept will start returning errors. This
+// is inconvenient, since we know these sorts of errors are peaceful, so we
+// silently swallow them.
+func peacefulError(err error) error {
+ if atomic.LoadInt32(&closing) == 0 {
+ return err
+ }
+ // Unfortunately Go doesn't really give us a better way to select errors
+ // than this, so *shrug*.
+ if oe, ok := err.(*net.OpError); ok {
+ errOp := "accept"
+ if runtime.GOOS == "windows" {
+ errOp = "AcceptEx"
+ }
+ if oe.Op == errOp && oe.Err.Error() == errClosing {
+ return nil
+ }
+ }
+ return err
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/listener/conn.go b/vendor/github.com/zenazn/goji/graceful/listener/conn.go
new file mode 100644
index 0000000..7b34b47
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/listener/conn.go
@@ -0,0 +1,151 @@
+package listener
+
+import (
+ "errors"
+ "io"
+ "net"
+ "sync"
+ "time"
+)
+
+type conn struct {
+ net.Conn
+
+ shard *shard
+ mode mode
+
+ mu sync.Mutex // Protects the state machine below
+ busy bool // connection is in use (i.e., not idle)
+ closed bool // connection is closed
+ disowned bool // if true, this connection is no longer under our management
+}
+
+// This intentionally looks a lot like the one in package net.
+var errClosing = errors.New("use of closed network connection")
+
+func (c *conn) init() error {
+ c.shard.wg.Add(1)
+ if shouldExit := c.shard.track(c); shouldExit {
+ c.Close()
+ return errClosing
+ }
+ return nil
+}
+
+func (c *conn) Read(b []byte) (n int, err error) {
+ defer func() {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.disowned {
+ return
+ }
+
+ // This protects against a Close/Read race. We're not really
+ // concerned about the general case (it's fundamentally racy),
+ // but are mostly trying to prevent a race between a new request
+ // getting read off the wire in one thread while the connection
+ // is being gracefully shut down in another.
+ if c.closed && err == nil {
+ n = 0
+ err = errClosing
+ return
+ }
+
+ if c.mode != Manual && !c.busy && !c.closed {
+ c.busy = true
+ c.shard.markInUse(c)
+ }
+ }()
+
+ return c.Conn.Read(b)
+}
+
+func (c *conn) Close() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.disowned {
+ return c.Conn.Close()
+ } else if c.closed {
+ return errClosing
+ }
+
+ c.closed = true
+ c.shard.disown(c)
+ defer c.shard.wg.Done()
+
+ return c.Conn.Close()
+}
+
+func (c *conn) SetReadDeadline(t time.Time) error {
+ c.mu.Lock()
+ if !c.disowned && c.mode == Deadline {
+ defer c.markIdle()
+ }
+ c.mu.Unlock()
+ return c.Conn.SetReadDeadline(t)
+}
+
+func (c *conn) ReadFrom(r io.Reader) (int64, error) {
+ return io.Copy(c.Conn, r)
+}
+
+func (c *conn) markIdle() {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if !c.busy {
+ return
+ }
+ c.busy = false
+
+ if exit := c.shard.markIdle(c); exit && !c.closed && !c.disowned {
+ c.closed = true
+ c.shard.disown(c)
+ defer c.shard.wg.Done()
+ c.Conn.Close()
+ return
+ }
+}
+
+func (c *conn) markInUse() {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if !c.busy && !c.closed && !c.disowned {
+ c.busy = true
+ c.shard.markInUse(c)
+ }
+}
+
+func (c *conn) closeIfIdle() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if !c.busy && !c.closed && !c.disowned {
+ c.closed = true
+ c.shard.disown(c)
+ defer c.shard.wg.Done()
+ return c.Conn.Close()
+ }
+
+ return nil
+}
+
+var errAlreadyDisowned = errors.New("listener: conn already disowned")
+
+func (c *conn) disown() error {
+ c.mu.Lock()
+ defer c.mu.Unlock()
+
+ if c.disowned {
+ return errAlreadyDisowned
+ }
+
+ c.shard.disown(c)
+ c.disowned = true
+ c.shard.wg.Done()
+
+ return nil
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/listener/listener.go b/vendor/github.com/zenazn/goji/graceful/listener/listener.go
new file mode 100644
index 0000000..6c9c477
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/listener/listener.go
@@ -0,0 +1,178 @@
+/*
+Package listener provides a way to incorporate graceful shutdown to any
+net.Listener.
+
+This package provides low-level primitives, not a high-level API. If you're
+looking for a package that provides graceful shutdown for HTTP servers, I
+recommend this package's parent package, github.com/zenazn/goji/graceful.
+*/
+package listener
+
+import (
+ "errors"
+ "net"
+ "runtime"
+ "sync"
+ "sync/atomic"
+)
+
+type mode int8
+
+const (
+ // Manual mode is completely manual: users must use use MarkIdle and
+ // MarkInUse to indicate when connections are busy servicing requests or
+ // are eligible for termination.
+ Manual mode = iota
+ // Automatic mode is what most users probably want: calling Read on a
+ // connection will mark it as in use, but users must manually call
+ // MarkIdle to indicate when connections may be safely closed.
+ Automatic
+ // Deadline mode is like automatic mode, except that calling
+ // SetReadDeadline on a connection will also mark it as being idle. This
+ // is useful for many servers like net/http, where SetReadDeadline is
+ // used to implement read timeouts on new requests.
+ Deadline
+)
+
+// Wrap a net.Listener, returning a net.Listener which supports idle connection
+// tracking and shutdown. Listeners can be placed in to one of three modes,
+// exported as variables from this package: most users will probably want the
+// "Automatic" mode.
+func Wrap(l net.Listener, m mode) *T {
+ t := &T{
+ l: l,
+ mode: m,
+ // To keep the expected contention rate constant we'd have to
+ // grow this as numcpu**2. In practice, CPU counts don't
+ // generally grow without bound, and contention is probably
+ // going to be small enough that nobody cares anyways.
+ shards: make([]shard, 2*runtime.NumCPU()),
+ }
+ for i := range t.shards {
+ t.shards[i].init(t)
+ }
+ return t
+}
+
+// T is the type of this package's graceful listeners.
+type T struct {
+ mu sync.Mutex
+ l net.Listener
+
+ // TODO(carl): a count of currently outstanding connections.
+ connCount uint64
+ shards []shard
+
+ mode mode
+}
+
+var _ net.Listener = &T{}
+
+// Accept waits for and returns the next connection to the listener. The
+// returned net.Conn's idleness is tracked, and idle connections can be closed
+// from the associated T.
+func (t *T) Accept() (net.Conn, error) {
+ c, err := t.l.Accept()
+ if err != nil {
+ return nil, err
+ }
+
+ connID := atomic.AddUint64(&t.connCount, 1)
+ shard := &t.shards[int(connID)%len(t.shards)]
+ wc := &conn{
+ Conn: c,
+ shard: shard,
+ mode: t.mode,
+ }
+
+ if err = wc.init(); err != nil {
+ return nil, err
+ }
+ return wc, nil
+}
+
+// Addr returns the wrapped listener's network address.
+func (t *T) Addr() net.Addr {
+ return t.l.Addr()
+}
+
+// Close closes the wrapped listener.
+func (t *T) Close() error {
+ return t.l.Close()
+}
+
+// CloseIdle closes all connections that are currently marked as being idle. It,
+// however, makes no attempt to wait for in-use connections to die, or to close
+// connections which become idle in the future. Call this function if you're
+// interested in shedding useless connections, but otherwise wish to continue
+// serving requests.
+func (t *T) CloseIdle() error {
+ for i := range t.shards {
+ t.shards[i].closeConns(false, false)
+ }
+ // Not sure if returning errors is actually useful here :/
+ return nil
+}
+
+// Drain immediately closes all idle connections, prevents new connections from
+// being accepted, and waits for all outstanding connections to finish.
+//
+// Once a listener has been drained, there is no way to re-enable it. You
+// probably want to Close the listener before draining it, otherwise new
+// connections will be accepted and immediately closed.
+func (t *T) Drain() error {
+ for i := range t.shards {
+ t.shards[i].closeConns(false, true)
+ }
+ for i := range t.shards {
+ t.shards[i].wait()
+ }
+ return nil
+}
+
+// DrainAll closes all connections currently tracked by this listener (both idle
+// and in-use connections), and prevents new connections from being accepted.
+// Disowned connections are not closed.
+func (t *T) DrainAll() error {
+ for i := range t.shards {
+ t.shards[i].closeConns(true, true)
+ }
+ for i := range t.shards {
+ t.shards[i].wait()
+ }
+ return nil
+}
+
+var errNotManaged = errors.New("listener: passed net.Conn is not managed by this package")
+
+// Disown causes a connection to no longer be tracked by the listener. The
+// passed connection must have been returned by a call to Accept from this
+// listener.
+func Disown(c net.Conn) error {
+ if cn, ok := c.(*conn); ok {
+ return cn.disown()
+ }
+ return errNotManaged
+}
+
+// MarkIdle marks the given connection as being idle, and therefore eligible for
+// closing at any time. The passed connection must have been returned by a call
+// to Accept from this listener.
+func MarkIdle(c net.Conn) error {
+ if cn, ok := c.(*conn); ok {
+ cn.markIdle()
+ return nil
+ }
+ return errNotManaged
+}
+
+// MarkInUse marks this connection as being in use, removing it from the set of
+// connections which are eligible for closing. The passed connection must have
+// been returned by a call to Accept from this listener.
+func MarkInUse(c net.Conn) error {
+ if cn, ok := c.(*conn); ok {
+ cn.markInUse()
+ return nil
+ }
+ return errNotManaged
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/listener/shard.go b/vendor/github.com/zenazn/goji/graceful/listener/shard.go
new file mode 100644
index 0000000..a9addad
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/listener/shard.go
@@ -0,0 +1,98 @@
+package listener
+
+import "sync"
+
+type shard struct {
+ l *T
+
+ mu sync.Mutex
+ idle map[*conn]struct{}
+ all map[*conn]struct{}
+ wg sync.WaitGroup
+ drain bool
+}
+
+// We pretty aggressively preallocate set entries in the hopes that we never
+// have to allocate memory with the lock held. This is definitely a premature
+// optimization and is probably misguided, but luckily it costs us essentially
+// nothing.
+const prealloc = 2048
+
+func (s *shard) init(l *T) {
+ s.l = l
+ s.idle = make(map[*conn]struct{}, prealloc)
+ s.all = make(map[*conn]struct{}, prealloc)
+}
+
+func (s *shard) track(c *conn) (shouldClose bool) {
+ s.mu.Lock()
+ if s.drain {
+ s.mu.Unlock()
+ return true
+ }
+ s.all[c] = struct{}{}
+ s.idle[c] = struct{}{}
+ s.mu.Unlock()
+ return false
+}
+
+func (s *shard) disown(c *conn) {
+ s.mu.Lock()
+ delete(s.all, c)
+ delete(s.idle, c)
+ s.mu.Unlock()
+}
+
+func (s *shard) markIdle(c *conn) (shouldClose bool) {
+ s.mu.Lock()
+ if s.drain {
+ s.mu.Unlock()
+ return true
+ }
+ s.idle[c] = struct{}{}
+ s.mu.Unlock()
+ return false
+}
+
+func (s *shard) markInUse(c *conn) {
+ s.mu.Lock()
+ delete(s.idle, c)
+ s.mu.Unlock()
+}
+
+func (s *shard) closeConns(all, drain bool) {
+ s.mu.Lock()
+ if drain {
+ s.drain = true
+ }
+ set := make(map[*conn]struct{}, len(s.all))
+ if all {
+ for c := range s.all {
+ set[c] = struct{}{}
+ }
+ } else {
+ for c := range s.idle {
+ set[c] = struct{}{}
+ }
+ }
+ // We have to drop the shard lock here to avoid deadlock: we cannot
+ // acquire the shard lock after the connection lock, and the closeIfIdle
+ // call below will grab a connection lock.
+ s.mu.Unlock()
+
+ for c := range set {
+ // This might return an error (from Close), but I don't think we
+ // can do anything about it, so let's just pretend it didn't
+ // happen. (I also expect that most errors returned in this way
+ // are going to be pretty boring)
+ if all {
+ c.Close()
+ } else {
+ c.closeIfIdle()
+ }
+ }
+}
+
+func (s *shard) wait() {
+ s.wg.Wait()
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/middleware.go b/vendor/github.com/zenazn/goji/graceful/middleware.go
new file mode 100644
index 0000000..94edfe3
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/middleware.go
@@ -0,0 +1,103 @@
+// +build !go1.3
+
+package graceful
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+ "sync/atomic"
+
+ "github.com/zenazn/goji/graceful/listener"
+)
+
+// Middleware provides functionality similar to net/http.Server's
+// SetKeepAlivesEnabled in Go 1.3, but in Go 1.2.
+func middleware(h http.Handler) http.Handler {
+ if h == nil {
+ return nil
+ }
+ return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ _, cn := w.(http.CloseNotifier)
+ _, fl := w.(http.Flusher)
+ _, hj := w.(http.Hijacker)
+ _, rf := w.(io.ReaderFrom)
+
+ bw := basicWriter{ResponseWriter: w}
+
+ if cn && fl && hj && rf {
+ h.ServeHTTP(&fancyWriter{bw}, r)
+ } else {
+ h.ServeHTTP(&bw, r)
+ }
+ if !bw.headerWritten {
+ bw.maybeClose()
+ }
+ })
+}
+
+type basicWriter struct {
+ http.ResponseWriter
+ headerWritten bool
+}
+
+func (b *basicWriter) maybeClose() {
+ b.headerWritten = true
+ if atomic.LoadInt32(&closing) != 0 {
+ b.ResponseWriter.Header().Set("Connection", "close")
+ }
+}
+
+func (b *basicWriter) WriteHeader(code int) {
+ b.maybeClose()
+ b.ResponseWriter.WriteHeader(code)
+}
+
+func (b *basicWriter) Write(buf []byte) (int, error) {
+ if !b.headerWritten {
+ b.maybeClose()
+ }
+ return b.ResponseWriter.Write(buf)
+}
+
+func (b *basicWriter) Unwrap() http.ResponseWriter {
+ return b.ResponseWriter
+}
+
+// Optimize for the common case of a ResponseWriter that supports all three of
+// CloseNotifier, Flusher, and Hijacker.
+type fancyWriter struct {
+ basicWriter
+}
+
+func (f *fancyWriter) CloseNotify() <-chan bool {
+ cn := f.basicWriter.ResponseWriter.(http.CloseNotifier)
+ return cn.CloseNotify()
+}
+func (f *fancyWriter) Flush() {
+ fl := f.basicWriter.ResponseWriter.(http.Flusher)
+ fl.Flush()
+}
+func (f *fancyWriter) Hijack() (c net.Conn, b *bufio.ReadWriter, e error) {
+ hj := f.basicWriter.ResponseWriter.(http.Hijacker)
+ c, b, e = hj.Hijack()
+
+ if e == nil {
+ e = listener.Disown(c)
+ }
+
+ return
+}
+func (f *fancyWriter) ReadFrom(r io.Reader) (int64, error) {
+ rf := f.basicWriter.ResponseWriter.(io.ReaderFrom)
+ if !f.basicWriter.headerWritten {
+ f.basicWriter.maybeClose()
+ }
+ return rf.ReadFrom(r)
+}
+
+var _ http.CloseNotifier = &fancyWriter{}
+var _ http.Flusher = &fancyWriter{}
+var _ http.Hijacker = &fancyWriter{}
+var _ io.ReaderFrom = &fancyWriter{}
diff --git a/vendor/github.com/zenazn/goji/graceful/serve.go b/vendor/github.com/zenazn/goji/graceful/serve.go
new file mode 100644
index 0000000..edb2a53
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/serve.go
@@ -0,0 +1,33 @@
+// +build !go1.3
+
+package graceful
+
+import (
+ "net"
+ "net/http"
+ "time"
+
+ "github.com/zenazn/goji/graceful/listener"
+)
+
+// About 200 years, also known as "forever"
+const forever time.Duration = 200 * 365 * 24 * time.Hour
+
+// Serve behaves like the method on net/http.Server with the same name.
+func (srv *Server) Serve(l net.Listener) error {
+ // Spawn a shadow http.Server to do the actual servering. We do this
+ // because we need to sketch on some of the parameters you passed in,
+ // and it's nice to keep our sketching to ourselves.
+ shadow := *(*http.Server)(srv)
+
+ if shadow.ReadTimeout == 0 {
+ shadow.ReadTimeout = forever
+ }
+ shadow.Handler = middleware(shadow.Handler)
+
+ wrap := listener.Wrap(l, listener.Deadline)
+ appendListener(wrap)
+
+ err := shadow.Serve(wrap)
+ return peacefulError(err)
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/serve13.go b/vendor/github.com/zenazn/goji/graceful/serve13.go
new file mode 100644
index 0000000..68cac04
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/serve13.go
@@ -0,0 +1,76 @@
+// +build go1.3
+
+package graceful
+
+import (
+ "log"
+ "net"
+ "net/http"
+
+ "github.com/zenazn/goji/graceful/listener"
+)
+
+// This is a slightly hacky shim to disable keepalives when shutting a server
+// down. We could have added extra functionality in listener or signal.go to
+// deal with this case, but this seems simpler.
+type gracefulServer struct {
+ net.Listener
+ s *http.Server
+}
+
+func (g gracefulServer) Close() error {
+ g.s.SetKeepAlivesEnabled(false)
+ return g.Listener.Close()
+}
+
+// A chaining http.ConnState wrapper
+type connState func(net.Conn, http.ConnState)
+
+func (c connState) Wrap(nc net.Conn, s http.ConnState) {
+ // There are a few other states defined, most notably StateActive.
+ // Unfortunately it doesn't look like it's possible to make use of
+ // StateActive to implement graceful shutdown, since StateActive is set
+ // after a complete request has been read off the wire with an intent to
+ // process it. If we were to race a graceful shutdown against a
+ // connection that was just read off the wire (but not yet in
+ // StateActive), we would accidentally close the connection out from
+ // underneath an active request.
+ //
+ // We already needed to work around this for Go 1.2 by shimming out a
+ // full net.Conn object, so we can just fall back to the old behavior
+ // there.
+ //
+ // I started a golang-nuts thread about this here:
+ // https://groups.google.com/forum/#!topic/golang-nuts/Xi8yjBGWfCQ
+ // I'd be very eager to find a better way to do this, so reach out to me
+ // if you have any ideas.
+ switch s {
+ case http.StateIdle:
+ if err := listener.MarkIdle(nc); err != nil {
+ log.Printf("error marking conn as idle: %v", err)
+ }
+ case http.StateHijacked:
+ if err := listener.Disown(nc); err != nil {
+ log.Printf("error disowning hijacked conn: %v", err)
+ }
+ }
+ if c != nil {
+ c(nc, s)
+ }
+}
+
+// Serve behaves like the method on net/http.Server with the same name.
+func (srv *Server) Serve(l net.Listener) error {
+ // Spawn a shadow http.Server to do the actual servering. We do this
+ // because we need to sketch on some of the parameters you passed in,
+ // and it's nice to keep our sketching to ourselves.
+ shadow := *(*http.Server)(srv)
+ shadow.ConnState = connState(shadow.ConnState).Wrap
+
+ l = gracefulServer{l, &shadow}
+ wrap := listener.Wrap(l, listener.Automatic)
+ appendListener(wrap)
+
+ err := shadow.Serve(wrap)
+ return peacefulError(err)
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/server.go b/vendor/github.com/zenazn/goji/graceful/server.go
new file mode 100644
index 0000000..ae9a5fb
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/server.go
@@ -0,0 +1,108 @@
+package graceful
+
+import (
+ "crypto/tls"
+ "net"
+ "net/http"
+ "time"
+)
+
+// Most of the code here is lifted straight from net/http
+
+// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
+// connections. It's used by ListenAndServe and ListenAndServeTLS so
+// dead TCP connections (e.g. closing laptop mid-download) eventually
+// go away.
+type tcpKeepAliveListener struct {
+ *net.TCPListener
+}
+
+func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) {
+ tc, err := ln.AcceptTCP()
+ if err != nil {
+ return
+ }
+ tc.SetKeepAlive(true)
+ tc.SetKeepAlivePeriod(3 * time.Minute)
+ return tc, nil
+}
+
+// A Server is exactly the same as an http.Server, but provides more graceful
+// implementations of its methods.
+type Server http.Server
+
+// ListenAndServe behaves like the method on net/http.Server with the same name.
+func (srv *Server) ListenAndServe() error {
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":http"
+ }
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return err
+ }
+ return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)})
+}
+
+// ListenAndServeTLS behaves like the method on net/http.Server with the same
+// name. Unlike the method of the same name on http.Server, this function
+// defaults to enforcing TLS 1.0 or higher in order to address the POODLE
+// vulnerability. Users who wish to enable SSLv3 must do so by supplying a
+// TLSConfig explicitly.
+func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
+ addr := srv.Addr
+ if addr == "" {
+ addr = ":https"
+ }
+ config := &tls.Config{
+ MinVersion: tls.VersionTLS10,
+ }
+ if srv.TLSConfig != nil {
+ config = cloneTLSConfig(srv.TLSConfig)
+ }
+ if config.NextProtos == nil {
+ config.NextProtos = []string{"http/1.1"}
+ }
+
+ var err error
+ config.Certificates = make([]tls.Certificate, 1)
+ config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+ if err != nil {
+ return err
+ }
+
+ ln, err := net.Listen("tcp", addr)
+ if err != nil {
+ return err
+ }
+
+ tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
+ return srv.Serve(tlsListener)
+}
+
+// ListenAndServe behaves exactly like the net/http function of the same name.
+func ListenAndServe(addr string, handler http.Handler) error {
+ server := &Server{Addr: addr, Handler: handler}
+ return server.ListenAndServe()
+}
+
+// ListenAndServeTLS behaves almost exactly like the net/http function of the
+// same name. Unlike net/http, however, this function defaults to enforcing TLS
+// 1.0 or higher in order to address the POODLE vulnerability. Users who wish to
+// enable SSLv3 must do so by explicitly instantiating a server with an
+// appropriately configured TLSConfig property.
+func ListenAndServeTLS(addr, certfile, keyfile string, handler http.Handler) error {
+ server := &Server{Addr: addr, Handler: handler}
+ return server.ListenAndServeTLS(certfile, keyfile)
+}
+
+// Serve mostly behaves like the net/http function of the same name, except that
+// if the passed listener is a net.TCPListener, TCP keep-alives are enabled on
+// accepted connections.
+func Serve(l net.Listener, handler http.Handler) error {
+ if tl, ok := l.(*net.TCPListener); ok {
+ l = tcpKeepAliveListener{tl}
+ }
+ server := &Server{Handler: handler}
+ return server.Serve(l)
+}
diff --git a/vendor/github.com/zenazn/goji/graceful/signal.go b/vendor/github.com/zenazn/goji/graceful/signal.go
new file mode 100644
index 0000000..60612b8
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/graceful/signal.go
@@ -0,0 +1,197 @@
+package graceful
+
+import (
+ "os"
+ "os/signal"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "github.com/zenazn/goji/graceful/listener"
+)
+
+var mu sync.Mutex // protects everything that follows
+var listeners = make([]*listener.T, 0)
+var prehooks = make([]func(), 0)
+var posthooks = make([]func(), 0)
+var closing int32
+var doubleKick, timeout time.Duration
+
+var wait = make(chan struct{})
+var stdSignals = []os.Signal{os.Interrupt}
+var sigchan = make(chan os.Signal, 1)
+
+// HandleSignals installs signal handlers for a set of standard signals. By
+// default, this set only includes keyboard interrupts, however when the package
+// detects that it is running under Einhorn, a SIGUSR2 handler is installed as
+// well.
+func HandleSignals() {
+ AddSignal(stdSignals...)
+}
+
+// AddSignal adds the given signal to the set of signals that trigger a graceful
+// shutdown.
+func AddSignal(sig ...os.Signal) {
+ signal.Notify(sigchan, sig...)
+}
+
+// ResetSignals resets the list of signals that trigger a graceful shutdown.
+func ResetSignals() {
+ signal.Stop(sigchan)
+}
+
+// PreHook registers a function to be called before any of this package's normal
+// shutdown actions. All listeners will be called in the order they were added,
+// from a single goroutine.
+func PreHook(f func()) {
+ mu.Lock()
+ defer mu.Unlock()
+
+ prehooks = append(prehooks, f)
+}
+
+// PostHook registers a function to be called after all of this package's normal
+// shutdown actions. All listeners will be called in the order they were added,
+// from a single goroutine, and are guaranteed to be called after all listening
+// connections have been closed, but before Wait() returns.
+//
+// If you've Hijacked any connections that must be gracefully shut down in some
+// other way (since this library disowns all hijacked connections), it's
+// reasonable to use a PostHook to signal and wait for them.
+func PostHook(f func()) {
+ mu.Lock()
+ defer mu.Unlock()
+
+ posthooks = append(posthooks, f)
+}
+
+// Shutdown manually triggers a shutdown from your application. Like Wait,
+// blocks until all connections have gracefully shut down.
+func Shutdown() {
+ shutdown(false)
+}
+
+// ShutdownNow triggers an immediate shutdown from your application. All
+// connections (not just those that are idle) are immediately closed, even if
+// they are in the middle of serving a request.
+func ShutdownNow() {
+ shutdown(true)
+}
+
+// DoubleKickWindow sets the length of the window during which two back-to-back
+// signals are treated as an especially urgent or forceful request to exit
+// (i.e., ShutdownNow instead of Shutdown). Signals delivered more than this
+// duration apart are treated as separate requests to exit gracefully as usual.
+//
+// Setting DoubleKickWindow to 0 disables the feature.
+func DoubleKickWindow(d time.Duration) {
+ if d < 0 {
+ return
+ }
+ mu.Lock()
+ defer mu.Unlock()
+
+ doubleKick = d
+}
+
+// Timeout sets the maximum amount of time package graceful will wait for
+// connections to gracefully shut down after receiving a signal. After this
+// timeout, connections will be forcefully shut down (similar to calling
+// ShutdownNow).
+//
+// Setting Timeout to 0 disables the feature.
+func Timeout(d time.Duration) {
+ if d < 0 {
+ return
+ }
+ mu.Lock()
+ defer mu.Unlock()
+
+ timeout = d
+}
+
+// Wait for all connections to gracefully shut down. This is commonly called at
+// the bottom of the main() function to prevent the program from exiting
+// prematurely.
+func Wait() {
+ <-wait
+}
+
+func init() {
+ go sigLoop()
+}
+func sigLoop() {
+ var last time.Time
+ for {
+ <-sigchan
+ now := time.Now()
+ mu.Lock()
+ force := doubleKick != 0 && now.Sub(last) < doubleKick
+ if t := timeout; t != 0 && !force {
+ go func() {
+ time.Sleep(t)
+ shutdown(true)
+ }()
+ }
+ mu.Unlock()
+ go shutdown(force)
+ last = now
+ }
+}
+
+var preOnce, closeOnce, forceOnce, postOnce, notifyOnce sync.Once
+
+func shutdown(force bool) {
+ preOnce.Do(func() {
+ mu.Lock()
+ defer mu.Unlock()
+ for _, f := range prehooks {
+ f()
+ }
+ })
+
+ if force {
+ forceOnce.Do(func() {
+ closeListeners(force)
+ })
+ } else {
+ closeOnce.Do(func() {
+ closeListeners(force)
+ })
+ }
+
+ postOnce.Do(func() {
+ mu.Lock()
+ defer mu.Unlock()
+ for _, f := range posthooks {
+ f()
+ }
+ })
+
+ notifyOnce.Do(func() {
+ close(wait)
+ })
+}
+
+func closeListeners(force bool) {
+ atomic.StoreInt32(&closing, 1)
+
+ var wg sync.WaitGroup
+ defer wg.Wait()
+
+ mu.Lock()
+ defer mu.Unlock()
+ wg.Add(len(listeners))
+
+ for _, l := range listeners {
+ go func(l *listener.T) {
+ defer wg.Done()
+ l.Close()
+ if force {
+ l.DrainAll()
+ } else {
+ l.Drain()
+ }
+ }(l)
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/serve.go b/vendor/github.com/zenazn/goji/serve.go
new file mode 100644
index 0000000..da73a9b
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/serve.go
@@ -0,0 +1,64 @@
+// +build !appengine
+
+package goji
+
+import (
+ "crypto/tls"
+ "flag"
+ "log"
+ "net"
+ "net/http"
+ "time"
+
+ "github.com/zenazn/goji/bind"
+ "github.com/zenazn/goji/graceful"
+)
+
+func init() {
+ bind.WithFlag()
+ if fl := log.Flags(); fl&log.Ltime != 0 {
+ log.SetFlags(fl | log.Lmicroseconds)
+ }
+ graceful.DoubleKickWindow(2 * time.Second)
+}
+
+// Serve starts Goji using reasonable defaults.
+func Serve() {
+ if !flag.Parsed() {
+ flag.Parse()
+ }
+
+ ServeListener(bind.Default())
+}
+
+// Like Serve, but enables TLS using the given config.
+func ServeTLS(config *tls.Config) {
+ if !flag.Parsed() {
+ flag.Parse()
+ }
+
+ ServeListener(tls.NewListener(bind.Default(), config))
+}
+
+// Like Serve, but runs Goji on top of an arbitrary net.Listener.
+func ServeListener(listener net.Listener) {
+ DefaultMux.Compile()
+ // Install our handler at the root of the standard net/http default mux.
+ // This allows packages like expvar to continue working as expected.
+ http.Handle("/", DefaultMux)
+
+ log.Println("Starting Goji on", listener.Addr())
+
+ graceful.HandleSignals()
+ bind.Ready()
+ graceful.PreHook(func() { log.Printf("Goji received signal, gracefully stopping") })
+ graceful.PostHook(func() { log.Printf("Goji stopped") })
+
+ err := graceful.Serve(listener, http.DefaultServeMux)
+
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ graceful.Wait()
+}
diff --git a/vendor/github.com/zenazn/goji/serve_appengine.go b/vendor/github.com/zenazn/goji/serve_appengine.go
new file mode 100644
index 0000000..88dc7a8
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/serve_appengine.go
@@ -0,0 +1,23 @@
+// +build appengine
+
+package goji
+
+import (
+ "log"
+ "net/http"
+)
+
+func init() {
+ if fl := log.Flags(); fl&log.Ltime != 0 {
+ log.SetFlags(fl | log.Lmicroseconds)
+ }
+}
+
+// Serve starts Goji using reasonable defaults.
+func Serve() {
+ DefaultMux.Compile()
+ // Install our handler at the root of the standard net/http default mux.
+ // This is required for App Engine, and also allows packages like expvar
+ // to continue working as expected.
+ http.Handle("/", DefaultMux)
+}
diff --git a/vendor/github.com/zenazn/goji/web/atomic.go b/vendor/github.com/zenazn/goji/web/atomic.go
new file mode 100644
index 0000000..795d8e5
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/atomic.go
@@ -0,0 +1,18 @@
+// +build !appengine
+
+package web
+
+import (
+ "sync/atomic"
+ "unsafe"
+)
+
+func (rt *router) getMachine() *routeMachine {
+ ptr := (*unsafe.Pointer)(unsafe.Pointer(&rt.machine))
+ sm := (*routeMachine)(atomic.LoadPointer(ptr))
+ return sm
+}
+func (rt *router) setMachine(m *routeMachine) {
+ ptr := (*unsafe.Pointer)(unsafe.Pointer(&rt.machine))
+ atomic.StorePointer(ptr, unsafe.Pointer(m))
+}
diff --git a/vendor/github.com/zenazn/goji/web/atomic_appengine.go b/vendor/github.com/zenazn/goji/web/atomic_appengine.go
new file mode 100644
index 0000000..027127a
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/atomic_appengine.go
@@ -0,0 +1,14 @@
+// +build appengine
+
+package web
+
+func (rt *router) getMachine() *routeMachine {
+ rt.lock.Lock()
+ defer rt.lock.Unlock()
+ return rt.machine
+}
+
+// We always hold the lock when calling setMachine.
+func (rt *router) setMachine(m *routeMachine) {
+ rt.machine = m
+}
diff --git a/vendor/github.com/zenazn/goji/web/bytecode_compiler.go b/vendor/github.com/zenazn/goji/web/bytecode_compiler.go
new file mode 100644
index 0000000..b6f52b1
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/bytecode_compiler.go
@@ -0,0 +1,265 @@
+package web
+
+/*
+This file implements a fast router by encoding a list of routes first into a
+pseudo-trie, then encoding that pseudo-trie into a state machine realized as
+a routing bytecode.
+
+The most interesting part of this router is not its speed (it is quite fast),
+but the guarantees it provides. In a naive router, routes are examined one after
+another until a match is found, and this is the programming model we want to
+support. For any given request ("GET /hello/carl"), there is a list of
+"plausible" routes: routes which match the method ("GET"), and which have a
+prefix that is a prefix of the requested path ("/" and "/hello/", for instance,
+but not "/foobar"). Patterns also have some amount of arbitrary code associated
+with them, which tells us whether or not the route matched. Just like the naive
+router, our goal is to call each plausible pattern, in the order they were
+added, until we find one that matches. The "fast" part here is being smart about
+which non-plausible routes we can skip.
+
+First, we sort routes using a pairwise comparison function: sorting occurs as
+normal on the prefixes, with the caveat that a route may not be moved past a
+route that might also match the same string. Among other things, this means
+we're forced to use particularly dumb sorting algorithms, but it only has to
+happen once, and there probably aren't even that many routes to begin with. This
+logic appears inline in the router's handle() function.
+
+We then build a pseudo-trie from the sorted list of routes. It's not quite a
+normal trie because there are certain routes we cannot reorder around other
+routes (since we're providing identical semantics to the naive router), but it's
+close enough and the basic idea is the same.
+
+Finally, we lower this psuedo-trie from its tree representation to a state
+machine bytecode. The bytecode is pretty simple: it contains up to three bytes,
+a choice of a bunch of flags, and an index. The state machine is pretty simple:
+if the bytes match the next few bytes after the cursor, the instruction matches,
+and the state machine advances to the next instruction. If it does not match, it
+jumps to the instruction at the index. Various flags modify this basic behavior,
+the documentation for which can be found below.
+
+The thing we're optimizing for here over pretty much everything else is memory
+locality. We make an effort to lay out both the trie child selection logic and
+the matching of long strings consecutively in memory, making both operations
+very cheap. In fact, our matching logic isn't particularly asymptotically good,
+but in practice the benefits of memory locality outweigh just about everything
+else.
+
+Unfortunately, the code implementing all of this is pretty bad (both inefficient
+and hard to read). Maybe someday I'll come and take a second pass at it.
+*/
+type state struct {
+ mode smMode
+ bs [3]byte
+ i int32
+}
+type stateMachine []state
+
+type smMode uint8
+
+// Many combinations of smModes don't make sense, but since this is interal to
+// the library I don't feel like documenting them.
+const (
+ // The two low bits of the mode are used as a length of how many bytes
+ // of bs are used. If the length is 0, the node is treated as a
+ // wildcard.
+ smLengthMask smMode = 3
+)
+
+const (
+ // Jump to the given index on a match. Ordinarily, the state machine
+ // will jump to the state given by the index if the characters do not
+ // match.
+ smJumpOnMatch smMode = 4 << iota
+ // The index is the index of a route to try. If running the route fails,
+ // the state machine advances by one.
+ smRoute
+ // Reset the state machine's cursor into the input string to the state's
+ // index value.
+ smSetCursor
+ // If this bit is set, the machine transitions into a non-accepting
+ // state if it matches.
+ smFail
+)
+
+type trie struct {
+ prefix string
+ children []trieSegment
+}
+
+// A trie segment is a route matching this point (or -1), combined with a list
+// of trie children that follow that route.
+type trieSegment struct {
+ route int
+ children []trie
+}
+
+func buildTrie(routes []route, dp, dr int) trie {
+ var t trie
+ ts := trieSegment{-1, nil}
+ for i, r := range routes {
+ if len(r.prefix) != dp {
+ continue
+ }
+
+ if i == 0 {
+ ts.route = 0
+ } else {
+ subroutes := routes[ts.route+1 : i]
+ ts.children = buildTrieSegment(subroutes, dp, dr+ts.route+1)
+ t.children = append(t.children, ts)
+ ts = trieSegment{i, nil}
+ }
+ }
+
+ // This could be a little DRYer...
+ subroutes := routes[ts.route+1:]
+ ts.children = buildTrieSegment(subroutes, dp, dr+ts.route+1)
+ t.children = append(t.children, ts)
+
+ for i := range t.children {
+ if t.children[i].route != -1 {
+ t.children[i].route += dr
+ }
+ }
+
+ return t
+}
+
+func commonPrefix(s1, s2 string) string {
+ if len(s1) > len(s2) {
+ return commonPrefix(s2, s1)
+ }
+ for i := 0; i < len(s1); i++ {
+ if s1[i] != s2[i] {
+ return s1[:i]
+ }
+ }
+ return s1
+}
+
+func buildTrieSegment(routes []route, dp, dr int) []trie {
+ if len(routes) == 0 {
+ return nil
+ }
+ var tries []trie
+
+ start := 0
+ p := routes[0].prefix[dp:]
+ for i := 1; i < len(routes); i++ {
+ ip := routes[i].prefix[dp:]
+ cp := commonPrefix(p, ip)
+ if len(cp) == 0 {
+ t := buildTrie(routes[start:i], dp+len(p), dr+start)
+ t.prefix = p
+ tries = append(tries, t)
+ start = i
+ p = ip
+ } else {
+ p = cp
+ }
+ }
+
+ t := buildTrie(routes[start:], dp+len(p), dr+start)
+ t.prefix = p
+ return append(tries, t)
+}
+
+// This is a bit confusing, since the encode method on a trie deals exclusively
+// with trieSegments (i.e., its children), and vice versa.
+//
+// These methods are also hideously inefficient, both in terms of memory usage
+// and algorithmic complexity. If it ever becomes a problem, maybe we can do
+// something smarter than stupid O(N^2) appends, but to be honest, I bet N is
+// small (it almost always is :P) and we only do it once at boot anyways.
+
+func (t trie) encode(dp, off int) stateMachine {
+ ms := make([]stateMachine, len(t.children))
+ subs := make([]stateMachine, len(t.children))
+ var l, msl, subl int
+
+ for i, ts := range t.children {
+ ms[i], subs[i] = ts.encode(dp, 0)
+ msl += len(ms[i])
+ l += len(ms[i]) + len(subs[i])
+ }
+
+ l++
+
+ m := make(stateMachine, 0, l)
+ for i, mm := range ms {
+ for j := range mm {
+ if mm[j].mode&(smRoute|smSetCursor) != 0 {
+ continue
+ }
+
+ mm[j].i += int32(off + msl + subl + 1)
+ }
+ m = append(m, mm...)
+ subl += len(subs[i])
+ }
+
+ m = append(m, state{mode: smJumpOnMatch, i: -1})
+
+ msl = 0
+ for i, sub := range subs {
+ msl += len(ms[i])
+ for j := range sub {
+ if sub[j].mode&(smRoute|smSetCursor) != 0 {
+ continue
+ }
+ if sub[j].i == -1 {
+ sub[j].i = int32(off + msl)
+ } else {
+ sub[j].i += int32(off + len(m))
+ }
+ }
+ m = append(m, sub...)
+ }
+
+ return m
+}
+
+func (ts trieSegment) encode(dp, off int) (me stateMachine, sub stateMachine) {
+ o := 1
+ if ts.route != -1 {
+ o++
+ }
+ me = make(stateMachine, len(ts.children)+o)
+
+ me[0] = state{mode: smSetCursor, i: int32(dp)}
+ if ts.route != -1 {
+ me[1] = state{mode: smRoute, i: int32(ts.route)}
+ }
+
+ for i, t := range ts.children {
+ p := t.prefix
+
+ bc := copy(me[i+o].bs[:], p)
+ me[i+o].mode = smMode(bc) | smJumpOnMatch
+ me[i+o].i = int32(off + len(sub))
+
+ for len(p) > bc {
+ var bs [3]byte
+ p = p[bc:]
+ bc = copy(bs[:], p)
+ sub = append(sub, state{bs: bs, mode: smMode(bc), i: -1})
+ }
+
+ sub = append(sub, t.encode(dp+len(t.prefix), off+len(sub))...)
+ }
+ return
+}
+
+func compile(routes []route) stateMachine {
+ if len(routes) == 0 {
+ return nil
+ }
+ t := buildTrie(routes, 0, 0)
+ m := t.encode(0, 0)
+ for i := range m {
+ if m[i].i == -1 {
+ m[i].mode = m[i].mode | smFail
+ }
+ }
+ return m
+}
diff --git a/vendor/github.com/zenazn/goji/web/bytecode_runner.go b/vendor/github.com/zenazn/goji/web/bytecode_runner.go
new file mode 100644
index 0000000..c32b16a
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/bytecode_runner.go
@@ -0,0 +1,83 @@
+package web
+
+import "net/http"
+
+type routeMachine struct {
+ sm stateMachine
+ routes []route
+}
+
+func matchRoute(route route, m method, ms *method, r *http.Request, c *C) bool {
+ if !route.pattern.Match(r, c) {
+ return false
+ }
+ *ms |= route.method
+
+ if route.method&m != 0 {
+ route.pattern.Run(r, c)
+ return true
+ }
+ return false
+}
+
+func (rm routeMachine) route(c *C, w http.ResponseWriter, r *http.Request) (method, *route) {
+ m := httpMethod(r.Method)
+ var methods method
+ p := r.URL.Path
+
+ if len(rm.sm) == 0 {
+ return methods, nil
+ }
+
+ var i int
+ for {
+ sm := rm.sm[i].mode
+ if sm&smSetCursor != 0 {
+ si := rm.sm[i].i
+ p = r.URL.Path[si:]
+ i++
+ continue
+ }
+
+ length := int(sm & smLengthMask)
+ match := false
+ if length <= len(p) {
+ bs := rm.sm[i].bs
+ switch length {
+ case 3:
+ if p[2] != bs[2] {
+ break
+ }
+ fallthrough
+ case 2:
+ if p[1] != bs[1] {
+ break
+ }
+ fallthrough
+ case 1:
+ if p[0] != bs[0] {
+ break
+ }
+ fallthrough
+ case 0:
+ p = p[length:]
+ match = true
+ }
+ }
+
+ if match && sm&smRoute != 0 {
+ si := rm.sm[i].i
+ if matchRoute(rm.routes[si], m, &methods, r, c) {
+ return 0, &rm.routes[si]
+ }
+ i++
+ } else if match != (sm&smJumpOnMatch == 0) {
+ if sm&smFail != 0 {
+ return methods, nil
+ }
+ i = int(rm.sm[i].i)
+ } else {
+ i++
+ }
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/chanpool.go b/vendor/github.com/zenazn/goji/web/chanpool.go
new file mode 100644
index 0000000..6c53c74
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/chanpool.go
@@ -0,0 +1,31 @@
+// +build !go1.3
+
+package web
+
+// This is an alternate implementation of Go 1.3's sync.Pool.
+
+// Maximum size of the pool of spare middleware stacks
+const cPoolSize = 32
+
+type cPool chan *cStack
+
+func makeCPool() *cPool {
+ p := make(cPool, cPoolSize)
+ return &p
+}
+
+func (c cPool) alloc() *cStack {
+ select {
+ case cs := <-c:
+ return cs
+ default:
+ return nil
+ }
+}
+
+func (c cPool) release(cs *cStack) {
+ select {
+ case c <- cs:
+ default:
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/cpool.go b/vendor/github.com/zenazn/goji/web/cpool.go
new file mode 100644
index 0000000..59f8764
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/cpool.go
@@ -0,0 +1,23 @@
+// +build go1.3
+
+package web
+
+import "sync"
+
+type cPool sync.Pool
+
+func makeCPool() *cPool {
+ return &cPool{}
+}
+
+func (c *cPool) alloc() *cStack {
+ cs := (*sync.Pool)(c).Get()
+ if cs == nil {
+ return nil
+ }
+ return cs.(*cStack)
+}
+
+func (c *cPool) release(cs *cStack) {
+ (*sync.Pool)(c).Put(cs)
+}
diff --git a/vendor/github.com/zenazn/goji/web/func_equal.go b/vendor/github.com/zenazn/goji/web/func_equal.go
new file mode 100644
index 0000000..9c8f7cb
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/func_equal.go
@@ -0,0 +1,32 @@
+package web
+
+import (
+ "reflect"
+)
+
+/*
+This is more than a little sketchtacular. Go's rules for function pointer
+equality are pretty restrictive: nil function pointers always compare equal, and
+all other pointer types never do. However, this is pretty limiting: it means
+that we can't let people reference the middleware they've given us since we have
+no idea which function they're referring to.
+
+To get better data out of Go, we sketch on the representation of interfaces. We
+happen to know that interfaces are pairs of pointers: one to the real data, one
+to data about the type. Therefore, two interfaces, including two function
+interface{}'s, point to exactly the same objects iff their interface
+representations are identical. And it turns out this is sufficient for our
+purposes.
+
+If you're curious, you can read more about the representation of functions here:
+http://golang.org/s/go11func
+We're in effect comparing the pointers of the indirect layer.
+
+This function also works on non-function values.
+*/
+func funcEqual(a, b interface{}) bool {
+ av := reflect.ValueOf(&a).Elem()
+ bv := reflect.ValueOf(&b).Elem()
+
+ return av.InterfaceData() == bv.InterfaceData()
+}
diff --git a/vendor/github.com/zenazn/goji/web/handler.go b/vendor/github.com/zenazn/goji/web/handler.go
new file mode 100644
index 0000000..746c9f0
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/handler.go
@@ -0,0 +1,42 @@
+package web
+
+import (
+ "log"
+ "net/http"
+)
+
+const unknownHandler = `Unknown handler type %T. See http://godoc.org/github.com/zenazn/goji/web#HandlerType for a list of acceptable types.`
+
+type netHTTPHandlerWrap struct{ http.Handler }
+type netHTTPHandlerFuncWrap struct {
+ fn func(http.ResponseWriter, *http.Request)
+}
+type handlerFuncWrap struct {
+ fn func(C, http.ResponseWriter, *http.Request)
+}
+
+func (h netHTTPHandlerWrap) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {
+ h.Handler.ServeHTTP(w, r)
+}
+func (h netHTTPHandlerFuncWrap) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {
+ h.fn(w, r)
+}
+func (h handlerFuncWrap) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {
+ h.fn(c, w, r)
+}
+
+func parseHandler(h HandlerType) Handler {
+ switch f := h.(type) {
+ case func(c C, w http.ResponseWriter, r *http.Request):
+ return handlerFuncWrap{f}
+ case func(w http.ResponseWriter, r *http.Request):
+ return netHTTPHandlerFuncWrap{f}
+ case Handler:
+ return f
+ case http.Handler:
+ return netHTTPHandlerWrap{f}
+ default:
+ log.Fatalf(unknownHandler, h)
+ panic("log.Fatalf does not return")
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/match.go b/vendor/github.com/zenazn/goji/web/match.go
new file mode 100644
index 0000000..1a44144
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/match.go
@@ -0,0 +1,66 @@
+package web
+
+// The key used to store route Matches in the Goji environment. If this key is
+// present in the environment and contains a value of type Match, routing will
+// not be performed, and the Match's Handler will be used instead.
+const MatchKey = "goji.web.Match"
+
+// Match is the type of routing matches. It is inserted into C.Env under
+// MatchKey when the Mux.Router middleware is invoked. If MatchKey is present at
+// route dispatch time, the Handler of the corresponding Match will be called
+// instead of performing routing as usual.
+//
+// By computing a Match and inserting it into the Goji environment as part of a
+// middleware stack (see Mux.Router, for instance), it is possible to customize
+// Goji's routing behavior or replace it entirely.
+type Match struct {
+ // Pattern is the Pattern that matched during routing. Will be nil if no
+ // route matched (Handler will be set to the Mux's NotFound handler)
+ Pattern Pattern
+ // The Handler corresponding to the matched pattern.
+ Handler Handler
+}
+
+// GetMatch returns the Match stored in the Goji environment, or an empty Match
+// if none exists (valid Matches always have a Handler property).
+func GetMatch(c C) Match {
+ if c.Env == nil {
+ return Match{}
+ }
+ mi, ok := c.Env[MatchKey]
+ if !ok {
+ return Match{}
+ }
+ if m, ok := mi.(Match); ok {
+ return m
+ }
+ return Match{}
+}
+
+// RawPattern returns the PatternType that was originally passed to ParsePattern
+// or any of the HTTP method functions (Get, Post, etc.).
+func (m Match) RawPattern() PatternType {
+ switch v := m.Pattern.(type) {
+ case regexpPattern:
+ return v.re
+ case stringPattern:
+ return v.raw
+ default:
+ return v
+ }
+}
+
+// RawHandler returns the HandlerType that was originally passed to the HTTP
+// method functions (Get, Post, etc.).
+func (m Match) RawHandler() HandlerType {
+ switch v := m.Handler.(type) {
+ case netHTTPHandlerWrap:
+ return v.Handler
+ case handlerFuncWrap:
+ return v.fn
+ case netHTTPHandlerFuncWrap:
+ return v.fn
+ default:
+ return v
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware.go b/vendor/github.com/zenazn/goji/web/middleware.go
new file mode 100644
index 0000000..7ec545d
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware.go
@@ -0,0 +1,154 @@
+package web
+
+import (
+ "fmt"
+ "log"
+ "net/http"
+ "sync"
+)
+
+// mLayer is a single middleware stack layer. It contains a canonicalized
+// middleware representation, as well as the original function as passed to us.
+type mLayer struct {
+ fn func(*C, http.Handler) http.Handler
+ orig interface{}
+}
+
+// mStack is an entire middleware stack. It contains a slice of middleware
+// layers (outermost first) protected by a mutex, a cache of pre-built stack
+// instances, and a final routing function.
+type mStack struct {
+ lock sync.Mutex
+ stack []mLayer
+ pool *cPool
+ router internalRouter
+}
+
+type internalRouter interface {
+ route(*C, http.ResponseWriter, *http.Request)
+}
+
+/*
+cStack is a cached middleware stack instance. Constructing a middleware stack
+involves a lot of allocations: at the very least each layer will have to close
+over the layer after (inside) it and a stack N levels deep will incur at least N
+separate allocations. Instead of doing this on every request, we keep a pool of
+pre-built stacks around for reuse.
+*/
+type cStack struct {
+ C
+ m http.Handler
+ pool *cPool
+}
+
+func (s *cStack) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ s.C = C{}
+ s.m.ServeHTTP(w, r)
+}
+func (s *cStack) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {
+ s.C = c
+ s.m.ServeHTTP(w, r)
+}
+
+const unknownMiddleware = `Unknown middleware type %T. See http://godoc.org/github.com/zenazn/goji/web#MiddlewareType for a list of acceptable types.`
+
+func (m *mStack) appendLayer(fn interface{}) {
+ ml := mLayer{orig: fn}
+ switch f := fn.(type) {
+ case func(http.Handler) http.Handler:
+ ml.fn = func(c *C, h http.Handler) http.Handler {
+ return f(h)
+ }
+ case func(*C, http.Handler) http.Handler:
+ ml.fn = f
+ default:
+ log.Fatalf(unknownMiddleware, fn)
+ }
+ m.stack = append(m.stack, ml)
+}
+
+func (m *mStack) findLayer(l interface{}) int {
+ for i, middleware := range m.stack {
+ if funcEqual(l, middleware.orig) {
+ return i
+ }
+ }
+ return -1
+}
+
+func (m *mStack) invalidate() {
+ m.pool = makeCPool()
+}
+
+func (m *mStack) newStack() *cStack {
+ cs := cStack{}
+ router := m.router
+
+ cs.m = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ router.route(&cs.C, w, r)
+ })
+ for i := len(m.stack) - 1; i >= 0; i-- {
+ cs.m = m.stack[i].fn(&cs.C, cs.m)
+ }
+
+ return &cs
+}
+
+func (m *mStack) alloc() *cStack {
+ p := m.pool
+ cs := p.alloc()
+ if cs == nil {
+ cs = m.newStack()
+ }
+
+ cs.pool = p
+ return cs
+}
+
+func (m *mStack) release(cs *cStack) {
+ cs.C = C{}
+ if cs.pool != m.pool {
+ return
+ }
+ cs.pool.release(cs)
+ cs.pool = nil
+}
+
+func (m *mStack) Use(middleware interface{}) {
+ m.lock.Lock()
+ defer m.lock.Unlock()
+ m.appendLayer(middleware)
+ m.invalidate()
+}
+
+func (m *mStack) Insert(middleware, before interface{}) error {
+ m.lock.Lock()
+ defer m.lock.Unlock()
+ i := m.findLayer(before)
+ if i < 0 {
+ return fmt.Errorf("web: unknown middleware %v", before)
+ }
+
+ m.appendLayer(middleware)
+ inserted := m.stack[len(m.stack)-1]
+ copy(m.stack[i+1:], m.stack[i:])
+ m.stack[i] = inserted
+
+ m.invalidate()
+ return nil
+}
+
+func (m *mStack) Abandon(middleware interface{}) error {
+ m.lock.Lock()
+ defer m.lock.Unlock()
+ i := m.findLayer(middleware)
+ if i < 0 {
+ return fmt.Errorf("web: unknown middleware %v", middleware)
+ }
+
+ copy(m.stack[i:], m.stack[i+1:])
+ m.stack = m.stack[:len(m.stack)-1 : len(m.stack)]
+
+ m.invalidate()
+ return nil
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/envinit.go b/vendor/github.com/zenazn/goji/web/middleware/envinit.go
new file mode 100644
index 0000000..ae3b683
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/envinit.go
@@ -0,0 +1,27 @@
+package middleware
+
+import (
+ "net/http"
+
+ "github.com/zenazn/goji/web"
+)
+
+type envInit struct {
+ c *web.C
+ h http.Handler
+}
+
+func (e envInit) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if e.c.Env == nil {
+ e.c.Env = make(map[interface{}]interface{})
+ }
+ e.h.ServeHTTP(w, r)
+}
+
+// EnvInit is a middleware that allocates an environment map if it is nil. While
+// it's impossible in general to ensure that Env is never nil in a middleware
+// stack, in most common cases placing this middleware at the top of the stack
+// will eliminate the need for repetative nil checks.
+func EnvInit(c *web.C, h http.Handler) http.Handler {
+ return envInit{c, h}
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/logger.go b/vendor/github.com/zenazn/goji/web/middleware/logger.go
new file mode 100644
index 0000000..8bbcac8
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/logger.go
@@ -0,0 +1,92 @@
+package middleware
+
+import (
+ "bytes"
+ "log"
+ "net/http"
+ "time"
+
+ "github.com/zenazn/goji/web"
+ "github.com/zenazn/goji/web/mutil"
+)
+
+// Logger is a middleware that logs the start and end of each request, along
+// with some useful data about what was requested, what the response status was,
+// and how long it took to return. When standard output is a TTY, Logger will
+// print in color, otherwise it will print in black and white.
+//
+// Logger prints a request ID if one is provided.
+//
+// Logger has been designed explicitly to be Good Enough for use in small
+// applications and for people just getting started with Goji. It is expected
+// that applications will eventually outgrow this middleware and replace it with
+// a custom request logger, such as one that produces machine-parseable output,
+// outputs logs to a different service (e.g., syslog), or formats lines like
+// those printed elsewhere in the application.
+func Logger(c *web.C, h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ reqID := GetReqID(*c)
+
+ printStart(reqID, r)
+
+ lw := mutil.WrapWriter(w)
+
+ t1 := time.Now()
+ h.ServeHTTP(lw, r)
+
+ if lw.Status() == 0 {
+ lw.WriteHeader(http.StatusOK)
+ }
+ t2 := time.Now()
+
+ printEnd(reqID, lw, t2.Sub(t1))
+ }
+
+ return http.HandlerFunc(fn)
+}
+
+func printStart(reqID string, r *http.Request) {
+ var buf bytes.Buffer
+
+ if reqID != "" {
+ cW(&buf, bBlack, "[%s] ", reqID)
+ }
+ buf.WriteString("Started ")
+ cW(&buf, bMagenta, "%s ", r.Method)
+ cW(&buf, nBlue, "%q ", r.URL.String())
+ buf.WriteString("from ")
+ buf.WriteString(r.RemoteAddr)
+
+ log.Print(buf.String())
+}
+
+func printEnd(reqID string, w mutil.WriterProxy, dt time.Duration) {
+ var buf bytes.Buffer
+
+ if reqID != "" {
+ cW(&buf, bBlack, "[%s] ", reqID)
+ }
+ buf.WriteString("Returning ")
+ status := w.Status()
+ if status < 200 {
+ cW(&buf, bBlue, "%03d", status)
+ } else if status < 300 {
+ cW(&buf, bGreen, "%03d", status)
+ } else if status < 400 {
+ cW(&buf, bCyan, "%03d", status)
+ } else if status < 500 {
+ cW(&buf, bYellow, "%03d", status)
+ } else {
+ cW(&buf, bRed, "%03d", status)
+ }
+ buf.WriteString(" in ")
+ if dt < 500*time.Millisecond {
+ cW(&buf, nGreen, "%s", dt)
+ } else if dt < 5*time.Second {
+ cW(&buf, nYellow, "%s", dt)
+ } else {
+ cW(&buf, nRed, "%s", dt)
+ }
+
+ log.Print(buf.String())
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/middleware.go b/vendor/github.com/zenazn/goji/web/middleware/middleware.go
new file mode 100644
index 0000000..23cfde2
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/middleware.go
@@ -0,0 +1,4 @@
+/*
+Package middleware provides several standard middleware implementations.
+*/
+package middleware
diff --git a/vendor/github.com/zenazn/goji/web/middleware/nocache.go b/vendor/github.com/zenazn/goji/web/middleware/nocache.go
new file mode 100644
index 0000000..ae3d260
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/nocache.go
@@ -0,0 +1,55 @@
+package middleware
+
+import (
+ "net/http"
+ "time"
+)
+
+// Unix epoch time
+var epoch = time.Unix(0, 0).Format(time.RFC1123)
+
+// Taken from https://github.com/mytrile/nocache
+var noCacheHeaders = map[string]string{
+ "Expires": epoch,
+ "Cache-Control": "no-cache, private, max-age=0",
+ "Pragma": "no-cache",
+ "X-Accel-Expires": "0",
+}
+
+var etagHeaders = []string{
+ "ETag",
+ "If-Modified-Since",
+ "If-Match",
+ "If-None-Match",
+ "If-Range",
+ "If-Unmodified-Since",
+}
+
+// NoCache is a simple piece of middleware that sets a number of HTTP headers to prevent
+// a router (or subrouter) from being cached by an upstream proxy and/or client.
+//
+// As per http://wiki.nginx.org/HttpProxyModule - NoCache sets:
+// Expires: Thu, 01 Jan 1970 00:00:00 UTC
+// Cache-Control: no-cache, private, max-age=0
+// X-Accel-Expires: 0
+// Pragma: no-cache (for HTTP/1.0 proxies/clients)
+func NoCache(h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+
+ // Delete any ETag headers that may have been set
+ for _, v := range etagHeaders {
+ if r.Header.Get(v) != "" {
+ r.Header.Del(v)
+ }
+ }
+
+ // Set our NoCache headers
+ for k, v := range noCacheHeaders {
+ w.Header().Set(k, v)
+ }
+
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/options.go b/vendor/github.com/zenazn/goji/web/middleware/options.go
new file mode 100644
index 0000000..4bdce5f
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/options.go
@@ -0,0 +1,97 @@
+package middleware
+
+import (
+ "net/http"
+ "strings"
+
+ "github.com/zenazn/goji/web"
+)
+
+type autoOptionsState int
+
+const (
+ aosInit autoOptionsState = iota
+ aosHeaderWritten
+ aosProxying
+)
+
+// I originally used an httptest.ResponseRecorder here, but package httptest
+// adds a flag which I'm not particularly eager to expose. This is essentially a
+// ResponseRecorder that has been specialized for the purpose at hand to avoid
+// the httptest dependency.
+type autoOptionsProxy struct {
+ w http.ResponseWriter
+ c *web.C
+ state autoOptionsState
+}
+
+func (p *autoOptionsProxy) Header() http.Header {
+ return p.w.Header()
+}
+
+func (p *autoOptionsProxy) Write(buf []byte) (int, error) {
+ switch p.state {
+ case aosInit:
+ p.state = aosHeaderWritten
+ case aosProxying:
+ return len(buf), nil
+ }
+ return p.w.Write(buf)
+}
+
+func (p *autoOptionsProxy) WriteHeader(code int) {
+ methods := getValidMethods(*p.c)
+ switch p.state {
+ case aosInit:
+ if methods != nil && code == http.StatusNotFound {
+ p.state = aosProxying
+ break
+ }
+ p.state = aosHeaderWritten
+ fallthrough
+ default:
+ p.w.WriteHeader(code)
+ return
+ }
+
+ methods = addMethod(methods, "OPTIONS")
+ p.w.Header().Set("Allow", strings.Join(methods, ", "))
+ p.w.WriteHeader(http.StatusOK)
+}
+
+// AutomaticOptions automatically return an appropriate "Allow" header when the
+// request method is OPTIONS and the request would have otherwise been 404'd.
+func AutomaticOptions(c *web.C, h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == "OPTIONS" {
+ w = &autoOptionsProxy{c: c, w: w}
+ }
+
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
+
+func getValidMethods(c web.C) []string {
+ if c.Env == nil {
+ return nil
+ }
+ v, ok := c.Env[web.ValidMethodsKey]
+ if !ok {
+ return nil
+ }
+ if methods, ok := v.([]string); ok {
+ return methods
+ }
+ return nil
+}
+
+func addMethod(methods []string, method string) []string {
+ for _, m := range methods {
+ if m == method {
+ return methods
+ }
+ }
+ return append(methods, method)
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/realip.go b/vendor/github.com/zenazn/goji/web/middleware/realip.go
new file mode 100644
index 0000000..ae5599f
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/realip.go
@@ -0,0 +1,51 @@
+package middleware
+
+import (
+ "net/http"
+ "strings"
+)
+
+var xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For")
+var xRealIP = http.CanonicalHeaderKey("X-Real-IP")
+
+// RealIP is a middleware that sets a http.Request's RemoteAddr to the results
+// of parsing either the X-Forwarded-For header or the X-Real-IP header (in that
+// order).
+//
+// This middleware should be inserted fairly early in the middleware stack to
+// ensure that subsequent layers (e.g., request loggers) which examine the
+// RemoteAddr will see the intended value.
+//
+// You should only use this middleware if you can trust the headers passed to
+// you (in particular, the two headers this middleware uses), for example
+// because you have placed a reverse proxy like HAProxy or nginx in front of
+// Goji. If your reverse proxies are configured to pass along arbitrary header
+// values from the client, or if you use this middleware without a reverse
+// proxy, malicious clients will be able to make you very sad (or, depending on
+// how you're using RemoteAddr, vulnerable to an attack of some sort).
+func RealIP(h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ if rip := realIP(r); rip != "" {
+ r.RemoteAddr = rip
+ }
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
+
+func realIP(r *http.Request) string {
+ var ip string
+
+ if xff := r.Header.Get(xForwardedFor); xff != "" {
+ i := strings.Index(xff, ", ")
+ if i == -1 {
+ i = len(xff)
+ }
+ ip = xff[:i]
+ } else if xrip := r.Header.Get(xRealIP); xrip != "" {
+ ip = xrip
+ }
+
+ return ip
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/recoverer.go b/vendor/github.com/zenazn/goji/web/middleware/recoverer.go
new file mode 100644
index 0000000..43ad648
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/recoverer.go
@@ -0,0 +1,44 @@
+package middleware
+
+import (
+ "bytes"
+ "log"
+ "net/http"
+ "runtime/debug"
+
+ "github.com/zenazn/goji/web"
+)
+
+// Recoverer is a middleware that recovers from panics, logs the panic (and a
+// backtrace), and returns a HTTP 500 (Internal Server Error) status if
+// possible.
+//
+// Recoverer prints a request ID if one is provided.
+func Recoverer(c *web.C, h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ reqID := GetReqID(*c)
+
+ defer func() {
+ if err := recover(); err != nil {
+ printPanic(reqID, err)
+ debug.PrintStack()
+ http.Error(w, http.StatusText(500), 500)
+ }
+ }()
+
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
+
+func printPanic(reqID string, err interface{}) {
+ var buf bytes.Buffer
+
+ if reqID != "" {
+ cW(&buf, bBlack, "[%s] ", reqID)
+ }
+ cW(&buf, bRed, "panic: %+v", err)
+
+ log.Print(buf.String())
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/request_id.go b/vendor/github.com/zenazn/goji/web/middleware/request_id.go
new file mode 100644
index 0000000..834d8e3
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/request_id.go
@@ -0,0 +1,88 @@
+package middleware
+
+import (
+ "crypto/rand"
+ "encoding/base64"
+ "fmt"
+ "net/http"
+ "os"
+ "strings"
+ "sync/atomic"
+
+ "github.com/zenazn/goji/web"
+)
+
+// Key to use when setting the request ID.
+const RequestIDKey = "reqID"
+
+var prefix string
+var reqid uint64
+
+/*
+A quick note on the statistics here: we're trying to calculate the chance that
+two randomly generated base62 prefixes will collide. We use the formula from
+http://en.wikipedia.org/wiki/Birthday_problem
+
+P[m, n] \approx 1 - e^{-m^2/2n}
+
+We ballpark an upper bound for $m$ by imagining (for whatever reason) a server
+that restarts every second over 10 years, for $m = 86400 * 365 * 10 = 315360000$
+
+For a $k$ character base-62 identifier, we have $n(k) = 62^k$
+
+Plugging this in, we find $P[m, n(10)] \approx 5.75%$, which is good enough for
+our purposes, and is surely more than anyone would ever need in practice -- a
+process that is rebooted a handful of times a day for a hundred years has less
+than a millionth of a percent chance of generating two colliding IDs.
+*/
+
+func init() {
+ hostname, err := os.Hostname()
+ if hostname == "" || err != nil {
+ hostname = "localhost"
+ }
+ var buf [12]byte
+ var b64 string
+ for len(b64) < 10 {
+ rand.Read(buf[:])
+ b64 = base64.StdEncoding.EncodeToString(buf[:])
+ b64 = strings.NewReplacer("+", "", "/", "").Replace(b64)
+ }
+
+ prefix = fmt.Sprintf("%s/%s", hostname, b64[0:10])
+}
+
+// RequestID is a middleware that injects a request ID into the context of each
+// request. A request ID is a string of the form "host.example.com/random-0001",
+// where "random" is a base62 random string that uniquely identifies this go
+// process, and where the last number is an atomically incremented request
+// counter.
+func RequestID(c *web.C, h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ if c.Env == nil {
+ c.Env = make(map[interface{}]interface{})
+ }
+ myid := atomic.AddUint64(&reqid, 1)
+ c.Env[RequestIDKey] = fmt.Sprintf("%s-%06d", prefix, myid)
+
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
+
+// GetReqID returns a request ID from the given context if one is present.
+// Returns the empty string if a request ID cannot be found.
+func GetReqID(c web.C) string {
+ if c.Env == nil {
+ return ""
+ }
+ v, ok := c.Env[RequestIDKey]
+ if !ok {
+ return ""
+ }
+ if reqID, ok := v.(string); ok {
+ return reqID
+ }
+ return ""
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/subrouter.go b/vendor/github.com/zenazn/goji/web/middleware/subrouter.go
new file mode 100644
index 0000000..e5b0921
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/subrouter.go
@@ -0,0 +1,65 @@
+package middleware
+
+import (
+ "net/http"
+
+ "github.com/zenazn/goji/web"
+)
+
+type subrouter struct {
+ c *web.C
+ h http.Handler
+}
+
+func (s subrouter) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if s.c.URLParams != nil {
+ path, ok := s.c.URLParams["*"]
+ if !ok {
+ path, ok = s.c.URLParams["_"]
+ }
+ if ok {
+ oldpath := r.URL.Path
+ oldmatch := web.GetMatch(*s.c)
+ r.URL.Path = path
+ if oldmatch.Handler != nil {
+ delete(s.c.Env, web.MatchKey)
+ }
+
+ defer func() {
+ r.URL.Path = oldpath
+
+ if s.c.Env == nil {
+ return
+ }
+ if oldmatch.Handler != nil {
+ s.c.Env[web.MatchKey] = oldmatch
+ } else {
+ delete(s.c.Env, web.MatchKey)
+ }
+ }()
+ }
+ }
+ s.h.ServeHTTP(w, r)
+}
+
+/*
+SubRouter is a helper middleware that makes writing sub-routers easier.
+
+If you register a sub-router under a key like "/admin/*", Goji's router will
+automatically set c.URLParams["*"] to the unmatched path suffix. This middleware
+will help you set the request URL's Path to this unmatched suffix, allowing you
+to write sub-routers with no knowledge of what routes the parent router matches.
+
+Since Go's regular expressions do not allow you to create a capturing group
+named "*", SubRouter also accepts the string "_". For instance, to duplicate the
+semantics of the string pattern "/foo/*", you might use the regular expression
+"^/foo(?P<_>/.*)$".
+
+This middleware is Match-aware: it will un-set any explicit routing information
+contained in the Goji context in order to prevent routing loops when using
+explicit routing with sub-routers. See the documentation for Mux.Router for
+more.
+*/
+func SubRouter(c *web.C, h http.Handler) http.Handler {
+ return subrouter{c, h}
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/terminal.go b/vendor/github.com/zenazn/goji/web/middleware/terminal.go
new file mode 100644
index 0000000..db02917
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/terminal.go
@@ -0,0 +1,60 @@
+package middleware
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+)
+
+var (
+ // Normal colors
+ nBlack = []byte{'\033', '[', '3', '0', 'm'}
+ nRed = []byte{'\033', '[', '3', '1', 'm'}
+ nGreen = []byte{'\033', '[', '3', '2', 'm'}
+ nYellow = []byte{'\033', '[', '3', '3', 'm'}
+ nBlue = []byte{'\033', '[', '3', '4', 'm'}
+ nMagenta = []byte{'\033', '[', '3', '5', 'm'}
+ nCyan = []byte{'\033', '[', '3', '6', 'm'}
+ nWhite = []byte{'\033', '[', '3', '7', 'm'}
+ // Bright colors
+ bBlack = []byte{'\033', '[', '3', '0', ';', '1', 'm'}
+ bRed = []byte{'\033', '[', '3', '1', ';', '1', 'm'}
+ bGreen = []byte{'\033', '[', '3', '2', ';', '1', 'm'}
+ bYellow = []byte{'\033', '[', '3', '3', ';', '1', 'm'}
+ bBlue = []byte{'\033', '[', '3', '4', ';', '1', 'm'}
+ bMagenta = []byte{'\033', '[', '3', '5', ';', '1', 'm'}
+ bCyan = []byte{'\033', '[', '3', '6', ';', '1', 'm'}
+ bWhite = []byte{'\033', '[', '3', '7', ';', '1', 'm'}
+
+ reset = []byte{'\033', '[', '0', 'm'}
+)
+
+var isTTY bool
+
+func init() {
+ // This is sort of cheating: if stdout is a character device, we assume
+ // that means it's a TTY. Unfortunately, there are many non-TTY
+ // character devices, but fortunately stdout is rarely set to any of
+ // them.
+ //
+ // We could solve this properly by pulling in a dependency on
+ // code.google.com/p/go.crypto/ssh/terminal, for instance, but as a
+ // heuristic for whether to print in color or in black-and-white, I'd
+ // really rather not.
+ fi, err := os.Stdout.Stat()
+ if err == nil {
+ m := os.ModeDevice | os.ModeCharDevice
+ isTTY = fi.Mode()&m == m
+ }
+}
+
+// colorWrite
+func cW(buf *bytes.Buffer, color []byte, s string, args ...interface{}) {
+ if isTTY {
+ buf.Write(color)
+ }
+ fmt.Fprintf(buf, s, args...)
+ if isTTY {
+ buf.Write(reset)
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/middleware/urlquery.go b/vendor/github.com/zenazn/goji/web/middleware/urlquery.go
new file mode 100644
index 0000000..36c8820
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/middleware/urlquery.go
@@ -0,0 +1,24 @@
+package middleware
+
+import (
+ "github.com/zenazn/goji/web"
+ "net/http"
+)
+
+// URLQueryKey is the context key for the URL Query
+const URLQueryKey string = "urlquery"
+
+// URLQuery is a middleware to parse the URL Query parameters just once,
+// and store the resulting url.Values in the context.
+func URLQuery(c *web.C, h http.Handler) http.Handler {
+ fn := func(w http.ResponseWriter, r *http.Request) {
+ if c.Env == nil {
+ c.Env = make(map[interface{}]interface{})
+ }
+ c.Env[URLQueryKey] = r.URL.Query()
+
+ h.ServeHTTP(w, r)
+ }
+
+ return http.HandlerFunc(fn)
+}
diff --git a/vendor/github.com/zenazn/goji/web/mutil/mutil.go b/vendor/github.com/zenazn/goji/web/mutil/mutil.go
new file mode 100644
index 0000000..e8d5b28
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/mutil/mutil.go
@@ -0,0 +1,3 @@
+// Package mutil contains various functions that are helpful when writing http
+// middleware.
+package mutil
diff --git a/vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go b/vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go
new file mode 100644
index 0000000..9f6d776
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go
@@ -0,0 +1,139 @@
+package mutil
+
+import (
+ "bufio"
+ "io"
+ "net"
+ "net/http"
+)
+
+// WriterProxy is a proxy around an http.ResponseWriter that allows you to hook
+// into various parts of the response process.
+type WriterProxy interface {
+ http.ResponseWriter
+ // Status returns the HTTP status of the request, or 0 if one has not
+ // yet been sent.
+ Status() int
+ // BytesWritten returns the total number of bytes sent to the client.
+ BytesWritten() int
+ // Tee causes the response body to be written to the given io.Writer in
+ // addition to proxying the writes through. Only one io.Writer can be
+ // tee'd to at once: setting a second one will overwrite the first.
+ // Writes will be sent to the proxy before being written to this
+ // io.Writer. It is illegal for the tee'd writer to be modified
+ // concurrently with writes.
+ Tee(io.Writer)
+ // Unwrap returns the original proxied target.
+ Unwrap() http.ResponseWriter
+}
+
+// WrapWriter wraps an http.ResponseWriter, returning a proxy that allows you to
+// hook into various parts of the response process.
+func WrapWriter(w http.ResponseWriter) WriterProxy {
+ _, cn := w.(http.CloseNotifier)
+ _, fl := w.(http.Flusher)
+ _, hj := w.(http.Hijacker)
+ _, rf := w.(io.ReaderFrom)
+
+ bw := basicWriter{ResponseWriter: w}
+ if cn && fl && hj && rf {
+ return &fancyWriter{bw}
+ }
+ if fl {
+ return &flushWriter{bw}
+ }
+ return &bw
+}
+
+// basicWriter wraps a http.ResponseWriter that implements the minimal
+// http.ResponseWriter interface.
+type basicWriter struct {
+ http.ResponseWriter
+ wroteHeader bool
+ code int
+ bytes int
+ tee io.Writer
+}
+
+func (b *basicWriter) WriteHeader(code int) {
+ if !b.wroteHeader {
+ b.code = code
+ b.wroteHeader = true
+ b.ResponseWriter.WriteHeader(code)
+ }
+}
+func (b *basicWriter) Write(buf []byte) (int, error) {
+ b.WriteHeader(http.StatusOK)
+ n, err := b.ResponseWriter.Write(buf)
+ if b.tee != nil {
+ _, err2 := b.tee.Write(buf[:n])
+ // Prefer errors generated by the proxied writer.
+ if err == nil {
+ err = err2
+ }
+ }
+ b.bytes += n
+ return n, err
+}
+func (b *basicWriter) maybeWriteHeader() {
+ if !b.wroteHeader {
+ b.WriteHeader(http.StatusOK)
+ }
+}
+func (b *basicWriter) Status() int {
+ return b.code
+}
+func (b *basicWriter) BytesWritten() int {
+ return b.bytes
+}
+func (b *basicWriter) Tee(w io.Writer) {
+ b.tee = w
+}
+func (b *basicWriter) Unwrap() http.ResponseWriter {
+ return b.ResponseWriter
+}
+
+// fancyWriter is a writer that additionally satisfies http.CloseNotifier,
+// http.Flusher, http.Hijacker, and io.ReaderFrom. It exists for the common case
+// of wrapping the http.ResponseWriter that package http gives you, in order to
+// make the proxied object support the full method set of the proxied object.
+type fancyWriter struct {
+ basicWriter
+}
+
+func (f *fancyWriter) CloseNotify() <-chan bool {
+ cn := f.basicWriter.ResponseWriter.(http.CloseNotifier)
+ return cn.CloseNotify()
+}
+func (f *fancyWriter) Flush() {
+ fl := f.basicWriter.ResponseWriter.(http.Flusher)
+ fl.Flush()
+}
+func (f *fancyWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
+ hj := f.basicWriter.ResponseWriter.(http.Hijacker)
+ return hj.Hijack()
+}
+func (f *fancyWriter) ReadFrom(r io.Reader) (int64, error) {
+ if f.basicWriter.tee != nil {
+ return io.Copy(&f.basicWriter, r)
+ }
+ rf := f.basicWriter.ResponseWriter.(io.ReaderFrom)
+ f.basicWriter.maybeWriteHeader()
+ return rf.ReadFrom(r)
+}
+
+var _ http.CloseNotifier = &fancyWriter{}
+var _ http.Flusher = &fancyWriter{}
+var _ http.Hijacker = &fancyWriter{}
+var _ io.ReaderFrom = &fancyWriter{}
+
+type flushWriter struct {
+ basicWriter
+}
+
+func (f *flushWriter) Flush() {
+ fl := f.basicWriter.ResponseWriter.(http.Flusher)
+ fl.Flush()
+}
+
+var _ http.Flusher = &flushWriter{}
diff --git a/vendor/github.com/zenazn/goji/web/mux.go b/vendor/github.com/zenazn/goji/web/mux.go
new file mode 100644
index 0000000..18b9991
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/mux.go
@@ -0,0 +1,213 @@
+package web
+
+import (
+ "net/http"
+)
+
+/*
+Mux is an HTTP multiplexer, much like net/http's ServeMux. It functions as both
+a middleware stack and as an HTTP router.
+
+Middleware provide a great abstraction for actions that must be performed on
+every request, such as request logging and authentication. To append, insert,
+and remove middleware, you can call the Use, Insert, and Abandon functions
+respectively.
+
+Routes may be added using any of the HTTP verb functions (Get, Post, etc.), or
+through the generic Handle function. Goji's routing algorithm is very simple:
+routes are processed in the order they are added, and the first matching route
+will be executed. Routes match if their HTTP method and Pattern both match.
+*/
+type Mux struct {
+ ms mStack
+ rt router
+}
+
+// New creates a new Mux without any routes or middleware.
+func New() *Mux {
+ mux := Mux{
+ ms: mStack{
+ stack: make([]mLayer, 0),
+ pool: makeCPool(),
+ },
+ rt: router{
+ routes: make([]route, 0),
+ notFound: parseHandler(http.NotFound),
+ },
+ }
+ mux.ms.router = &mux.rt
+ return &mux
+}
+
+// ServeHTTP processes HTTP requests. Satisfies net/http.Handler.
+func (m *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ stack := m.ms.alloc()
+ stack.ServeHTTP(w, r)
+ m.ms.release(stack)
+}
+
+// ServeHTTPC creates a context dependent request with the given Mux. Satisfies
+// the Handler interface.
+func (m *Mux) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {
+ stack := m.ms.alloc()
+ stack.ServeHTTPC(c, w, r)
+ m.ms.release(stack)
+}
+
+// Middleware Stack functions
+
+// Use appends the given middleware to the middleware stack.
+//
+// No attempt is made to enforce the uniqueness of middlewares. It is illegal to
+// call this function concurrently with active requests.
+func (m *Mux) Use(middleware MiddlewareType) {
+ m.ms.Use(middleware)
+}
+
+// Insert inserts the given middleware immediately before a given existing
+// middleware in the stack. Returns an error if "before" cannot be found in the
+// current stack.
+//
+// No attempt is made to enforce the uniqueness of middlewares. If the insertion
+// point is ambiguous, the first (outermost) one is chosen. It is illegal to
+// call this function concurrently with active requests.
+func (m *Mux) Insert(middleware, before MiddlewareType) error {
+ return m.ms.Insert(middleware, before)
+}
+
+// Abandon removes the given middleware from the middleware stack. Returns an
+// error if no such middleware can be found.
+//
+// If the name of the middleware to delete is ambiguous, the first (outermost)
+// one is chosen. It is illegal to call this function concurrently with active
+// requests.
+func (m *Mux) Abandon(middleware MiddlewareType) error {
+ return m.ms.Abandon(middleware)
+}
+
+// Router functions
+
+type routerMiddleware struct {
+ m *Mux
+ c *C
+ h http.Handler
+}
+
+func (rm routerMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ if rm.c.Env == nil {
+ rm.c.Env = make(map[interface{}]interface{}, 1)
+ }
+ rm.c.Env[MatchKey] = rm.m.rt.getMatch(rm.c, w, r)
+ rm.h.ServeHTTP(w, r)
+}
+
+/*
+Router is a middleware that performs routing and stores the resulting Match in
+Goji's environment. If a routing Match is present at the end of the middleware
+stack, that Match is used instead of re-routing.
+
+This middleware is especially useful to create post-routing middleware, e.g. a
+request logger which prints which pattern or handler was selected, or an
+authentication middleware which only applies to certain routes.
+
+If you use nested Muxes with explicit routing, you should be aware that the
+explicit routing information set by an outer Mux can be picked up by an inner
+Mux, inadvertently causing an infinite routing loop. If you use both explicit
+routing and nested Muxes, you should be sure to unset MatchKey before the inner
+Mux performs routing (or attach a Router to the inner Mux as well).
+*/
+func (m *Mux) Router(c *C, h http.Handler) http.Handler {
+ return routerMiddleware{m, c, h}
+}
+
+/*
+Handle dispatches to the given handler when the pattern matches, regardless of
+HTTP method.
+
+This method is commonly used to implement sub-routing: an admin application, for
+instance, can expose a single handler that is attached to the main Mux by
+calling Handle("/admin/*", adminHandler) or similar. Note that this function
+doesn't strip this prefix from the path before forwarding it on (e.g., the
+handler will see the full path, including the "/admin/" part), but this
+functionality can easily be performed by an extra middleware layer.
+*/
+func (m *Mux) Handle(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mALL, handler)
+}
+
+// Connect dispatches to the given handler when the pattern matches and the HTTP
+// method is CONNECT.
+func (m *Mux) Connect(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mCONNECT, handler)
+}
+
+// Delete dispatches to the given handler when the pattern matches and the HTTP
+// method is DELETE.
+func (m *Mux) Delete(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mDELETE, handler)
+}
+
+// Get dispatches to the given handler when the pattern matches and the HTTP
+// method is GET.
+//
+// All GET handlers also transparently serve HEAD requests, since net/http will
+// take care of all the fiddly bits for you. If you wish to provide an alternate
+// implementation of HEAD, you should add a handler explicitly and place it
+// above your GET handler.
+func (m *Mux) Get(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mGET|mHEAD, handler)
+}
+
+// Head dispatches to the given handler when the pattern matches and the HTTP
+// method is HEAD.
+func (m *Mux) Head(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mHEAD, handler)
+}
+
+// Options dispatches to the given handler when the pattern matches and the HTTP
+// method is OPTIONS.
+func (m *Mux) Options(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mOPTIONS, handler)
+}
+
+// Patch dispatches to the given handler when the pattern matches and the HTTP
+// method is PATCH.
+func (m *Mux) Patch(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mPATCH, handler)
+}
+
+// Post dispatches to the given handler when the pattern matches and the HTTP
+// method is POST.
+func (m *Mux) Post(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mPOST, handler)
+}
+
+// Put dispatches to the given handler when the pattern matches and the HTTP
+// method is PUT.
+func (m *Mux) Put(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mPUT, handler)
+}
+
+// Trace dispatches to the given handler when the pattern matches and the HTTP
+// method is TRACE.
+func (m *Mux) Trace(pattern PatternType, handler HandlerType) {
+ m.rt.handleUntyped(pattern, mTRACE, handler)
+}
+
+// NotFound sets the fallback (i.e., 404) handler for this mux.
+//
+// As a convenience, the context environment variable "goji.web.validMethods"
+// (also available as the constant ValidMethodsKey) will be set to the list of
+// HTTP methods that could have been routed had they been provided on an
+// otherwise identical request.
+func (m *Mux) NotFound(handler HandlerType) {
+ m.rt.notFound = parseHandler(handler)
+}
+
+// Compile compiles the list of routes into bytecode. This only needs to be done
+// once after all the routes have been added, and will be called automatically
+// for you (at some performance cost on the first request) if you do not call it
+// explicitly.
+func (m *Mux) Compile() {
+ m.rt.compile()
+}
diff --git a/vendor/github.com/zenazn/goji/web/pattern.go b/vendor/github.com/zenazn/goji/web/pattern.go
new file mode 100644
index 0000000..9f9fc85
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/pattern.go
@@ -0,0 +1,58 @@
+package web
+
+import (
+ "log"
+ "net/http"
+ "regexp"
+)
+
+// A Pattern determines whether or not a given request matches some criteria.
+// They are often used in routes, which are essentially (pattern, methodSet,
+// handler) tuples. If the method and pattern match, the given handler is used.
+//
+// Built-in implementations of this interface are used to implement regular
+// expression and string matching.
+type Pattern interface {
+ // In practice, most real-world routes have a string prefix that can be
+ // used to quickly determine if a pattern is an eligible match. The
+ // router uses the result of this function to optimize away calls to the
+ // full Match function, which is likely much more expensive to compute.
+ // If your Pattern does not support prefixes, this function should
+ // return the empty string.
+ Prefix() string
+ // Returns true if the request satisfies the pattern. This function is
+ // free to examine both the request and the context to make this
+ // decision. Match should not modify either argument, and since it will
+ // potentially be called several times over the course of matching a
+ // request, it should be reasonably efficient.
+ Match(r *http.Request, c *C) bool
+ // Run the pattern on the request and context, modifying the context as
+ // necessary to bind URL parameters or other parsed state.
+ Run(r *http.Request, c *C)
+}
+
+const unknownPattern = `Unknown pattern type %T. See http://godoc.org/github.com/zenazn/goji/web#PatternType for a list of acceptable types.`
+
+/*
+ParsePattern is used internally by Goji to parse route patterns. It is exposed
+publicly to make it easier to write thin wrappers around the built-in Pattern
+implementations.
+
+ParsePattern fatally exits (using log.Fatalf) if it is passed a value of an
+unexpected type (see the documentation for PatternType for a list of which types
+are accepted). It is the caller's responsibility to ensure that ParsePattern is
+called in a type-safe manner.
+*/
+func ParsePattern(raw PatternType) Pattern {
+ switch v := raw.(type) {
+ case Pattern:
+ return v
+ case *regexp.Regexp:
+ return parseRegexpPattern(v)
+ case string:
+ return parseStringPattern(v)
+ default:
+ log.Fatalf(unknownPattern, v)
+ panic("log.Fatalf does not return")
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/regexp_pattern.go b/vendor/github.com/zenazn/goji/web/regexp_pattern.go
new file mode 100644
index 0000000..95e7e09
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/regexp_pattern.go
@@ -0,0 +1,149 @@
+package web
+
+import (
+ "bytes"
+ "fmt"
+ "log"
+ "net/http"
+ "regexp"
+ "regexp/syntax"
+)
+
+type regexpPattern struct {
+ re *regexp.Regexp
+ prefix string
+ names []string
+}
+
+func (p regexpPattern) Prefix() string {
+ return p.prefix
+}
+func (p regexpPattern) Match(r *http.Request, c *C) bool {
+ return p.match(r, c, false)
+}
+func (p regexpPattern) Run(r *http.Request, c *C) {
+ p.match(r, c, false)
+}
+
+func (p regexpPattern) match(r *http.Request, c *C, dryrun bool) bool {
+ matches := p.re.FindStringSubmatch(r.URL.Path)
+ if matches == nil || len(matches) == 0 {
+ return false
+ }
+
+ if c == nil || dryrun || len(matches) == 1 {
+ return true
+ }
+
+ if c.URLParams == nil {
+ c.URLParams = make(map[string]string, len(matches)-1)
+ }
+ for i := 1; i < len(matches); i++ {
+ c.URLParams[p.names[i]] = matches[i]
+ }
+ return true
+}
+
+func (p regexpPattern) String() string {
+ return fmt.Sprintf("regexpPattern(%v)", p.re)
+}
+
+func (p regexpPattern) Raw() *regexp.Regexp {
+ return p.re
+}
+
+/*
+I'm sorry, dear reader. I really am.
+
+The problem here is to take an arbitrary regular expression and:
+1. return a regular expression that is just like it, but left-anchored,
+ preferring to return the original if possible.
+2. determine a string literal prefix that all matches of this regular expression
+ have, much like regexp.Regexp.Prefix(). Unfortunately, Prefix() does not work
+ in the presence of anchors, so we need to write it ourselves.
+
+What this actually means is that we need to sketch on the internals of the
+standard regexp library to forcefully extract the information we want.
+
+Unfortunately, regexp.Regexp hides a lot of its state, so our abstraction is
+going to be pretty leaky. The biggest leak is that we blindly assume that all
+regular expressions are perl-style, not POSIX. This is probably Mostly True, and
+I think most users of the library probably won't be able to notice.
+*/
+func sketchOnRegex(re *regexp.Regexp) (*regexp.Regexp, string) {
+ rawRe := re.String()
+ sRe, err := syntax.Parse(rawRe, syntax.Perl)
+ if err != nil {
+ log.Printf("WARN(web): unable to parse regexp %v as perl. "+
+ "This route might behave unexpectedly.", re)
+ return re, ""
+ }
+ sRe = sRe.Simplify()
+ p, err := syntax.Compile(sRe)
+ if err != nil {
+ log.Printf("WARN(web): unable to compile regexp %v. This "+
+ "route might behave unexpectedly.", re)
+ return re, ""
+ }
+ if p.StartCond()&syntax.EmptyBeginText == 0 {
+ // I hope doing this is always legal...
+ newRe, err := regexp.Compile(`\A` + rawRe)
+ if err != nil {
+ log.Printf("WARN(web): unable to create a left-"+
+ "anchored regexp from %v. This route might "+
+ "behave unexpectedly", re)
+ return re, ""
+ }
+ re = newRe
+ }
+
+ // Run the regular expression more or less by hand :(
+ pc := uint32(p.Start)
+ atStart := true
+ i := &p.Inst[pc]
+ var buf bytes.Buffer
+Sadness:
+ for {
+ switch i.Op {
+ case syntax.InstEmptyWidth:
+ if !atStart {
+ break Sadness
+ }
+ case syntax.InstCapture, syntax.InstNop:
+ // nop!
+ case syntax.InstRune, syntax.InstRune1, syntax.InstRuneAny,
+ syntax.InstRuneAnyNotNL:
+
+ atStart = false
+ if len(i.Rune) != 1 ||
+ syntax.Flags(i.Arg)&syntax.FoldCase != 0 {
+ break Sadness
+ }
+ buf.WriteRune(i.Rune[0])
+ default:
+ break Sadness
+ }
+ pc = i.Out
+ i = &p.Inst[pc]
+ }
+ return re, buf.String()
+}
+
+func parseRegexpPattern(re *regexp.Regexp) regexpPattern {
+ re, prefix := sketchOnRegex(re)
+ rnames := re.SubexpNames()
+ // We have to make our own copy since package regexp forbids us
+ // from scribbling over the slice returned by SubexpNames().
+ names := make([]string, len(rnames))
+ for i, rname := range rnames {
+ if rname == "" {
+ rname = fmt.Sprintf("$%d", i)
+ }
+ names[i] = rname
+ }
+ return regexpPattern{
+ re: re,
+ prefix: prefix,
+ names: names,
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/router.go b/vendor/github.com/zenazn/goji/web/router.go
new file mode 100644
index 0000000..1fbc41f
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/router.go
@@ -0,0 +1,154 @@
+package web
+
+import (
+ "net/http"
+ "sort"
+ "strings"
+ "sync"
+)
+
+type method int
+
+const (
+ mCONNECT method = 1 << iota
+ mDELETE
+ mGET
+ mHEAD
+ mOPTIONS
+ mPATCH
+ mPOST
+ mPUT
+ mTRACE
+ // We only natively support the methods above, but we pass through other
+ // methods. This constant pretty much only exists for the sake of mALL.
+ mIDK
+
+ mALL method = mCONNECT | mDELETE | mGET | mHEAD | mOPTIONS | mPATCH |
+ mPOST | mPUT | mTRACE | mIDK
+)
+
+// The key used to communicate to the NotFound handler what methods would have
+// been allowed if they'd been provided.
+const ValidMethodsKey = "goji.web.ValidMethods"
+
+var validMethodsMap = map[string]method{
+ "CONNECT": mCONNECT,
+ "DELETE": mDELETE,
+ "GET": mGET,
+ "HEAD": mHEAD,
+ "OPTIONS": mOPTIONS,
+ "PATCH": mPATCH,
+ "POST": mPOST,
+ "PUT": mPUT,
+ "TRACE": mTRACE,
+}
+
+type route struct {
+ prefix string
+ method method
+ pattern Pattern
+ handler Handler
+}
+
+type router struct {
+ lock sync.Mutex
+ routes []route
+ notFound Handler
+ machine *routeMachine
+}
+
+func httpMethod(mname string) method {
+ if method, ok := validMethodsMap[mname]; ok {
+ return method
+ }
+ return mIDK
+}
+
+func (rt *router) compile() *routeMachine {
+ rt.lock.Lock()
+ defer rt.lock.Unlock()
+ sm := routeMachine{
+ sm: compile(rt.routes),
+ routes: rt.routes,
+ }
+ rt.setMachine(&sm)
+ return &sm
+}
+
+func (rt *router) getMatch(c *C, w http.ResponseWriter, r *http.Request) Match {
+ rm := rt.getMachine()
+ if rm == nil {
+ rm = rt.compile()
+ }
+
+ methods, route := rm.route(c, w, r)
+ if route != nil {
+ return Match{
+ Pattern: route.pattern,
+ Handler: route.handler,
+ }
+ }
+
+ if methods == 0 {
+ return Match{Handler: rt.notFound}
+ }
+
+ var methodsList = make([]string, 0)
+ for mname, meth := range validMethodsMap {
+ if methods&meth != 0 {
+ methodsList = append(methodsList, mname)
+ }
+ }
+ sort.Strings(methodsList)
+
+ if c.Env == nil {
+ c.Env = map[interface{}]interface{}{
+ ValidMethodsKey: methodsList,
+ }
+ } else {
+ c.Env[ValidMethodsKey] = methodsList
+ }
+ return Match{Handler: rt.notFound}
+}
+
+func (rt *router) route(c *C, w http.ResponseWriter, r *http.Request) {
+ match := GetMatch(*c)
+ if match.Handler == nil {
+ match = rt.getMatch(c, w, r)
+ }
+ match.Handler.ServeHTTPC(*c, w, r)
+}
+
+func (rt *router) handleUntyped(p PatternType, m method, h HandlerType) {
+ rt.handle(ParsePattern(p), m, parseHandler(h))
+}
+
+func (rt *router) handle(p Pattern, m method, h Handler) {
+ rt.lock.Lock()
+ defer rt.lock.Unlock()
+
+ // Calculate the sorted insertion point, because there's no reason to do
+ // swapping hijinks if we're already making a copy. We need to use
+ // bubble sort because we can only compare adjacent elements.
+ pp := p.Prefix()
+ var i int
+ for i = len(rt.routes); i > 0; i-- {
+ rip := rt.routes[i-1].prefix
+ if rip <= pp || strings.HasPrefix(rip, pp) {
+ break
+ }
+ }
+
+ newRoutes := make([]route, len(rt.routes)+1)
+ copy(newRoutes, rt.routes[:i])
+ newRoutes[i] = route{
+ prefix: pp,
+ method: m,
+ pattern: p,
+ handler: h,
+ }
+ copy(newRoutes[i+1:], rt.routes[i:])
+
+ rt.setMachine(nil)
+ rt.routes = newRoutes
+}
diff --git a/vendor/github.com/zenazn/goji/web/string_pattern.go b/vendor/github.com/zenazn/goji/web/string_pattern.go
new file mode 100644
index 0000000..aa9b33a
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/string_pattern.go
@@ -0,0 +1,137 @@
+package web
+
+import (
+ "fmt"
+ "net/http"
+ "regexp"
+ "strings"
+)
+
+// stringPattern is a struct describing
+type stringPattern struct {
+ raw string
+ pats []string
+ breaks []byte
+ literals []string
+ wildcard bool
+}
+
+func (s stringPattern) Prefix() string {
+ return s.literals[0]
+}
+func (s stringPattern) Match(r *http.Request, c *C) bool {
+ return s.match(r, c, true)
+}
+func (s stringPattern) Run(r *http.Request, c *C) {
+ s.match(r, c, false)
+}
+func (s stringPattern) match(r *http.Request, c *C, dryrun bool) bool {
+ path := r.URL.Path
+ var matches map[string]string
+ if !dryrun {
+ if s.wildcard {
+ matches = make(map[string]string, len(s.pats)+1)
+ } else if len(s.pats) != 0 {
+ matches = make(map[string]string, len(s.pats))
+ }
+ }
+ for i, pat := range s.pats {
+ sli := s.literals[i]
+ if !strings.HasPrefix(path, sli) {
+ return false
+ }
+ path = path[len(sli):]
+
+ m := 0
+ bc := s.breaks[i]
+ for ; m < len(path); m++ {
+ if path[m] == bc || path[m] == '/' {
+ break
+ }
+ }
+ if m == 0 {
+ // Empty strings are not matches, otherwise routes like
+ // "/:foo" would match the path "/"
+ return false
+ }
+ if !dryrun {
+ matches[pat] = path[:m]
+ }
+ path = path[m:]
+ }
+ // There's exactly one more literal than pat.
+ tail := s.literals[len(s.pats)]
+ if s.wildcard {
+ if !strings.HasPrefix(path, tail) {
+ return false
+ }
+ if !dryrun {
+ matches["*"] = path[len(tail)-1:]
+ }
+ } else if path != tail {
+ return false
+ }
+
+ if c == nil || dryrun {
+ return true
+ }
+
+ if c.URLParams == nil {
+ c.URLParams = matches
+ } else {
+ for k, v := range matches {
+ c.URLParams[k] = v
+ }
+ }
+ return true
+}
+
+func (s stringPattern) String() string {
+ return fmt.Sprintf("stringPattern(%q)", s.raw)
+}
+
+func (s stringPattern) Raw() string {
+ return s.raw
+}
+
+// "Break characters" are characters that can end patterns. They are not allowed
+// to appear in pattern names. "/" was chosen because it is the standard path
+// separator, and "." was chosen because it often delimits file extensions. ";"
+// and "," were chosen because Section 3.3 of RFC 3986 suggests their use.
+const bc = "/.;,"
+
+var patternRe = regexp.MustCompile(`[` + bc + `]:([^` + bc + `]+)`)
+
+func parseStringPattern(s string) stringPattern {
+ raw := s
+ var wildcard bool
+ if strings.HasSuffix(s, "/*") {
+ s = s[:len(s)-1]
+ wildcard = true
+ }
+
+ matches := patternRe.FindAllStringSubmatchIndex(s, -1)
+ pats := make([]string, len(matches))
+ breaks := make([]byte, len(matches))
+ literals := make([]string, len(matches)+1)
+ n := 0
+ for i, match := range matches {
+ a, b := match[2], match[3]
+ literals[i] = s[n : a-1] // Need to leave off the colon
+ pats[i] = s[a:b]
+ if b == len(s) {
+ breaks[i] = '/'
+ } else {
+ breaks[i] = s[b]
+ }
+ n = b
+ }
+ literals[len(matches)] = s[n:]
+ return stringPattern{
+ raw: raw,
+ pats: pats,
+ breaks: breaks,
+ literals: literals,
+ wildcard: wildcard,
+ }
+}
diff --git a/vendor/github.com/zenazn/goji/web/web.go b/vendor/github.com/zenazn/goji/web/web.go
new file mode 100644
index 0000000..21f6fcc
--- /dev/null
+++ b/vendor/github.com/zenazn/goji/web/web.go
@@ -0,0 +1,112 @@
+/*
+Package web provides a fast and flexible middleware stack and mux.
+
+This package attempts to solve three problems that net/http does not. First, it
+allows you to specify flexible patterns, including routes with named parameters
+and regular expressions. Second, it allows you to write reconfigurable
+middleware stacks. And finally, it allows you to attach additional context to
+requests, in a manner that can be manipulated by both compliant middleware and
+handlers.
+*/
+package web
+
+import (
+ "net/http"
+)
+
+/*
+C is a request-local context object which is threaded through all compliant
+middleware layers and given to the final request handler.
+*/
+type C struct {
+ // URLParams is a map of variables extracted from the URL (typically
+ // from the path portion) during routing. See the documentation for the
+ // URL Pattern you are using (or the documentation for PatternType for
+ // the case of standard pattern types) for more information about how
+ // variables are extracted and named.
+ URLParams map[string]string
+ // Env is a free-form environment for storing request-local data. Keys
+ // may be arbitrary types that support equality, however package-private
+ // types with type-safe accessors provide a convenient way for packages
+ // to mediate access to their request-local data.
+ Env map[interface{}]interface{}
+}
+
+// Handler is similar to net/http's http.Handler, but also accepts a Goji
+// context object.
+type Handler interface {
+ ServeHTTPC(C, http.ResponseWriter, *http.Request)
+}
+
+// HandlerFunc is similar to net/http's http.HandlerFunc, but supports a context
+// object. Implements both http.Handler and Handler.
+type HandlerFunc func(C, http.ResponseWriter, *http.Request)
+
+// ServeHTTP implements http.Handler, allowing HandlerFunc's to be used with
+// net/http and other compliant routers. When used in this way, the underlying
+// function will be passed an empty context.
+func (h HandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ h(C{}, w, r)
+}
+
+// ServeHTTPC implements Handler.
+func (h HandlerFunc) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {
+ h(c, w, r)
+}
+
+/*
+PatternType is the type denoting Patterns and types that Goji internally
+converts to Pattern (via the ParsePattern function). In order to provide an
+expressive API, this type is an alias for interface{} that is named for the
+purposes of documentation, however only the following concrete types are
+accepted:
+ - types that implement Pattern
+ - string, which is interpreted as a Sinatra-like URL pattern. In
+ particular, the following syntax is recognized:
+ - a path segment starting with a colon will match any
+ string placed at that position. e.g., "/:name" will match
+ "/carl", binding "name" to "carl".
+ - a pattern ending with "/*" will match any route with that
+ prefix. For instance, the pattern "/u/:name/*" will match
+ "/u/carl/" and "/u/carl/projects/123", but not "/u/carl"
+ (because there is no trailing slash). In addition to any names
+ bound in the pattern, the special key "*" is bound to the
+ unmatched tail of the match, but including the leading "/". So
+ for the two matching examples above, "*" would be bound to "/"
+ and "/projects/123" respectively.
+ Unlike http.ServeMux's patterns, string patterns support neither the
+ "rooted subtree" behavior nor Host-specific routes. Users who require
+ either of these features are encouraged to compose package http's mux
+ with the mux provided by this package.
+ - regexp.Regexp, which is assumed to be a Perl-style regular expression
+ that is anchored on the left (i.e., the beginning of the string). If
+ your regular expression is not anchored on the left, a
+ hopefully-identical left-anchored regular expression will be created
+ and used instead.
+
+ Capturing groups will be converted into bound URL parameters in
+ URLParams. If the capturing group is named, that name will be used;
+ otherwise the special identifiers "$1", "$2", etc. will be used.
+*/
+type PatternType interface{}
+
+/*
+HandlerType is the type of Handlers and types that Goji internally converts to
+Handler. In order to provide an expressive API, this type is an alias for
+interface{} that is named for the purposes of documentation, however only the
+following concrete types are accepted:
+ - types that implement http.Handler
+ - types that implement Handler
+ - func(http.ResponseWriter, *http.Request)
+ - func(web.C, http.ResponseWriter, *http.Request)
+*/
+type HandlerType interface{}
+
+/*
+MiddlewareType is the type of Goji middleware. In order to provide an expressive
+API, this type is an alias for interface{} that is named for the purposes of
+documentation, however only the following concrete types are accepted:
+ - func(http.Handler) http.Handler
+ - func(*web.C, http.Handler) http.Handler
+*/
+type MiddlewareType interface{}
diff --git a/vendor/golang.org/x/net/context/LICENSE b/vendor/golang.org/x/net/context/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/net/context/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/context.go
new file mode 100644
index 0000000..134654c
--- /dev/null
+++ b/vendor/golang.org/x/net/context/context.go
@@ -0,0 +1,156 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package context defines the Context type, which carries deadlines,
+// cancelation signals, and other request-scoped values across API boundaries
+// and between processes.
+//
+// Incoming requests to a server should create a Context, and outgoing calls to
+// servers should accept a Context. The chain of function calls between must
+// propagate the Context, optionally replacing it with a modified copy created
+// using WithDeadline, WithTimeout, WithCancel, or WithValue.
+//
+// Programs that use Contexts should follow these rules to keep interfaces
+// consistent across packages and enable static analysis tools to check context
+// propagation:
+//
+// Do not store Contexts inside a struct type; instead, pass a Context
+// explicitly to each function that needs it. The Context should be the first
+// parameter, typically named ctx:
+//
+// func DoSomething(ctx context.Context, arg Arg) error {
+// // ... use ctx ...
+// }
+//
+// Do not pass a nil Context, even if a function permits it. Pass context.TODO
+// if you are unsure about which Context to use.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+//
+// The same Context may be passed to functions running in different goroutines;
+// Contexts are safe for simultaneous use by multiple goroutines.
+//
+// See http://blog.golang.org/context for example code for a server that uses
+// Contexts.
+package context // import "golang.org/x/net/context"
+
+import "time"
+
+// A Context carries a deadline, a cancelation signal, and other values across
+// API boundaries.
+//
+// Context's methods may be called by multiple goroutines simultaneously.
+type Context interface {
+ // Deadline returns the time when work done on behalf of this context
+ // should be canceled. Deadline returns ok==false when no deadline is
+ // set. Successive calls to Deadline return the same results.
+ Deadline() (deadline time.Time, ok bool)
+
+ // Done returns a channel that's closed when work done on behalf of this
+ // context should be canceled. Done may return nil if this context can
+ // never be canceled. Successive calls to Done return the same value.
+ //
+ // WithCancel arranges for Done to be closed when cancel is called;
+ // WithDeadline arranges for Done to be closed when the deadline
+ // expires; WithTimeout arranges for Done to be closed when the timeout
+ // elapses.
+ //
+ // Done is provided for use in select statements:
+ //
+ // // Stream generates values with DoSomething and sends them to out
+ // // until DoSomething returns an error or ctx.Done is closed.
+ // func Stream(ctx context.Context, out chan<- Value) error {
+ // for {
+ // v, err := DoSomething(ctx)
+ // if err != nil {
+ // return err
+ // }
+ // select {
+ // case <-ctx.Done():
+ // return ctx.Err()
+ // case out <- v:
+ // }
+ // }
+ // }
+ //
+ // See http://blog.golang.org/pipelines for more examples of how to use
+ // a Done channel for cancelation.
+ Done() <-chan struct{}
+
+ // Err returns a non-nil error value after Done is closed. Err returns
+ // Canceled if the context was canceled or DeadlineExceeded if the
+ // context's deadline passed. No other values for Err are defined.
+ // After Done is closed, successive calls to Err return the same value.
+ Err() error
+
+ // Value returns the value associated with this context for key, or nil
+ // if no value is associated with key. Successive calls to Value with
+ // the same key returns the same result.
+ //
+ // Use context values only for request-scoped data that transits
+ // processes and API boundaries, not for passing optional parameters to
+ // functions.
+ //
+ // A key identifies a specific value in a Context. Functions that wish
+ // to store values in Context typically allocate a key in a global
+ // variable then use that key as the argument to context.WithValue and
+ // Context.Value. A key can be any type that supports equality;
+ // packages should define keys as an unexported type to avoid
+ // collisions.
+ //
+ // Packages that define a Context key should provide type-safe accessors
+ // for the values stores using that key:
+ //
+ // // Package user defines a User type that's stored in Contexts.
+ // package user
+ //
+ // import "golang.org/x/net/context"
+ //
+ // // User is the type of value stored in the Contexts.
+ // type User struct {...}
+ //
+ // // key is an unexported type for keys defined in this package.
+ // // This prevents collisions with keys defined in other packages.
+ // type key int
+ //
+ // // userKey is the key for user.User values in Contexts. It is
+ // // unexported; clients use user.NewContext and user.FromContext
+ // // instead of using this key directly.
+ // var userKey key = 0
+ //
+ // // NewContext returns a new Context that carries value u.
+ // func NewContext(ctx context.Context, u *User) context.Context {
+ // return context.WithValue(ctx, userKey, u)
+ // }
+ //
+ // // FromContext returns the User value stored in ctx, if any.
+ // func FromContext(ctx context.Context) (*User, bool) {
+ // u, ok := ctx.Value(userKey).(*User)
+ // return u, ok
+ // }
+ Value(key interface{}) interface{}
+}
+
+// Background returns a non-nil, empty Context. It is never canceled, has no
+// values, and has no deadline. It is typically used by the main function,
+// initialization, and tests, and as the top-level Context for incoming
+// requests.
+func Background() Context {
+ return background
+}
+
+// TODO returns a non-nil, empty Context. Code should use context.TODO when
+// it's unclear which Context to use or it is not yet available (because the
+// surrounding function has not yet been extended to accept a Context
+// parameter). TODO is recognized by static analysis tools that determine
+// whether Contexts are propagated correctly in a program.
+func TODO() Context {
+ return todo
+}
+
+// A CancelFunc tells an operation to abandon its work.
+// A CancelFunc does not wait for the work to stop.
+// After the first call, subsequent calls to a CancelFunc do nothing.
+type CancelFunc func()
diff --git a/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
new file mode 100644
index 0000000..606cf1f
--- /dev/null
+++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
@@ -0,0 +1,74 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+package ctxhttp // import "golang.org/x/net/context/ctxhttp"
+
+import (
+ "io"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "golang.org/x/net/context"
+)
+
+// Do sends an HTTP request with the provided http.Client and returns
+// an HTTP response.
+//
+// If the client is nil, http.DefaultClient is used.
+//
+// The provided ctx must be non-nil. If it is canceled or times out,
+// ctx.Err() will be returned.
+func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
+ if client == nil {
+ client = http.DefaultClient
+ }
+ resp, err := client.Do(req.WithContext(ctx))
+ // If we got an error, and the context has been canceled,
+ // the context's error is probably more useful.
+ if err != nil {
+ select {
+ case <-ctx.Done():
+ err = ctx.Err()
+ default:
+ }
+ }
+ return resp, err
+}
+
+// Get issues a GET request via the Do function.
+func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("GET", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Head issues a HEAD request via the Do function.
+func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
+ req, err := http.NewRequest("HEAD", url, nil)
+ if err != nil {
+ return nil, err
+ }
+ return Do(ctx, client, req)
+}
+
+// Post issues a POST request via the Do function.
+func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest("POST", url, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Content-Type", bodyType)
+ return Do(ctx, client, req)
+}
+
+// PostForm issues a POST request via the Do function.
+func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
+ return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
+}
diff --git a/src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
index 62620d4..926870c 100644
--- a/src/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go
+++ b/vendor/golang.org/x/net/context/ctxhttp/ctxhttp_pre17.go
@@ -2,7 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package ctxhttp provides helper functions for performing context-aware HTTP requests.
+// +build !go1.7
+
package ctxhttp // import "golang.org/x/net/context/ctxhttp"
import (
@@ -30,8 +31,9 @@ func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Resp
client = http.DefaultClient
}
- // Request cancelation changed in Go 1.5, see cancelreq.go and cancelreq_go14.go.
- cancel := canceler(client, req)
+ // TODO(djd): Respect any existing value of req.Cancel.
+ cancel := make(chan struct{})
+ req.Cancel = cancel
type responseAndError struct {
resp *http.Response
@@ -39,6 +41,11 @@ func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Resp
}
result := make(chan responseAndError, 1)
+ // Make local copies of test hooks closed over by goroutines below.
+ // Prevents data races in tests.
+ testHookDoReturned := testHookDoReturned
+ testHookDidBodyClose := testHookDidBodyClose
+
go func() {
resp, err := client.Do(req)
testHookDoReturned()
@@ -50,7 +57,7 @@ func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Resp
select {
case <-ctx.Done():
testHookContextDoneBeforeHeaders()
- cancel()
+ close(cancel)
// Clean up after the goroutine calling client.Do:
go func() {
if r := <-result; r.resp != nil {
@@ -71,7 +78,7 @@ func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Resp
go func() {
select {
case <-ctx.Done():
- cancel()
+ close(cancel)
case <-c:
// The response's Body is closed.
}
diff --git a/vendor/golang.org/x/net/context/go17.go b/vendor/golang.org/x/net/context/go17.go
new file mode 100644
index 0000000..f8cda19
--- /dev/null
+++ b/vendor/golang.org/x/net/context/go17.go
@@ -0,0 +1,72 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+
+package context
+
+import (
+ "context" // standard library's context, as of Go 1.7
+ "time"
+)
+
+var (
+ todo = context.TODO()
+ background = context.Background()
+)
+
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = context.Canceled
+
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = context.DeadlineExceeded
+
+// WithCancel returns a copy of parent with a new Done channel. The returned
+// context's Done channel is closed when the returned cancel function is called
+// or when the parent context's Done channel is closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
+ ctx, f := context.WithCancel(parent)
+ return ctx, CancelFunc(f)
+}
+
+// WithDeadline returns a copy of the parent context with the deadline adjusted
+// to be no later than d. If the parent's deadline is already earlier than d,
+// WithDeadline(parent, d) is semantically equivalent to parent. The returned
+// context's Done channel is closed when the deadline expires, when the returned
+// cancel function is called, or when the parent context's Done channel is
+// closed, whichever happens first.
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete.
+func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
+ ctx, f := context.WithDeadline(parent, deadline)
+ return ctx, CancelFunc(f)
+}
+
+// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).
+//
+// Canceling this context releases resources associated with it, so code should
+// call cancel as soon as the operations running in this Context complete:
+//
+// func slowOperationWithTimeout(ctx context.Context) (Result, error) {
+// ctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond)
+// defer cancel() // releases resources if slowOperation completes before timeout elapses
+// return slowOperation(ctx)
+// }
+func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc) {
+ return WithDeadline(parent, time.Now().Add(timeout))
+}
+
+// WithValue returns a copy of parent in which the value associated with key is
+// val.
+//
+// Use context Values only for request-scoped data that transits processes and
+// APIs, not for passing optional parameters to functions.
+func WithValue(parent Context, key interface{}, val interface{}) Context {
+ return context.WithValue(parent, key, val)
+}
diff --git a/src/vendor/golang.org/x/net/context/context.go b/vendor/golang.org/x/net/context/pre_go17.go
index 77b64d0..5a30aca 100644
--- a/src/vendor/golang.org/x/net/context/context.go
+++ b/vendor/golang.org/x/net/context/pre_go17.go
@@ -2,39 +2,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Package context defines the Context type, which carries deadlines,
-// cancelation signals, and other request-scoped values across API boundaries
-// and between processes.
-//
-// Incoming requests to a server should create a Context, and outgoing calls to
-// servers should accept a Context. The chain of function calls between must
-// propagate the Context, optionally replacing it with a modified copy created
-// using WithDeadline, WithTimeout, WithCancel, or WithValue.
-//
-// Programs that use Contexts should follow these rules to keep interfaces
-// consistent across packages and enable static analysis tools to check context
-// propagation:
-//
-// Do not store Contexts inside a struct type; instead, pass a Context
-// explicitly to each function that needs it. The Context should be the first
-// parameter, typically named ctx:
-//
-// func DoSomething(ctx context.Context, arg Arg) error {
-// // ... use ctx ...
-// }
-//
-// Do not pass a nil Context, even if a function permits it. Pass context.TODO
-// if you are unsure about which Context to use.
-//
-// Use context Values only for request-scoped data that transits processes and
-// APIs, not for passing optional parameters to functions.
-//
-// The same Context may be passed to functions running in different goroutines;
-// Contexts are safe for simultaneous use by multiple goroutines.
-//
-// See http://blog.golang.org/context for example code for a server that uses
-// Contexts.
-package context // import "golang.org/x/net/context"
+// +build !go1.7
+
+package context
import (
"errors"
@@ -43,108 +13,6 @@ import (
"time"
)
-// A Context carries a deadline, a cancelation signal, and other values across
-// API boundaries.
-//
-// Context's methods may be called by multiple goroutines simultaneously.
-type Context interface {
- // Deadline returns the time when work done on behalf of this context
- // should be canceled. Deadline returns ok==false when no deadline is
- // set. Successive calls to Deadline return the same results.
- Deadline() (deadline time.Time, ok bool)
-
- // Done returns a channel that's closed when work done on behalf of this
- // context should be canceled. Done may return nil if this context can
- // never be canceled. Successive calls to Done return the same value.
- //
- // WithCancel arranges for Done to be closed when cancel is called;
- // WithDeadline arranges for Done to be closed when the deadline
- // expires; WithTimeout arranges for Done to be closed when the timeout
- // elapses.
- //
- // Done is provided for use in select statements:
- //
- // // Stream generates values with DoSomething and sends them to out
- // // until DoSomething returns an error or ctx.Done is closed.
- // func Stream(ctx context.Context, out <-chan Value) error {
- // for {
- // v, err := DoSomething(ctx)
- // if err != nil {
- // return err
- // }
- // select {
- // case <-ctx.Done():
- // return ctx.Err()
- // case out <- v:
- // }
- // }
- // }
- //
- // See http://blog.golang.org/pipelines for more examples of how to use
- // a Done channel for cancelation.
- Done() <-chan struct{}
-
- // Err returns a non-nil error value after Done is closed. Err returns
- // Canceled if the context was canceled or DeadlineExceeded if the
- // context's deadline passed. No other values for Err are defined.
- // After Done is closed, successive calls to Err return the same value.
- Err() error
-
- // Value returns the value associated with this context for key, or nil
- // if no value is associated with key. Successive calls to Value with
- // the same key returns the same result.
- //
- // Use context values only for request-scoped data that transits
- // processes and API boundaries, not for passing optional parameters to
- // functions.
- //
- // A key identifies a specific value in a Context. Functions that wish
- // to store values in Context typically allocate a key in a global
- // variable then use that key as the argument to context.WithValue and
- // Context.Value. A key can be any type that supports equality;
- // packages should define keys as an unexported type to avoid
- // collisions.
- //
- // Packages that define a Context key should provide type-safe accessors
- // for the values stores using that key:
- //
- // // Package user defines a User type that's stored in Contexts.
- // package user
- //
- // import "golang.org/x/net/context"
- //
- // // User is the type of value stored in the Contexts.
- // type User struct {...}
- //
- // // key is an unexported type for keys defined in this package.
- // // This prevents collisions with keys defined in other packages.
- // type key int
- //
- // // userKey is the key for user.User values in Contexts. It is
- // // unexported; clients use user.NewContext and user.FromContext
- // // instead of using this key directly.
- // var userKey key = 0
- //
- // // NewContext returns a new Context that carries value u.
- // func NewContext(ctx context.Context, u *User) context.Context {
- // return context.WithValue(ctx, userKey, u)
- // }
- //
- // // FromContext returns the User value stored in ctx, if any.
- // func FromContext(ctx context.Context) (*User, bool) {
- // u, ok := ctx.Value(userKey).(*User)
- // return u, ok
- // }
- Value(key interface{}) interface{}
-}
-
-// Canceled is the error returned by Context.Err when the context is canceled.
-var Canceled = errors.New("context canceled")
-
-// DeadlineExceeded is the error returned by Context.Err when the context's
-// deadline passes.
-var DeadlineExceeded = errors.New("context deadline exceeded")
-
// An emptyCtx is never canceled, has no values, and has no deadline. It is not
// struct{}, since vars of this type must have distinct addresses.
type emptyCtx int
@@ -180,27 +48,12 @@ var (
todo = new(emptyCtx)
)
-// Background returns a non-nil, empty Context. It is never canceled, has no
-// values, and has no deadline. It is typically used by the main function,
-// initialization, and tests, and as the top-level Context for incoming
-// requests.
-func Background() Context {
- return background
-}
-
-// TODO returns a non-nil, empty Context. Code should use context.TODO when
-// it's unclear which Context to use or it is not yet available (because the
-// surrounding function has not yet been extended to accept a Context
-// parameter). TODO is recognized by static analysis tools that determine
-// whether Contexts are propagated correctly in a program.
-func TODO() Context {
- return todo
-}
+// Canceled is the error returned by Context.Err when the context is canceled.
+var Canceled = errors.New("context canceled")
-// A CancelFunc tells an operation to abandon its work.
-// A CancelFunc does not wait for the work to stop.
-// After the first call, subsequent calls to a CancelFunc do nothing.
-type CancelFunc func()
+// DeadlineExceeded is the error returned by Context.Err when the context's
+// deadline passes.
+var DeadlineExceeded = errors.New("context deadline exceeded")
// WithCancel returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed when the returned cancel function is called
@@ -210,13 +63,13 @@ type CancelFunc func()
// call cancel as soon as the operations running in this Context complete.
func WithCancel(parent Context) (ctx Context, cancel CancelFunc) {
c := newCancelCtx(parent)
- propagateCancel(parent, &c)
- return &c, func() { c.cancel(true, Canceled) }
+ propagateCancel(parent, c)
+ return c, func() { c.cancel(true, Canceled) }
}
// newCancelCtx returns an initialized cancelCtx.
-func newCancelCtx(parent Context) cancelCtx {
- return cancelCtx{
+func newCancelCtx(parent Context) *cancelCtx {
+ return &cancelCtx{
Context: parent,
done: make(chan struct{}),
}
@@ -259,7 +112,7 @@ func parentCancelCtx(parent Context) (*cancelCtx, bool) {
case *cancelCtx:
return c, true
case *timerCtx:
- return &c.cancelCtx, true
+ return c.cancelCtx, true
case *valueCtx:
parent = c.Context
default:
@@ -377,7 +230,7 @@ func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc) {
// implement Done and Err. It implements cancel by stopping its timer then
// delegating to cancelCtx.cancel.
type timerCtx struct {
- cancelCtx
+ *cancelCtx
timer *time.Timer // Under cancelCtx.mu.
deadline time.Time
diff --git a/vendor/golang.org/x/net/dict/LICENSE b/vendor/golang.org/x/net/dict/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/net/dict/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/vendor/golang.org/x/net/dict/dict.go b/vendor/golang.org/x/net/dict/dict.go
index 58fef89..93e65c0 100644
--- a/src/vendor/golang.org/x/net/dict/dict.go
+++ b/vendor/golang.org/x/net/dict/dict.go
@@ -1,4 +1,4 @@
-// Copyright 2010 The Go Authors. All rights reserved.
+// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
diff --git a/vendor/gopkg.in/tylerb/graceful.v1/LICENSE b/vendor/gopkg.in/tylerb/graceful.v1/LICENSE
new file mode 100644
index 0000000..a4f2f28
--- /dev/null
+++ b/vendor/gopkg.in/tylerb/graceful.v1/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Tyler Bunnell
+
+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/src/vendor/github.com/stretchr/graceful/graceful.go b/vendor/gopkg.in/tylerb/graceful.v1/graceful.go
index d3a7175..a5e2395 100644
--- a/src/vendor/github.com/stretchr/graceful/graceful.go
+++ b/vendor/gopkg.in/tylerb/graceful.v1/graceful.go
@@ -10,8 +10,6 @@ import (
"sync"
"syscall"
"time"
-
- "golang.org/x/net/netutil"
)
// Server wraps an http.Server with graceful connection handling.
@@ -34,6 +32,11 @@ type Server struct {
// Limit the number of outstanding requests
ListenLimit int
+ // TCPKeepAlive sets the TCP keep-alive timeouts on accepted
+ // connections. It prunes dead TCP connections ( e.g. closing
+ // laptop mid-download)
+ TCPKeepAlive time.Duration
+
// ConnState specifies an optional callback function that is
// called when a client connection changes state. This is a proxy
// to the underlying http.Server's ConnState, and the original
@@ -41,8 +44,8 @@ type Server struct {
ConnState func(net.Conn, http.ConnState)
// BeforeShutdown is an optional callback function that is called
- // before the listener is closed.
- BeforeShutdown func()
+ // before the listener is closed. Returns true if shutdown is allowed
+ BeforeShutdown func() bool
// ShutdownInitiated is an optional callback function that is called
// when shutdown is initiated. It can be used to notify the client
@@ -54,6 +57,17 @@ type Server struct {
// manually with Stop().
NoSignalHandling bool
+ // Logger used to notify of errors on startup and on stop.
+ Logger *log.Logger
+
+ // LogFunc can be assigned with a logging function of your choice, allowing
+ // you to use whatever logging approach you would like
+ LogFunc func(format string, args ...interface{})
+
+ // Interrupted is true if the server is handling a SIGINT or SIGTERM
+ // signal and is thus shutting down.
+ Interrupted bool
+
// interrupt signals the listener to stop serving connections,
// and the server to shut down.
interrupt chan os.Signal
@@ -70,6 +84,9 @@ type Server struct {
// connections holds all connections managed by graceful
connections map[net.Conn]struct{}
+
+ // idleConnections holds all idle connections managed by graceful
+ idleConnections map[net.Conn]struct{}
}
// Run serves the http.Handler with graceful shutdown enabled.
@@ -78,25 +95,42 @@ type Server struct {
// If timeout is 0, the server never times out. It waits for all active requests to finish.
func Run(addr string, timeout time.Duration, n http.Handler) {
srv := &Server{
- Timeout: timeout,
- Server: &http.Server{Addr: addr, Handler: n},
+ Timeout: timeout,
+ TCPKeepAlive: 3 * time.Minute,
+ Server: &http.Server{Addr: addr, Handler: n},
+ // Logger: DefaultLogger(),
}
if err := srv.ListenAndServe(); err != nil {
if opErr, ok := err.(*net.OpError); !ok || (ok && opErr.Op != "accept") {
- logger := log.New(os.Stdout, "[graceful] ", 0)
- logger.Fatal(err)
+ srv.logf("%s", err)
+ os.Exit(1)
}
}
}
+// RunWithErr is an alternative version of Run function which can return error.
+//
+// Unlike Run this version will not exit the program if an error is encountered but will
+// return it instead.
+func RunWithErr(addr string, timeout time.Duration, n http.Handler) error {
+ srv := &Server{
+ Timeout: timeout,
+ TCPKeepAlive: 3 * time.Minute,
+ Server: &http.Server{Addr: addr, Handler: n},
+ Logger: DefaultLogger(),
+ }
+
+ return srv.ListenAndServe()
+}
+
// ListenAndServe is equivalent to http.Server.ListenAndServe with graceful shutdown enabled.
//
// timeout is the duration to wait until killing active requests and stopping the server.
// If timeout is 0, the server never times out. It waits for all active requests to finish.
func ListenAndServe(server *http.Server, timeout time.Duration) error {
- srv := &Server{Timeout: timeout, Server: server}
+ srv := &Server{Timeout: timeout, Server: server, Logger: DefaultLogger()}
return srv.ListenAndServe()
}
@@ -107,12 +141,12 @@ func (srv *Server) ListenAndServe() error {
if addr == "" {
addr = ":http"
}
- l, err := net.Listen("tcp", addr)
+ conn, err := srv.newTCPListener(addr)
if err != nil {
return err
}
- return srv.Serve(l)
+ return srv.Serve(conn)
}
// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled.
@@ -120,7 +154,7 @@ func (srv *Server) ListenAndServe() error {
// timeout is the duration to wait until killing active requests and stopping the server.
// If timeout is 0, the server never times out. It waits for all active requests to finish.
func ListenAndServeTLS(server *http.Server, certFile, keyFile string, timeout time.Duration) error {
- srv := &Server{Timeout: timeout, Server: server}
+ srv := &Server{Timeout: timeout, Server: server, Logger: DefaultLogger()}
return srv.ListenAndServeTLS(certFile, keyFile)
}
@@ -138,9 +172,6 @@ func (srv *Server) ListenTLS(certFile, keyFile string) (net.Listener, error) {
if srv.TLSConfig != nil {
*config = *srv.TLSConfig
}
- if config.NextProtos == nil {
- config.NextProtos = []string{"http/1.1"}
- }
var err error
config.Certificates = make([]tls.Certificate, 1)
@@ -149,15 +180,42 @@ func (srv *Server) ListenTLS(certFile, keyFile string) (net.Listener, error) {
return nil, err
}
- conn, err := net.Listen("tcp", addr)
+ // Enable http2
+ enableHTTP2ForTLSConfig(config)
+
+ conn, err := srv.newTCPListener(addr)
if err != nil {
return nil, err
}
+ srv.TLSConfig = config
+
tlsListener := tls.NewListener(conn, config)
return tlsListener, nil
}
+// Enable HTTP2ForTLSConfig explicitly enables http/2 for a TLS Config. This is due to changes in Go 1.7 where
+// http servers are no longer automatically configured to enable http/2 if the server's TLSConfig is set.
+// See https://github.com/golang/go/issues/15908
+func enableHTTP2ForTLSConfig(t *tls.Config) {
+
+ if TLSConfigHasHTTP2Enabled(t) {
+ return
+ }
+
+ t.NextProtos = append(t.NextProtos, "h2")
+}
+
+// TLSConfigHasHTTP2Enabled checks to see if a given TLS Config has http2 enabled.
+func TLSConfigHasHTTP2Enabled(t *tls.Config) bool {
+ for _, value := range t.NextProtos {
+ if value == "h2" {
+ return true
+ }
+ }
+ return false
+}
+
// ListenAndServeTLS is equivalent to http.Server.ListenAndServeTLS with graceful shutdown enabled.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
l, err := srv.ListenTLS(certFile, keyFile)
@@ -176,11 +234,13 @@ func (srv *Server) ListenAndServeTLSConfig(config *tls.Config) error {
addr = ":https"
}
- conn, err := net.Listen("tcp", addr)
+ conn, err := srv.newTCPListener(addr)
if err != nil {
return err
}
+ srv.TLSConfig = config
+
tlsListener := tls.NewListener(conn, config)
return srv.Serve(tlsListener)
}
@@ -190,7 +250,8 @@ func (srv *Server) ListenAndServeTLSConfig(config *tls.Config) error {
// timeout is the duration to wait until killing active requests and stopping the server.
// If timeout is 0, the server never times out. It waits for all active requests to finish.
func Serve(server *http.Server, l net.Listener, timeout time.Duration) error {
- srv := &Server{Timeout: timeout, Server: server}
+ srv := &Server{Timeout: timeout, Server: server, Logger: DefaultLogger()}
+
return srv.Serve(l)
}
@@ -198,20 +259,33 @@ func Serve(server *http.Server, l net.Listener, timeout time.Duration) error {
func (srv *Server) Serve(listener net.Listener) error {
if srv.ListenLimit != 0 {
- listener = netutil.LimitListener(listener, srv.ListenLimit)
+ listener = LimitListener(listener, srv.ListenLimit)
}
+ // Make our stopchan
+ srv.StopChan()
+
// Track connection state
add := make(chan net.Conn)
+ idle := make(chan net.Conn)
+ active := make(chan net.Conn)
remove := make(chan net.Conn)
srv.Server.ConnState = func(conn net.Conn, state http.ConnState) {
switch state {
case http.StateNew:
add <- conn
+ case http.StateActive:
+ active <- conn
+ case http.StateIdle:
+ idle <- conn
case http.StateClosed, http.StateHijacked:
remove <- conn
}
+
+ srv.stopLock.Lock()
+ defer srv.stopLock.Unlock()
+
if srv.ConnState != nil {
srv.ConnState(conn, state)
}
@@ -220,7 +294,7 @@ func (srv *Server) Serve(listener net.Listener) error {
// Manage open connections
shutdown := make(chan chan struct{})
kill := make(chan struct{})
- go srv.manageConnections(add, remove, shutdown, kill)
+ go srv.manageConnections(add, idle, active, remove, shutdown, kill)
interrupt := srv.interruptChan()
// Set up the interrupt handler
@@ -259,10 +333,11 @@ func (srv *Server) Serve(listener net.Listener) error {
// command to stop the server.
func (srv *Server) Stop(timeout time.Duration) {
srv.stopLock.Lock()
+ defer srv.stopLock.Unlock()
+
srv.Timeout = timeout
interrupt := srv.interruptChan()
interrupt <- syscall.SIGINT
- srv.stopLock.Unlock()
}
// StopChan gets the stop channel which will block until
@@ -270,34 +345,62 @@ func (srv *Server) Stop(timeout time.Duration) {
// Callers should never close the stop channel.
func (srv *Server) StopChan() <-chan struct{} {
srv.chanLock.Lock()
+ defer srv.chanLock.Unlock()
+
if srv.stopChan == nil {
srv.stopChan = make(chan struct{})
}
- srv.chanLock.Unlock()
return srv.stopChan
}
-func (srv *Server) manageConnections(add, remove chan net.Conn, shutdown chan chan struct{}, kill chan struct{}) {
+// DefaultLogger returns the logger used by Run, RunWithErr, ListenAndServe, ListenAndServeTLS and Serve.
+// The logger outputs to STDERR by default.
+func DefaultLogger() *log.Logger {
+ return log.New(os.Stderr, "[graceful] ", 0)
+}
+
+func (srv *Server) manageConnections(add, idle, active, remove chan net.Conn, shutdown chan chan struct{}, kill chan struct{}) {
var done chan struct{}
srv.connections = map[net.Conn]struct{}{}
+ srv.idleConnections = map[net.Conn]struct{}{}
for {
select {
case conn := <-add:
srv.connections[conn] = struct{}{}
+ case conn := <-idle:
+ srv.idleConnections[conn] = struct{}{}
+ case conn := <-active:
+ delete(srv.idleConnections, conn)
case conn := <-remove:
delete(srv.connections, conn)
+ delete(srv.idleConnections, conn)
if done != nil && len(srv.connections) == 0 {
done <- struct{}{}
return
}
case done = <-shutdown:
- if len(srv.connections) == 0 {
+ if len(srv.connections) == 0 && len(srv.idleConnections) == 0 {
done <- struct{}{}
return
}
+ // a shutdown request has been received. if we have open idle
+ // connections, we must close all of them now. this prevents idle
+ // connections from holding the server open while waiting for them to
+ // hit their idle timeout.
+ for k := range srv.idleConnections {
+ if err := k.Close(); err != nil {
+ srv.logf("[ERROR] %s", err)
+ }
+ }
case <-kill:
+ srv.stopLock.Lock()
+ defer srv.stopLock.Unlock()
+
+ srv.Server.ConnState = nil
for k := range srv.connections {
- _ = k.Close() // nothing to do here if it errors
+ if err := k.Close(); err != nil {
+ srv.logf("[ERROR] %s", err)
+ }
}
return
}
@@ -306,34 +409,48 @@ func (srv *Server) manageConnections(add, remove chan net.Conn, shutdown chan ch
func (srv *Server) interruptChan() chan os.Signal {
srv.chanLock.Lock()
+ defer srv.chanLock.Unlock()
+
if srv.interrupt == nil {
srv.interrupt = make(chan os.Signal, 1)
}
- srv.chanLock.Unlock()
return srv.interrupt
}
func (srv *Server) handleInterrupt(interrupt chan os.Signal, quitting chan struct{}, listener net.Listener) {
- <-interrupt
-
- if srv.BeforeShutdown != nil {
- srv.BeforeShutdown()
- }
+ for _ = range interrupt {
+ if srv.Interrupted {
+ srv.logf("already shutting down")
+ continue
+ }
+ srv.logf("shutdown initiated")
+ srv.Interrupted = true
+ if srv.BeforeShutdown != nil {
+ if !srv.BeforeShutdown() {
+ srv.Interrupted = false
+ continue
+ }
+ }
- close(quitting)
- srv.SetKeepAlivesEnabled(false)
- _ = listener.Close() // we are shutting down anyway. ignore error.
+ close(quitting)
+ srv.SetKeepAlivesEnabled(false)
+ if err := listener.Close(); err != nil {
+ srv.logf("[ERROR] %s", err)
+ }
- if srv.ShutdownInitiated != nil {
- srv.ShutdownInitiated()
+ if srv.ShutdownInitiated != nil {
+ srv.ShutdownInitiated()
+ }
}
+}
- srv.stopLock.Lock()
- signal.Stop(interrupt)
- close(interrupt)
- srv.interrupt = nil
- srv.stopLock.Unlock()
+func (srv *Server) logf(format string, args ...interface{}) {
+ if srv.LogFunc != nil {
+ srv.LogFunc(format, args...)
+ } else if srv.Logger != nil {
+ srv.Logger.Printf(format, args...)
+ }
}
func (srv *Server) shutdown(shutdown chan chan struct{}, kill chan struct{}) {
@@ -357,3 +474,14 @@ func (srv *Server) shutdown(shutdown chan chan struct{}, kill chan struct{}) {
}
srv.chanLock.Unlock()
}
+
+func (srv *Server) newTCPListener(addr string) (net.Listener, error) {
+ conn, err := net.Listen("tcp", addr)
+ if err != nil {
+ return conn, err
+ }
+ if srv.TCPKeepAlive != 0 {
+ conn = keepAliveListener{conn, srv.TCPKeepAlive}
+ }
+ return conn, nil
+}
diff --git a/vendor/gopkg.in/tylerb/graceful.v1/keepalive_listener.go b/vendor/gopkg.in/tylerb/graceful.v1/keepalive_listener.go
new file mode 100644
index 0000000..1484bc2
--- /dev/null
+++ b/vendor/gopkg.in/tylerb/graceful.v1/keepalive_listener.go
@@ -0,0 +1,32 @@
+package graceful
+
+import (
+ "net"
+ "time"
+)
+
+type keepAliveConn interface {
+ SetKeepAlive(bool) error
+ SetKeepAlivePeriod(d time.Duration) error
+}
+
+// keepAliveListener sets TCP keep-alive timeouts on accepted
+// connections. It's used by ListenAndServe and ListenAndServeTLS so
+// dead TCP connections (e.g. closing laptop mid-download) eventually
+// go away.
+type keepAliveListener struct {
+ net.Listener
+ keepAlivePeriod time.Duration
+}
+
+func (ln keepAliveListener) Accept() (net.Conn, error) {
+ c, err := ln.Listener.Accept()
+ if err != nil {
+ return nil, err
+ }
+
+ kac := c.(keepAliveConn)
+ kac.SetKeepAlive(true)
+ kac.SetKeepAlivePeriod(ln.keepAlivePeriod)
+ return c, nil
+}
diff --git a/vendor/gopkg.in/tylerb/graceful.v1/limit_listen.go b/vendor/gopkg.in/tylerb/graceful.v1/limit_listen.go
new file mode 100644
index 0000000..ce32ce9
--- /dev/null
+++ b/vendor/gopkg.in/tylerb/graceful.v1/limit_listen.go
@@ -0,0 +1,77 @@
+// Copyright 2013 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package graceful
+
+import (
+ "errors"
+ "net"
+ "sync"
+ "time"
+)
+
+// ErrNotTCP indicates that network connection is not a TCP connection.
+var ErrNotTCP = errors.New("only tcp connections have keepalive")
+
+// LimitListener returns a Listener that accepts at most n simultaneous
+// connections from the provided Listener.
+func LimitListener(l net.Listener, n int) net.Listener {
+ return &limitListener{l, make(chan struct{}, n)}
+}
+
+type limitListener struct {
+ net.Listener
+ sem chan struct{}
+}
+
+func (l *limitListener) acquire() { l.sem <- struct{}{} }
+func (l *limitListener) release() { <-l.sem }
+
+func (l *limitListener) Accept() (net.Conn, error) {
+ l.acquire()
+ c, err := l.Listener.Accept()
+ if err != nil {
+ l.release()
+ return nil, err
+ }
+ return &limitListenerConn{Conn: c, release: l.release}, nil
+}
+
+type limitListenerConn struct {
+ net.Conn
+ releaseOnce sync.Once
+ release func()
+}
+
+func (l *limitListenerConn) Close() error {
+ err := l.Conn.Close()
+ l.releaseOnce.Do(l.release)
+ return err
+}
+
+func (l *limitListenerConn) SetKeepAlive(doKeepAlive bool) error {
+ tcpc, ok := l.Conn.(*net.TCPConn)
+ if !ok {
+ return ErrNotTCP
+ }
+ return tcpc.SetKeepAlive(doKeepAlive)
+}
+
+func (l *limitListenerConn) SetKeepAlivePeriod(d time.Duration) error {
+ tcpc, ok := l.Conn.(*net.TCPConn)
+ if !ok {
+ return ErrNotTCP
+ }
+ return tcpc.SetKeepAlivePeriod(d)
+}
diff --git a/vendor/gopkg.in/tylerb/graceful.v1/tests/main.go b/vendor/gopkg.in/tylerb/graceful.v1/tests/main.go
new file mode 100644
index 0000000..9380ae6
--- /dev/null
+++ b/vendor/gopkg.in/tylerb/graceful.v1/tests/main.go
@@ -0,0 +1,40 @@
+package main
+
+import (
+ "fmt"
+ "sync"
+
+ "github.com/urfave/negroni"
+ "gopkg.in/tylerb/graceful.v1"
+)
+
+func main() {
+
+ var wg sync.WaitGroup
+
+ wg.Add(3)
+ go func() {
+ n := negroni.New()
+ fmt.Println("Launching server on :3000")
+ graceful.Run(":3000", 0, n)
+ fmt.Println("Terminated server on :3000")
+ wg.Done()
+ }()
+ go func() {
+ n := negroni.New()
+ fmt.Println("Launching server on :3001")
+ graceful.Run(":3001", 0, n)
+ fmt.Println("Terminated server on :3001")
+ wg.Done()
+ }()
+ go func() {
+ n := negroni.New()
+ fmt.Println("Launching server on :3002")
+ graceful.Run(":3002", 0, n)
+ fmt.Println("Terminated server on :3002")
+ wg.Done()
+ }()
+ fmt.Println("Press ctrl+c. All servers should terminate.")
+ wg.Wait()
+
+}
diff --git a/vendor/manifest b/vendor/manifest
new file mode 100644
index 0000000..b7244eb
--- /dev/null
+++ b/vendor/manifest
@@ -0,0 +1,135 @@
+{
+ "version": 0,
+ "dependencies": [
+ {
+ "importpath": "github.com/alexedwards/stack",
+ "repository": "https://github.com/alexedwards/stack",
+ "vcs": "git",
+ "revision": "3ba431d5d12d93bf95dd641ad6aad6691e5eafe9",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/codegangsta/inject",
+ "repository": "https://github.com/codegangsta/inject",
+ "vcs": "git",
+ "revision": "33e0aa1cb7c019ccc3fbe049a8262a6403d30504",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/codegangsta/negroni",
+ "repository": "https://github.com/codegangsta/negroni",
+ "vcs": "git",
+ "revision": "cd9734011043904139c24dbad9a71b21f1586f36",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/go-martini/martini",
+ "repository": "https://github.com/go-martini/martini",
+ "vcs": "git",
+ "revision": "fe605b5cd210047ae3bb73d2b69a5b912a9b423d",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/julienschmidt/httprouter",
+ "repository": "https://github.com/julienschmidt/httprouter",
+ "vcs": "git",
+ "revision": "5dd70ee059943e81987a817fa1a755b11dd119c1",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/justinas/alice",
+ "repository": "https://github.com/justinas/alice",
+ "vcs": "git",
+ "revision": "1051eaf52fcafdd87ead59d28b065f1fcb8274ec",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/martini-contrib/render",
+ "repository": "https://github.com/martini-contrib/render",
+ "vcs": "git",
+ "revision": "ec18f8345a1181146728238980606fb1d6f40e8c",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/oxtoacart/bpool",
+ "repository": "https://github.com/oxtoacart/bpool",
+ "vcs": "git",
+ "revision": "4e1c5567d7c2dd59fa4c7c83d34c2f3528b025d6",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/rs/cors",
+ "repository": "https://github.com/rs/cors",
+ "vcs": "git",
+ "revision": "a62a804a8a009876ca59105f7899938a1349f4b3",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/rs/xhandler",
+ "repository": "https://github.com/rs/xhandler",
+ "vcs": "git",
+ "revision": "ed27b6fd65218132ee50cd95f38474a3d8a2cd12",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/stretchr/graceful",
+ "repository": "https://github.com/stretchr/graceful",
+ "vcs": "git",
+ "revision": "4df1190835320af7076dfcf27b3d071fd3612caf",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/urfave/negroni",
+ "repository": "https://github.com/urfave/negroni",
+ "vcs": "git",
+ "revision": "cd9734011043904139c24dbad9a71b21f1586f36",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "github.com/zenazn/goji",
+ "repository": "https://github.com/zenazn/goji",
+ "vcs": "git",
+ "revision": "4d7077956293261309684d3cf1af673f773c6819",
+ "branch": "master",
+ "notests": true
+ },
+ {
+ "importpath": "golang.org/x/net/context",
+ "repository": "https://go.googlesource.com/net",
+ "vcs": "git",
+ "revision": "6cdc0daab091c43fc46193327e0047b4f883c613",
+ "branch": "master",
+ "path": "/context",
+ "notests": true
+ },
+ {
+ "importpath": "golang.org/x/net/dict",
+ "repository": "https://go.googlesource.com/net",
+ "vcs": "git",
+ "revision": "6cdc0daab091c43fc46193327e0047b4f883c613",
+ "branch": "master",
+ "path": "/dict",
+ "notests": true
+ },
+ {
+ "importpath": "gopkg.in/tylerb/graceful.v1",
+ "repository": "https://gopkg.in/tylerb/graceful.v1",
+ "vcs": "git",
+ "revision": "50a48b6e73fcc75b45e22c05b79629a67c79e938",
+ "branch": "master",
+ "notests": true
+ }
+ ]
+} \ No newline at end of file