diff --git a/vendor/github.com/zenazn/goji/.travis.yml b/vendor/github.com/zenazn/goji/.travis.yml deleted file mode 100644 index 35410e2..0000000 --- a/vendor/github.com/zenazn/goji/.travis.yml +++ /dev/null @@ -1,33 +0,0 @@ -language: go - -matrix: - include: - - go: 1.2 - install: - - go get golang.org/x/tools/cmd/cover - - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v - - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v - - go: 1.3 - install: - - go get golang.org/x/tools/cmd/cover - - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v - - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v - - go: 1.4 - install: - - go get golang.org/x/tools/cmd/cover - - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v - - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v - - go: 1.5 - install: - - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v - - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v - - go: 1.6 - install: - - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v - - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v - - go: tip - install: - - go list -f '{{range .Imports}}{{.}} {{end}}' ./... | xargs go get -v - - go list -f '{{range .TestImports}}{{.}} {{end}}' ./... | xargs go get -v -script: - - go test -cover ./... diff --git a/vendor/github.com/zenazn/goji/LICENSE b/vendor/github.com/zenazn/goji/LICENSE deleted file mode 100644 index 446aba0..0000000 --- a/vendor/github.com/zenazn/goji/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -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/README.md b/vendor/github.com/zenazn/goji/README.md deleted file mode 100644 index 82df6fe..0000000 --- a/vendor/github.com/zenazn/goji/README.md +++ /dev/null @@ -1,176 +0,0 @@ -Goji -==== - -[![GoDoc](https://godoc.org/github.com/zenazn/goji/web?status.svg)](https://godoc.org/github.com/zenazn/goji/web) [![Build Status](https://travis-ci.org/zenazn/goji.svg?branch=master)](https://travis-ci.org/zenazn/goji) - -Goji is a minimalistic web framework that values composability and simplicity. - -This project has been superseded by a [new version of Goji][goji2] by the same -author, which has very similar primitives and semantics, but has been updated to -reflect several years of experience with this library and the surrounding Go -ecosystem. This project is still well-loved and well-maintained, and will be for -the foreseeable future, but new projects are encouraged to use `goji.io` -instead. - -[goji2]: https://goji.io - -Example -------- - -```go -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() -} -``` - -Goji also includes a [sample application][sample] in the `example` folder which -was artificially constructed to show off all of Goji's features. Check it out! - -[sample]: https://github.com/zenazn/goji/tree/master/example - - -Features --------- - -* Compatible with `net/http` -* URL patterns (both Sinatra style `/foo/:bar` patterns and regular expressions, - as well as [custom patterns][pattern]) -* Reconfigurable middleware stack -* Context/environment object threaded through middleware and handlers -* Automatic support for [Einhorn][einhorn], systemd, and [more][bind] -* [Graceful shutdown][graceful], and zero-downtime graceful reload when combined - with Einhorn. -* High in antioxidants - -[einhorn]: https://github.com/stripe/einhorn -[bind]: http://godoc.org/github.com/zenazn/goji/bind -[graceful]: http://godoc.org/github.com/zenazn/goji/graceful -[pattern]: https://godoc.org/github.com/zenazn/goji/web#Pattern - - -Stability ---------- - -Goji's API is essentially frozen, and guarantees to never break compatibility -with existing code (under similar rules to the Go project's -[guidelines][compat]). Goji is suitable for use in production, and has served -billions of requests across several companies. - -[compat]: https://golang.org/doc/go1compat - - -Is it any good? ---------------- - -Maybe! - -There are [plenty][revel] of [other][gorilla] [good][pat] [Go][martini] -[web][gocraft] [frameworks][tiger] out there. Goji is by no means especially -novel, nor is it uniquely good. The primary difference between Goji and other -frameworks—and the primary reason I think Goji is any good—is its philosophy: - -Goji first of all attempts to be simple. It is of the Sinatra and Flask school -of web framework design, and not the Rails/Django one. If you want me to tell -you what directory you should put your models in, or if you want built-in flash -sessions, you won't have a good time with Goji. - -Secondly, Goji attempts to be composable. It is fully composable with net/http, -and can be used as a `http.Handler`, or can serve arbitrary `http.Handler`s. At -least a few HTTP frameworks share this property, and is not particularly novel. -The more interesting property in my mind is that Goji is fully composable with -itself: it defines an interface (`web.Handler`) which is both fully compatible -with `http.Handler` and allows Goji to perform a "protocol upgrade" of sorts -when it detects that it is talking to itself (or another `web.Handler` -compatible component). `web.Handler` is at the core of Goji's interfaces and is -what allows it to share request contexts across unrelated objects. - -Third, Goji is not magic. One of my favorite existing frameworks is -[Martini][martini], but I rejected it in favor of building Goji because I -thought it was too magical. Goji's web package does not use reflection at all, -which is not in itself a sign of API quality, but to me at least seems to -suggest it. - -Finally, Goji gives you enough rope to hang yourself with. One of my other -favorite libraries, [pat][pat], implements Sinatra-like routing in a -particularly elegant way, but because of its reliance on net/http's interfaces, -doesn't allow programmers to thread their own state through the request handling -process. Implementing arbitrary context objects was one of the primary -motivations behind abandoning pat to write Goji. - -[revel]: http://revel.github.io/ -[gorilla]: http://www.gorillatoolkit.org/ -[pat]: https://github.com/bmizerany/pat -[martini]: http://martini.codegangsta.io/ -[gocraft]: https://github.com/gocraft/web -[tiger]: https://github.com/rcrowley/go-tigertonic - - -Is it fast? ------------ - -[Yeah][bench1], [it is][bench2]. Goji is among the fastest HTTP routers out -there, and is very gentle on the garbage collector. - -But that's sort of missing the point. Almost all Go routers are fast enough for -almost all purposes. In my opinion, what matters more is how simple and flexible -the routing semantics are. - -Goji provides results indistinguishable from naively trying routes one after -another. This means that a route added before another route will be attempted -before that route as well. This is perhaps the most simple and most intuitive -interface a router can provide, and makes routes very easy to understand and -debug. - -Goji's router is also very flexible: in addition to the standard Sinatra-style -patterns and regular expression patterns, you can define [custom -patterns][pattern] to perform whatever custom matching logic you desire. Custom -patterns of course are fully compatible with the routing semantics above. - -It's easy (and quite a bit of fun!) to get carried away by microbenchmarks, but -at the end of the day you're not going to miss those extra hundred nanoseconds -on a request. What matters is that you aren't compromising on the API for a -handful of CPU cycles. - -[bench1]: https://gist.github.com/zenazn/c5c8528efe1a00634096 -[bench2]: https://github.com/julienschmidt/go-http-routing-benchmark - - -Third-Party Libraries ---------------------- - -Goji is already compatible with a great many third-party libraries that are -themselves compatible with `net/http`, however some library authors have gone -out of their way to include Goji compatibility specifically, perhaps by -integrating more tightly with Goji's `web.C` or by providing a custom pattern -type. An informal list of such libraries is maintained [on the wiki][third]; -feel free to add to it as you see fit. - -[third]: https://github.com/zenazn/goji/wiki/Third-Party-Libraries - - -Contributing ------------- - -Please do! I love pull requests, and I love pull requests that include tests -even more. Goji's core packages have pretty good code coverage (yay code -coverage gamification!), and if you have the time to write tests I'd like to -keep it that way. - -In addition to contributing code, I'd love to know what you think about Goji. -Please open an issue or send me an email with your thoughts; it'd mean a lot to -me. diff --git a/vendor/github.com/zenazn/goji/bind/bind.go b/vendor/github.com/zenazn/goji/bind/bind.go deleted file mode 100644 index 8e783bf..0000000 --- a/vendor/github.com/zenazn/goji/bind/bind.go +++ /dev/null @@ -1,145 +0,0 @@ -/* -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() -} - -// 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 port 8000, 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() { - defaultBind := ":8000" - if s := Sniff(); s != "" { - defaultBind = s - } - flag.StringVar(&bind, "bind", defaultBind, - `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 deleted file mode 100644 index e695c0e..0000000 --- a/vendor/github.com/zenazn/goji/bind/einhorn.go +++ /dev/null @@ -1,91 +0,0 @@ -// +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 deleted file mode 100644 index 093707f..0000000 --- a/vendor/github.com/zenazn/goji/bind/einhorn_stub.go +++ /dev/null @@ -1,12 +0,0 @@ -// +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 deleted file mode 100644 index e7cd8e4..0000000 --- a/vendor/github.com/zenazn/goji/bind/systemd.go +++ /dev/null @@ -1,36 +0,0 @@ -// +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 deleted file mode 100644 index 4ad4d20..0000000 --- a/vendor/github.com/zenazn/goji/bind/systemd_stub.go +++ /dev/null @@ -1,6 +0,0 @@ -// +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 deleted file mode 100644 index 540e792..0000000 --- a/vendor/github.com/zenazn/goji/default.go +++ /dev/null @@ -1,102 +0,0 @@ -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/.gitignore b/vendor/github.com/zenazn/goji/example/.gitignore deleted file mode 100644 index 33a9488..0000000 --- a/vendor/github.com/zenazn/goji/example/.gitignore +++ /dev/null @@ -1 +0,0 @@ -example diff --git a/vendor/github.com/zenazn/goji/example/README.md b/vendor/github.com/zenazn/goji/example/README.md deleted file mode 100644 index 8d33103..0000000 --- a/vendor/github.com/zenazn/goji/example/README.md +++ /dev/null @@ -1,10 +0,0 @@ -Gritter -======= - -Gritter is an example application built using Goji, where people who have -nothing better to do can post short 140-character "greets." - -A good place to start is with `main.go`, which contains a well-commented -walkthrough of Goji's features. Gritter uses a couple custom middlewares, which -have been arbitrarily placed in `middleware.go`. Finally some uninteresting -"database models" live in `models.go`. diff --git a/vendor/github.com/zenazn/goji/example/main.go b/vendor/github.com/zenazn/goji/example/main.go deleted file mode 100644 index b2bcf6f..0000000 --- a/vendor/github.com/zenazn/goji/example/main.go +++ /dev/null @@ -1,177 +0,0 @@ -// 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\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 deleted file mode 100644 index 9652ebb..0000000 --- a/vendor/github.com/zenazn/goji/example/middleware.go +++ /dev/null @@ -1,47 +0,0 @@ -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 deleted file mode 100644 index 4c34c08..0000000 --- a/vendor/github.com/zenazn/goji/example/models.go +++ /dev/null @@ -1,49 +0,0 @@ -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 deleted file mode 100644 index ab278cd..0000000 --- a/vendor/github.com/zenazn/goji/goji.go +++ /dev/null @@ -1,36 +0,0 @@ -/* -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 deleted file mode 100644 index a9027e5..0000000 --- a/vendor/github.com/zenazn/goji/graceful/clone.go +++ /dev/null @@ -1,11 +0,0 @@ -// +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 deleted file mode 100644 index 810b3a2..0000000 --- a/vendor/github.com/zenazn/goji/graceful/clone16.go +++ /dev/null @@ -1,34 +0,0 @@ -// +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 deleted file mode 100644 index 082d1c4..0000000 --- a/vendor/github.com/zenazn/goji/graceful/einhorn.go +++ /dev/null @@ -1,21 +0,0 @@ -// +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 deleted file mode 100644 index ff9b186..0000000 --- a/vendor/github.com/zenazn/goji/graceful/graceful.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -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 deleted file mode 100644 index 7b34b47..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/conn.go +++ /dev/null @@ -1,151 +0,0 @@ -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/conn_test.go b/vendor/github.com/zenazn/goji/graceful/listener/conn_test.go deleted file mode 100644 index ff26e32..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/conn_test.go +++ /dev/null @@ -1,198 +0,0 @@ -package listener - -import ( - "io" - "strings" - "testing" - "time" -) - -func TestManualRead(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Manual) - - go c.AllowRead() - wc.Read(make([]byte, 1024)) - - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if !c.Closed() { - t.Error("Read() should not make connection not-idle") - } -} - -func TestAutomaticRead(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Automatic) - - go c.AllowRead() - wc.Read(make([]byte, 1024)) - - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if c.Closed() { - t.Error("expected Read() to mark connection as in-use") - } -} - -func TestDeadlineRead(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Deadline) - - go c.AllowRead() - if _, err := wc.Read(make([]byte, 1024)); err != nil { - t.Fatalf("error reading from connection: %v", err) - } - - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if c.Closed() { - t.Error("expected Read() to mark connection as in-use") - } -} - -func TestDisownedRead(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Deadline) - - if err := Disown(wc); err != nil { - t.Fatalf("unexpected error disowning conn: %v", err) - } - if err := l.Close(); err != nil { - t.Fatalf("unexpected error closing listener: %v", err) - } - if err := l.Drain(); err != nil { - t.Fatalf("unexpected error draining listener: %v", err) - } - - go c.AllowRead() - if _, err := wc.Read(make([]byte, 1024)); err != nil { - t.Fatalf("error reading from connection: %v", err) - } -} - -func TestCloseConn(t *testing.T) { - t.Parallel() - l, _, wc := singleConn(t, Deadline) - - if err := MarkInUse(wc); err != nil { - t.Fatalf("error marking conn in use: %v", err) - } - if err := wc.Close(); err != nil { - t.Errorf("error closing connection: %v", err) - } - // This will hang if wc.Close() doesn't un-track the connection - if err := l.Drain(); err != nil { - t.Errorf("error draining listener: %v", err) - } -} - -// Regression test for issue #130. -func TestDisownedClose(t *testing.T) { - t.Parallel() - _, c, wc := singleConn(t, Deadline) - - if err := Disown(wc); err != nil { - t.Fatalf("unexpected error disowning conn: %v", err) - } - if err := wc.Close(); err != nil { - t.Errorf("error closing connection: %v", err) - } - if !c.Closed() { - t.Errorf("connection didn't get closed") - } -} - -func TestManualReadDeadline(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Manual) - - if err := MarkInUse(wc); err != nil { - t.Fatalf("error marking connection in use: %v", err) - } - if err := wc.SetReadDeadline(time.Now()); err != nil { - t.Fatalf("error setting read deadline: %v", err) - } - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if c.Closed() { - t.Error("SetReadDeadline() should not mark manual conn as idle") - } -} - -func TestAutomaticReadDeadline(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Automatic) - - if err := MarkInUse(wc); err != nil { - t.Fatalf("error marking connection in use: %v", err) - } - if err := wc.SetReadDeadline(time.Now()); err != nil { - t.Fatalf("error setting read deadline: %v", err) - } - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if c.Closed() { - t.Error("SetReadDeadline() should not mark automatic conn as idle") - } -} - -func TestDeadlineReadDeadline(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Deadline) - - if err := MarkInUse(wc); err != nil { - t.Fatalf("error marking connection in use: %v", err) - } - if err := wc.SetReadDeadline(time.Now()); err != nil { - t.Fatalf("error setting read deadline: %v", err) - } - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if !c.Closed() { - t.Error("SetReadDeadline() should mark deadline conn as idle") - } -} - -type readerConn struct { - fakeConn -} - -func (rc *readerConn) ReadFrom(r io.Reader) (int64, error) { - return 123, nil -} - -func TestReadFrom(t *testing.T) { - t.Parallel() - - l := makeFakeListener("net.Listener") - wl := Wrap(l, Manual) - c := &readerConn{ - fakeConn{ - read: make(chan struct{}), - write: make(chan struct{}), - closed: make(chan struct{}), - me: fakeAddr{"tcp", "local"}, - you: fakeAddr{"tcp", "remote"}, - }, - } - - go l.Enqueue(c) - wc, err := wl.Accept() - if err != nil { - t.Fatalf("error accepting connection: %v", err) - } - - // The io.MultiReader is a convenient hack to ensure that we're using - // our ReadFrom, not strings.Reader's WriteTo. - r := io.MultiReader(strings.NewReader("hello world")) - if _, err := io.Copy(wc, r); err != nil { - t.Fatalf("error copying: %v", err) - } -} diff --git a/vendor/github.com/zenazn/goji/graceful/listener/fake_test.go b/vendor/github.com/zenazn/goji/graceful/listener/fake_test.go deleted file mode 100644 index 083f6a8..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/fake_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package listener - -import ( - "net" - "time" -) - -type fakeAddr struct { - network, addr string -} - -func (f fakeAddr) Network() string { - return f.network -} -func (f fakeAddr) String() string { - return f.addr -} - -type fakeListener struct { - ch chan net.Conn - closed chan struct{} - addr net.Addr -} - -func makeFakeListener(addr string) *fakeListener { - a := fakeAddr{"tcp", addr} - return &fakeListener{ - ch: make(chan net.Conn), - closed: make(chan struct{}), - addr: a, - } -} - -func (f *fakeListener) Accept() (net.Conn, error) { - select { - case c := <-f.ch: - return c, nil - case <-f.closed: - return nil, errClosing - } -} -func (f *fakeListener) Close() error { - close(f.closed) - return nil -} - -func (f *fakeListener) Addr() net.Addr { - return f.addr -} - -func (f *fakeListener) Enqueue(c net.Conn) { - f.ch <- c -} - -type fakeConn struct { - read, write, closed chan struct{} - me, you net.Addr -} - -func makeFakeConn(me, you string) *fakeConn { - return &fakeConn{ - read: make(chan struct{}), - write: make(chan struct{}), - closed: make(chan struct{}), - me: fakeAddr{"tcp", me}, - you: fakeAddr{"tcp", you}, - } -} - -func (f *fakeConn) Read(buf []byte) (int, error) { - select { - case <-f.read: - return len(buf), nil - case <-f.closed: - return 0, errClosing - } -} - -func (f *fakeConn) Write(buf []byte) (int, error) { - select { - case <-f.write: - return len(buf), nil - case <-f.closed: - return 0, errClosing - } -} - -func (f *fakeConn) Close() error { - close(f.closed) - return nil -} - -func (f *fakeConn) LocalAddr() net.Addr { - return f.me -} -func (f *fakeConn) RemoteAddr() net.Addr { - return f.you -} -func (f *fakeConn) SetDeadline(t time.Time) error { - return nil -} -func (f *fakeConn) SetReadDeadline(t time.Time) error { - return nil -} -func (f *fakeConn) SetWriteDeadline(t time.Time) error { - return nil -} - -func (f *fakeConn) Closed() bool { - select { - case <-f.closed: - return true - default: - return false - } -} - -func (f *fakeConn) AllowRead() { - f.read <- struct{}{} -} -func (f *fakeConn) AllowWrite() { - f.write <- struct{}{} -} diff --git a/vendor/github.com/zenazn/goji/graceful/listener/listener.go b/vendor/github.com/zenazn/goji/graceful/listener/listener.go deleted file mode 100644 index 6c9c477..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/listener.go +++ /dev/null @@ -1,178 +0,0 @@ -/* -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/listener_test.go b/vendor/github.com/zenazn/goji/graceful/listener/listener_test.go deleted file mode 100644 index dcefdaa..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/listener_test.go +++ /dev/null @@ -1,156 +0,0 @@ -package listener - -import ( - "net" - "testing" - "time" -) - -// Helper for tests acting on a single accepted connection -func singleConn(t *testing.T, m mode) (*T, *fakeConn, net.Conn) { - l := makeFakeListener("net.Listener") - wl := Wrap(l, m) - c := makeFakeConn("local", "remote") - - go l.Enqueue(c) - wc, err := wl.Accept() - if err != nil { - t.Fatalf("error accepting connection: %v", err) - } - return wl, c, wc -} - -func TestAddr(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Manual) - - if a := l.Addr(); a.String() != "net.Listener" { - t.Errorf("addr was %v, wanted net.Listener", a) - } - - if c.LocalAddr() != wc.LocalAddr() { - t.Errorf("local addresses don't match: %v, %v", c.LocalAddr(), - wc.LocalAddr()) - } - if c.RemoteAddr() != wc.RemoteAddr() { - t.Errorf("remote addresses don't match: %v, %v", c.RemoteAddr(), - wc.RemoteAddr()) - } -} - -func TestBasicCloseIdle(t *testing.T) { - t.Parallel() - l, c, _ := singleConn(t, Manual) - - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if !c.Closed() { - t.Error("idle connection not closed") - } -} - -func TestMark(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Manual) - - if err := MarkInUse(wc); err != nil { - t.Fatalf("error marking %v in-use: %v", wc, err) - } - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if c.Closed() { - t.Errorf("manually in-use connection was closed") - } - - if err := MarkIdle(wc); err != nil { - t.Fatalf("error marking %v idle: %v", wc, err) - } - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - if !c.Closed() { - t.Error("manually idle connection was not closed") - } -} - -func TestDisown(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Manual) - - if err := Disown(wc); err != nil { - t.Fatalf("error disowning connection: %v", err) - } - if err := l.CloseIdle(); err != nil { - t.Fatalf("error closing idle connections: %v", err) - } - - if c.Closed() { - t.Errorf("disowned connection got closed") - } -} - -func TestDrain(t *testing.T) { - t.Parallel() - l, _, wc := singleConn(t, Manual) - - MarkInUse(wc) - start := time.Now() - go func() { - time.Sleep(50 * time.Millisecond) - MarkIdle(wc) - }() - if err := l.Drain(); err != nil { - t.Fatalf("error draining listener: %v", err) - } - end := time.Now() - if dt := end.Sub(start); dt < 50*time.Millisecond { - t.Errorf("expected at least 50ms wait, but got %v", dt) - } -} - -func TestDrainAll(t *testing.T) { - t.Parallel() - l, c, wc := singleConn(t, Manual) - - MarkInUse(wc) - if err := l.DrainAll(); err != nil { - t.Fatalf("error draining listener: %v", err) - } - if !c.Closed() { - t.Error("expected in-use connection to be closed") - } -} - -func TestErrors(t *testing.T) { - t.Parallel() - _, c, wc := singleConn(t, Manual) - if err := Disown(c); err == nil { - t.Error("expected error when disowning unmanaged net.Conn") - } - if err := MarkIdle(c); err == nil { - t.Error("expected error when marking unmanaged net.Conn idle") - } - if err := MarkInUse(c); err == nil { - t.Error("expected error when marking unmanaged net.Conn in use") - } - - if err := Disown(wc); err != nil { - t.Fatalf("unexpected error disowning socket: %v", err) - } - if err := Disown(wc); err == nil { - t.Error("expected error disowning socket twice") - } -} - -func TestClose(t *testing.T) { - t.Parallel() - l, c, _ := singleConn(t, Manual) - if err := l.Close(); err != nil { - t.Fatalf("error while closing listener: %v", err) - } - if c.Closed() { - t.Error("connection closed when listener was?") - } -} diff --git a/vendor/github.com/zenazn/goji/graceful/listener/race_test.go b/vendor/github.com/zenazn/goji/graceful/listener/race_test.go deleted file mode 100644 index 835d6b4..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/race_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package listener - -import ( - "fmt" - "math/rand" - "runtime" - "sync/atomic" - "testing" - "time" -) - -func init() { - // Just to make sure we get some variety - runtime.GOMAXPROCS(4 * runtime.NumCPU()) -} - -// Chosen by random die roll -const seed = 4611413766552969250 - -// This is mostly just fuzzing to see what happens. -func TestRace(t *testing.T) { - t.Parallel() - - l := makeFakeListener("net.Listener") - wl := Wrap(l, Automatic) - - var flag int32 - - go func() { - for i := 0; ; i++ { - laddr := fmt.Sprintf("local%d", i) - raddr := fmt.Sprintf("remote%d", i) - c := makeFakeConn(laddr, raddr) - go func() { - defer func() { - if r := recover(); r != nil { - if atomic.LoadInt32(&flag) != 0 { - return - } - panic(r) - } - }() - l.Enqueue(c) - }() - wc, err := wl.Accept() - if err != nil { - if atomic.LoadInt32(&flag) != 0 { - return - } - t.Fatalf("error accepting connection: %v", err) - } - - go func() { - for { - time.Sleep(50 * time.Millisecond) - c.AllowRead() - } - }() - - go func(i int64) { - rng := rand.New(rand.NewSource(i + seed)) - buf := make([]byte, 1024) - for j := 0; j < 1024; j++ { - if _, err := wc.Read(buf); err != nil { - if atomic.LoadInt32(&flag) != 0 { - // Peaceful; the connection has - // probably been closed while - // idle - return - } - t.Errorf("error reading in conn %d: %v", - i, err) - } - time.Sleep(time.Duration(rng.Intn(100)) * time.Millisecond) - // This one is to make sure the connection - // hasn't closed underneath us - if _, err := wc.Read(buf); err != nil { - t.Errorf("error reading in conn %d: %v", - i, err) - } - MarkIdle(wc) - time.Sleep(time.Duration(rng.Intn(100)) * time.Millisecond) - } - }(int64(i)) - - time.Sleep(time.Duration(i) * time.Millisecond / 2) - } - }() - - if testing.Short() { - time.Sleep(2 * time.Second) - } else { - time.Sleep(10 * time.Second) - } - start := time.Now() - atomic.StoreInt32(&flag, 1) - wl.Close() - wl.Drain() - end := time.Now() - if dt := end.Sub(start); dt > 300*time.Millisecond { - t.Errorf("took %v to drain; expected shorter", dt) - } -} diff --git a/vendor/github.com/zenazn/goji/graceful/listener/shard.go b/vendor/github.com/zenazn/goji/graceful/listener/shard.go deleted file mode 100644 index a9addad..0000000 --- a/vendor/github.com/zenazn/goji/graceful/listener/shard.go +++ /dev/null @@ -1,98 +0,0 @@ -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 deleted file mode 100644 index 94edfe3..0000000 --- a/vendor/github.com/zenazn/goji/graceful/middleware.go +++ /dev/null @@ -1,103 +0,0 @@ -// +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/middleware_test.go b/vendor/github.com/zenazn/goji/graceful/middleware_test.go deleted file mode 100644 index aa4e623..0000000 --- a/vendor/github.com/zenazn/goji/graceful/middleware_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// +build !go1.3 - -package graceful - -import ( - "net/http" - "sync/atomic" - "testing" -) - -type fakeWriter http.Header - -func (f fakeWriter) Header() http.Header { - return http.Header(f) -} -func (f fakeWriter) Write(buf []byte) (int, error) { - return len(buf), nil -} -func (f fakeWriter) WriteHeader(status int) {} - -func testClose(t *testing.T, h http.Handler, expectClose bool) { - m := middleware(h) - r, _ := http.NewRequest("GET", "/", nil) - w := make(fakeWriter) - m.ServeHTTP(w, r) - - c, ok := w["Connection"] - if expectClose { - if !ok || len(c) != 1 || c[0] != "close" { - t.Fatal("Expected 'Connection: close'") - } - } else { - if ok { - t.Fatal("Did not expect Connection header") - } - } -} - -func TestNormal(t *testing.T) { - atomic.StoreInt32(&closing, 0) - h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Write([]byte{}) - }) - testClose(t, h, false) -} - -func TestClose(t *testing.T) { - atomic.StoreInt32(&closing, 0) - h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - atomic.StoreInt32(&closing, 1) - }) - testClose(t, h, true) -} - -func TestCloseWriteHeader(t *testing.T) { - atomic.StoreInt32(&closing, 0) - h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - atomic.StoreInt32(&closing, 1) - w.WriteHeader(200) - }) - testClose(t, h, true) -} - -func TestCloseWrite(t *testing.T) { - atomic.StoreInt32(&closing, 0) - h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - atomic.StoreInt32(&closing, 1) - w.Write([]byte{}) - }) - testClose(t, h, true) -} diff --git a/vendor/github.com/zenazn/goji/graceful/serve.go b/vendor/github.com/zenazn/goji/graceful/serve.go deleted file mode 100644 index edb2a53..0000000 --- a/vendor/github.com/zenazn/goji/graceful/serve.go +++ /dev/null @@ -1,33 +0,0 @@ -// +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 deleted file mode 100644 index 68cac04..0000000 --- a/vendor/github.com/zenazn/goji/graceful/serve13.go +++ /dev/null @@ -1,76 +0,0 @@ -// +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 deleted file mode 100644 index ae9a5fb..0000000 --- a/vendor/github.com/zenazn/goji/graceful/server.go +++ /dev/null @@ -1,108 +0,0 @@ -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 deleted file mode 100644 index 60612b8..0000000 --- a/vendor/github.com/zenazn/goji/graceful/signal.go +++ /dev/null @@ -1,197 +0,0 @@ -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 deleted file mode 100644 index da73a9b..0000000 --- a/vendor/github.com/zenazn/goji/serve.go +++ /dev/null @@ -1,64 +0,0 @@ -// +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 deleted file mode 100644 index 88dc7a8..0000000 --- a/vendor/github.com/zenazn/goji/serve_appengine.go +++ /dev/null @@ -1,23 +0,0 @@ -// +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 deleted file mode 100644 index 795d8e5..0000000 --- a/vendor/github.com/zenazn/goji/web/atomic.go +++ /dev/null @@ -1,18 +0,0 @@ -// +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 deleted file mode 100644 index 027127a..0000000 --- a/vendor/github.com/zenazn/goji/web/atomic_appengine.go +++ /dev/null @@ -1,14 +0,0 @@ -// +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/bench_test.go b/vendor/github.com/zenazn/goji/web/bench_test.go deleted file mode 100644 index fc285db..0000000 --- a/vendor/github.com/zenazn/goji/web/bench_test.go +++ /dev/null @@ -1,166 +0,0 @@ -// +build go1.3 - -package web - -import ( - "crypto/rand" - "encoding/base64" - mrand "math/rand" - "net/http" - "testing" -) - -/* -The core benchmarks here are based on cypriss's mux benchmarks, which can be -found here: -https://github.com/cypriss/golang-mux-benchmark - -They happen to play very well into Goji's router's strengths. -*/ - -type nilRouter struct{} - -var helloWorld = []byte("Hello world!\n") - -func (_ nilRouter) ServeHTTP(w http.ResponseWriter, r *http.Request) { - w.Write(helloWorld) -} - -type nilResponse struct{} - -func (_ nilResponse) Write(buf []byte) (int, error) { - return len(buf), nil -} -func (_ nilResponse) Header() http.Header { - return nil -} -func (_ nilResponse) WriteHeader(code int) { -} - -func trivialMiddleware(h http.Handler) http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - h.ServeHTTP(w, r) - } - return http.HandlerFunc(fn) -} - -var w nilResponse - -func addRoutes(m *Mux, prefix string) { - m.Get(prefix, nilRouter{}) - m.Post(prefix, nilRouter{}) - m.Get(prefix+"/:id", nilRouter{}) - m.Put(prefix+"/:id", nilRouter{}) - m.Delete(prefix+"/:id", nilRouter{}) -} - -func randString() string { - var buf [6]byte - rand.Reader.Read(buf[:]) - return base64.URLEncoding.EncodeToString(buf[:]) -} - -func genPrefixes(n int) []string { - p := make([]string, n) - for i := range p { - p[i] = "/" + randString() - } - return p -} - -func genRequests(prefixes []string) []*http.Request { - rs := make([]*http.Request, 5*len(prefixes)) - for i, prefix := range prefixes { - rs[5*i+0], _ = http.NewRequest("GET", prefix, nil) - rs[5*i+1], _ = http.NewRequest("POST", prefix, nil) - rs[5*i+2], _ = http.NewRequest("GET", prefix+"/foo", nil) - rs[5*i+3], _ = http.NewRequest("PUT", prefix+"/foo", nil) - rs[5*i+4], _ = http.NewRequest("DELETE", prefix+"/foo", nil) - } - return rs -} - -func permuteRequests(reqs []*http.Request) []*http.Request { - out := make([]*http.Request, len(reqs)) - perm := mrand.Perm(len(reqs)) - for i, req := range reqs { - out[perm[i]] = req - } - return out -} - -func benchN(b *testing.B, n int) { - m := New() - prefixes := genPrefixes(n) - for _, prefix := range prefixes { - addRoutes(m, prefix) - } - m.Compile() - reqs := permuteRequests(genRequests(prefixes)) - - b.ResetTimer() - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - i := 0 - for pb.Next() { - i++ - m.ServeHTTP(w, reqs[i%len(reqs)]) - } - }) -} - -func benchM(b *testing.B, n int) { - m := New() - m.Get("/", nilRouter{}) - for i := 0; i < n; i++ { - m.Use(trivialMiddleware) - } - r, _ := http.NewRequest("GET", "/", nil) - m.Compile() - - b.ResetTimer() - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - m.ServeHTTP(w, r) - } - }) -} - -func BenchmarkStatic(b *testing.B) { - m := New() - m.Get("/", nilRouter{}) - r, _ := http.NewRequest("GET", "/", nil) - m.Compile() - - b.ResetTimer() - b.ReportAllocs() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - m.ServeHTTP(w, r) - } - }) -} - -func BenchmarkRoute5(b *testing.B) { - benchN(b, 1) -} -func BenchmarkRoute50(b *testing.B) { - benchN(b, 10) -} -func BenchmarkRoute500(b *testing.B) { - benchN(b, 100) -} -func BenchmarkRoute5000(b *testing.B) { - benchN(b, 1000) -} - -func BenchmarkMiddleware1(b *testing.B) { - benchM(b, 1) -} -func BenchmarkMiddleware10(b *testing.B) { - benchM(b, 10) -} -func BenchmarkMiddleware100(b *testing.B) { - benchM(b, 100) -} diff --git a/vendor/github.com/zenazn/goji/web/bytecode_compiler.go b/vendor/github.com/zenazn/goji/web/bytecode_compiler.go deleted file mode 100644 index b6f52b1..0000000 --- a/vendor/github.com/zenazn/goji/web/bytecode_compiler.go +++ /dev/null @@ -1,265 +0,0 @@ -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 deleted file mode 100644 index c32b16a..0000000 --- a/vendor/github.com/zenazn/goji/web/bytecode_runner.go +++ /dev/null @@ -1,83 +0,0 @@ -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 deleted file mode 100644 index 6c53c74..0000000 --- a/vendor/github.com/zenazn/goji/web/chanpool.go +++ /dev/null @@ -1,31 +0,0 @@ -// +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 deleted file mode 100644 index 59f8764..0000000 --- a/vendor/github.com/zenazn/goji/web/cpool.go +++ /dev/null @@ -1,23 +0,0 @@ -// +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/example_test.go b/vendor/github.com/zenazn/goji/web/example_test.go deleted file mode 100644 index 9dc8de2..0000000 --- a/vendor/github.com/zenazn/goji/web/example_test.go +++ /dev/null @@ -1,69 +0,0 @@ -package web_test - -import ( - "fmt" - "log" - "net/http" - "regexp" - - "github.com/zenazn/goji/web" - "github.com/zenazn/goji/web/middleware" -) - -func Example() { - m := web.New() - - // Use your favorite HTTP verbs and the interfaces you know and love - // from net/http: - m.Get("/hello", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Why hello there!\n") - }) - m.Post("/login", func(w http.ResponseWriter, r *http.Request) { - if r.FormValue("password") != "god" { - http.Error(w, "Hack the planet!", 401) - } - }) - - // Handlers can optionally take a context parameter, which contains - // (among other things) a set of bound parameters. - hello := func(c web.C, w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, %s!\n", c.URLParams["name"]) - } - - // Bind parameters using pattern strings... - m.Get("/hello/:name", hello) - - // ...or use regular expressions if you need additional power. - bonjour := regexp.MustCompile(`^/bonjour/(?P[A-Za-z]+)$`) - m.Get(bonjour, hello) - - // Middleware are a great abstraction for performing logic on every - // request. Some middleware use the Goji context object to set - // request-scoped variables. - logger := func(h http.Handler) http.Handler { - wrap := func(w http.ResponseWriter, r *http.Request) { - log.Println("Before request") - h.ServeHTTP(w, r) - log.Println("After request") - } - return http.HandlerFunc(wrap) - } - auth := func(c *web.C, h http.Handler) http.Handler { - wrap := func(w http.ResponseWriter, r *http.Request) { - if cookie, err := r.Cookie("user"); err == nil { - c.Env["user"] = cookie.Value - } - h.ServeHTTP(w, r) - } - return http.HandlerFunc(wrap) - } - - // A Middleware stack is a flexible way to assemble the common - // components of your application, like request loggers and - // authentication. There is an ecosystem of open-source middleware for - // Goji, so there's a chance someone has already written the middleware - // you are looking for! - m.Use(middleware.EnvInit) - m.Use(logger) - m.Use(auth) -} diff --git a/vendor/github.com/zenazn/goji/web/func_equal.go b/vendor/github.com/zenazn/goji/web/func_equal.go deleted file mode 100644 index 9c8f7cb..0000000 --- a/vendor/github.com/zenazn/goji/web/func_equal.go +++ /dev/null @@ -1,32 +0,0 @@ -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/func_equal_test.go b/vendor/github.com/zenazn/goji/web/func_equal_test.go deleted file mode 100644 index 9080a5a..0000000 --- a/vendor/github.com/zenazn/goji/web/func_equal_test.go +++ /dev/null @@ -1,84 +0,0 @@ -package web - -import ( - "testing" -) - -// To tell you the truth, I'm not actually sure how many of these cases are -// needed. Presumably someone with more patience than I could comb through -// http://golang.org/s/go11func and figure out what all the different cases I -// ought to test are, but I think this test includes all the cases I care about -// and is at least reasonably thorough. - -func a() string { - return "A" -} -func b() string { - return "B" -} -func mkFn(s string) func() string { - return func() string { - return s - } -} - -var c = mkFn("C") -var d = mkFn("D") -var e = a -var f = c -var g = mkFn("D") - -type Type string - -func (t *Type) String() string { - return string(*t) -} - -var t1 = Type("hi") -var t2 = Type("bye") -var t1f = t1.String -var t2f = t2.String - -var funcEqualTests = []struct { - a, b func() string - result bool -}{ - {a, a, true}, - {a, b, false}, - {b, b, true}, - {a, c, false}, - {c, c, true}, - {c, d, false}, - {a, e, true}, - {a, f, false}, - {c, f, true}, - {e, f, false}, - {d, g, false}, - {t1f, t1f, true}, - {t1f, t2f, false}, -} - -func TestFuncEqual(t *testing.T) { - t.Parallel() - - for _, test := range funcEqualTests { - r := funcEqual(test.a, test.b) - if r != test.result { - t.Errorf("funcEqual(%v, %v) should have been %v", - test.a, test.b, test.result) - } - } - h := mkFn("H") - i := h - j := mkFn("H") - k := a - if !funcEqual(h, i) { - t.Errorf("h and i should have been equal") - } - if funcEqual(h, j) { - t.Errorf("h and j should not have been equal") - } - if !funcEqual(a, k) { - t.Errorf("a and k should have been equal") - } -} diff --git a/vendor/github.com/zenazn/goji/web/handler.go b/vendor/github.com/zenazn/goji/web/handler.go deleted file mode 100644 index 746c9f0..0000000 --- a/vendor/github.com/zenazn/goji/web/handler.go +++ /dev/null @@ -1,42 +0,0 @@ -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 deleted file mode 100644 index 1a44144..0000000 --- a/vendor/github.com/zenazn/goji/web/match.go +++ /dev/null @@ -1,66 +0,0 @@ -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/match_test.go b/vendor/github.com/zenazn/goji/web/match_test.go deleted file mode 100644 index aefff04..0000000 --- a/vendor/github.com/zenazn/goji/web/match_test.go +++ /dev/null @@ -1,50 +0,0 @@ -package web - -import ( - "net/http" - "regexp" - "testing" -) - -var rawPatterns = []PatternType{ - "/hello/:name", - regexp.MustCompile("^/hello/(?P[^/]+)$"), - testPattern{}, -} - -func TestRawPattern(t *testing.T) { - t.Parallel() - - for _, p := range rawPatterns { - m := Match{Pattern: ParsePattern(p)} - if rp := m.RawPattern(); rp != p { - t.Errorf("got %#v, expected %#v", rp, p) - } - } -} - -type httpHandlerOnly struct{} - -func (httpHandlerOnly) ServeHTTP(w http.ResponseWriter, r *http.Request) {} - -type handlerOnly struct{} - -func (handlerOnly) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) {} - -var rawHandlers = []HandlerType{ - func(w http.ResponseWriter, r *http.Request) {}, - func(c C, w http.ResponseWriter, r *http.Request) {}, - httpHandlerOnly{}, - handlerOnly{}, -} - -func TestRawHandler(t *testing.T) { - t.Parallel() - - for _, h := range rawHandlers { - m := Match{Handler: parseHandler(h)} - if rh := m.RawHandler(); !funcEqual(rh, h) { - t.Errorf("got %#v, expected %#v", rh, h) - } - } -} diff --git a/vendor/github.com/zenazn/goji/web/middleware.go b/vendor/github.com/zenazn/goji/web/middleware.go deleted file mode 100644 index 7ec545d..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware.go +++ /dev/null @@ -1,154 +0,0 @@ -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 deleted file mode 100644 index ae3b683..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/envinit.go +++ /dev/null @@ -1,27 +0,0 @@ -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 deleted file mode 100644 index 8bbcac8..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/logger.go +++ /dev/null @@ -1,92 +0,0 @@ -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 deleted file mode 100644 index 23cfde2..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/middleware.go +++ /dev/null @@ -1,4 +0,0 @@ -/* -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 deleted file mode 100644 index ae3d260..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/nocache.go +++ /dev/null @@ -1,55 +0,0 @@ -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/nocache_test.go b/vendor/github.com/zenazn/goji/web/middleware/nocache_test.go deleted file mode 100644 index 1fb71f6..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/nocache_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package middleware - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/zenazn/goji/web" -) - -func TestNoCache(t *testing.T) { - - rr := httptest.NewRecorder() - s := web.New() - - s.Use(NoCache) - r, err := http.NewRequest("GET", "/", nil) - if err != nil { - t.Fatal(err) - } - - s.ServeHTTP(rr, r) - - for k, v := range noCacheHeaders { - if rr.HeaderMap[k][0] != v { - t.Errorf("%s header not set by middleware.", k) - } - } -} diff --git a/vendor/github.com/zenazn/goji/web/middleware/options.go b/vendor/github.com/zenazn/goji/web/middleware/options.go deleted file mode 100644 index 4bdce5f..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/options.go +++ /dev/null @@ -1,97 +0,0 @@ -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/options_test.go b/vendor/github.com/zenazn/goji/web/middleware/options_test.go deleted file mode 100644 index e962145..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/options_test.go +++ /dev/null @@ -1,112 +0,0 @@ -package middleware - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/zenazn/goji/web" -) - -func testOptions(r *http.Request, f func(*web.C, http.ResponseWriter, *http.Request)) *httptest.ResponseRecorder { - var c web.C - - h := func(w http.ResponseWriter, r *http.Request) { - f(&c, w, r) - } - m := AutomaticOptions(&c, http.HandlerFunc(h)) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - - return w -} - -var optionsTestEnv = map[interface{}]interface{}{ - web.ValidMethodsKey: []string{ - "hello", - "world", - }, -} - -func TestAutomaticOptions(t *testing.T) { - t.Parallel() - - // Shouldn't interfere with normal requests - r, _ := http.NewRequest("GET", "/", nil) - rr := testOptions(r, - func(c *web.C, w http.ResponseWriter, r *http.Request) { - w.Write([]byte{'h', 'i'}) - }, - ) - if rr.Code != http.StatusOK { - t.Errorf("status is %d, not 200", rr.Code) - } - if rr.Body.String() != "hi" { - t.Errorf("body was %q, should be %q", rr.Body.String(), "hi") - } - allow := rr.HeaderMap.Get("Allow") - if allow != "" { - t.Errorf("Allow header was set to %q, should be empty", allow) - } - - // If we respond non-404 to an OPTIONS request, also don't interfere - r, _ = http.NewRequest("OPTIONS", "/", nil) - rr = testOptions(r, - func(c *web.C, w http.ResponseWriter, r *http.Request) { - c.Env = optionsTestEnv - w.Write([]byte{'h', 'i'}) - }, - ) - if rr.Code != http.StatusOK { - t.Errorf("status is %d, not 200", rr.Code) - } - if rr.Body.String() != "hi" { - t.Errorf("body was %q, should be %q", rr.Body.String(), "hi") - } - allow = rr.HeaderMap.Get("Allow") - if allow != "" { - t.Errorf("Allow header was set to %q, should be empty", allow) - } - - // Provide options if we 404. Make sure we nom the output bytes - r, _ = http.NewRequest("OPTIONS", "/", nil) - rr = testOptions(r, - func(c *web.C, w http.ResponseWriter, r *http.Request) { - c.Env = optionsTestEnv - w.WriteHeader(http.StatusNotFound) - w.Write([]byte{'h', 'i'}) - }, - ) - if rr.Code != http.StatusOK { - t.Errorf("status is %d, not 200", rr.Code) - } - if rr.Body.Len() != 0 { - t.Errorf("body was %q, should be empty", rr.Body.String()) - } - allow = rr.HeaderMap.Get("Allow") - correctHeaders := "hello, world, OPTIONS" - if allow != "hello, world, OPTIONS" { - t.Errorf("Allow header should be %q, was %q", correctHeaders, - allow) - } - - // If we somehow 404 without giving a list of valid options, don't do - // anything - r, _ = http.NewRequest("OPTIONS", "/", nil) - rr = testOptions(r, - func(c *web.C, w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusNotFound) - w.Write([]byte{'h', 'i'}) - }, - ) - if rr.Code != http.StatusNotFound { - t.Errorf("status is %d, not 404", rr.Code) - } - if rr.Body.String() != "hi" { - t.Errorf("body was %q, should be %q", rr.Body.String(), "hi") - } - allow = rr.HeaderMap.Get("Allow") - if allow != "" { - t.Errorf("Allow header was set to %q, should be empty", allow) - } -} diff --git a/vendor/github.com/zenazn/goji/web/middleware/realip.go b/vendor/github.com/zenazn/goji/web/middleware/realip.go deleted file mode 100644 index ae5599f..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/realip.go +++ /dev/null @@ -1,51 +0,0 @@ -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 deleted file mode 100644 index 43ad648..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/recoverer.go +++ /dev/null @@ -1,44 +0,0 @@ -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 deleted file mode 100644 index 834d8e3..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/request_id.go +++ /dev/null @@ -1,88 +0,0 @@ -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 deleted file mode 100644 index e5b0921..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/subrouter.go +++ /dev/null @@ -1,65 +0,0 @@ -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/subrouter_test.go b/vendor/github.com/zenazn/goji/web/middleware/subrouter_test.go deleted file mode 100644 index c46c27e..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/subrouter_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package middleware - -import ( - "net/http" - "net/http/httptest" - "testing" - - "github.com/zenazn/goji/web" -) - -func TestSubRouterMatch(t *testing.T) { - m := web.New() - m.Use(m.Router) - - m2 := web.New() - m2.Use(SubRouter) - m2.Get("/bar", func(w http.ResponseWriter, r *http.Request) {}) - - m.Get("/foo/*", m2) - - r, err := http.NewRequest("GET", "/foo/bar", nil) - if err != nil { - t.Fatal(err) - } - - // This function will recurse forever if SubRouter + Match didn't work. - m.ServeHTTP(httptest.NewRecorder(), r) -} diff --git a/vendor/github.com/zenazn/goji/web/middleware/terminal.go b/vendor/github.com/zenazn/goji/web/middleware/terminal.go deleted file mode 100644 index db02917..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/terminal.go +++ /dev/null @@ -1,60 +0,0 @@ -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 deleted file mode 100644 index 36c8820..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/urlquery.go +++ /dev/null @@ -1,24 +0,0 @@ -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/middleware/urlquery_test.go b/vendor/github.com/zenazn/goji/web/middleware/urlquery_test.go deleted file mode 100644 index d9b7833..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware/urlquery_test.go +++ /dev/null @@ -1,53 +0,0 @@ -package middleware - -import ( - "net/http" - "net/http/httptest" - "net/url" - "reflect" - "testing" - - "github.com/zenazn/goji/web" -) - -func testURLQuery(r *http.Request, f func(*web.C, http.ResponseWriter, *http.Request)) *httptest.ResponseRecorder { - var c web.C - - h := func(w http.ResponseWriter, r *http.Request) { - f(&c, w, r) - } - m := URLQuery(&c, http.HandlerFunc(h)) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - - return w -} - -func TestURLQuery(t *testing.T) { - type testcase struct { - url string - expectedParams url.Values - } - - // we're not testing url.Query() here, but rather that the results of the query - // appear in the context - testcases := []testcase{ - testcase{"/", url.Values{}}, - testcase{"/?a=1&b=2&a=3", url.Values{"a": []string{"1", "3"}, "b": []string{"2"}}}, - testcase{"/?x=1&y=2&z=3#freddyishere", url.Values{"x": []string{"1"}, "y": []string{"2"}, "z": []string{"3"}}}, - } - - for _, tc := range testcases { - r, _ := http.NewRequest("GET", tc.url, nil) - testURLQuery(r, - func(c *web.C, w http.ResponseWriter, r *http.Request) { - params := c.Env[URLQueryKey].(url.Values) - if !reflect.DeepEqual(params, tc.expectedParams) { - t.Errorf("GET %s, URLQuery middleware found %v, should be %v", tc.url, params, tc.expectedParams) - } - - w.Write([]byte{'h', 'i'}) - }, - ) - } -} diff --git a/vendor/github.com/zenazn/goji/web/middleware12_test.go b/vendor/github.com/zenazn/goji/web/middleware12_test.go deleted file mode 100644 index fe5ca9b..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware12_test.go +++ /dev/null @@ -1,52 +0,0 @@ -// +build !go1.3 - -package web - -import "testing" - -// These tests were pretty sketchtacular to start with, but they aren't even -// guaranteed to pass with Go 1.3's sync.Pool. Let's keep them here for now; if -// they start spuriously failing later we can delete them outright. - -func TestCaching(t *testing.T) { - ch := make(chan string) - st := makeStack(ch) - cs1 := st.alloc() - cs2 := st.alloc() - if cs1 == cs2 { - t.Fatal("cs1 and cs2 are the same") - } - st.release(cs2) - cs3 := st.alloc() - if cs2 != cs3 { - t.Fatalf("Expected cs2 to equal cs3") - } - st.release(cs1) - st.release(cs3) - cs4 := st.alloc() - cs5 := st.alloc() - if cs4 != cs1 { - t.Fatal("Expected cs4 to equal cs1") - } - if cs5 != cs3 { - t.Fatal("Expected cs5 to equal cs3") - } -} - -func TestInvalidation(t *testing.T) { - ch := make(chan string) - st := makeStack(ch) - cs1 := st.alloc() - cs2 := st.alloc() - st.release(cs1) - st.invalidate() - cs3 := st.alloc() - if cs3 == cs1 { - t.Fatal("Expected cs3 to be fresh, instead got cs1") - } - st.release(cs2) - cs4 := st.alloc() - if cs4 == cs2 { - t.Fatal("Expected cs4 to be fresh, instead got cs2") - } -} diff --git a/vendor/github.com/zenazn/goji/web/middleware_test.go b/vendor/github.com/zenazn/goji/web/middleware_test.go deleted file mode 100644 index 678ccaa..0000000 --- a/vendor/github.com/zenazn/goji/web/middleware_test.go +++ /dev/null @@ -1,204 +0,0 @@ -package web - -import ( - "net/http" - "net/http/httptest" - "testing" - "time" -) - -type iRouter func(*C, http.ResponseWriter, *http.Request) - -func (i iRouter) route(c *C, w http.ResponseWriter, r *http.Request) { - i(c, w, r) -} - -func makeStack(ch chan string) *mStack { - router := func(c *C, w http.ResponseWriter, r *http.Request) { - ch <- "router" - } - return &mStack{ - stack: make([]mLayer, 0), - pool: makeCPool(), - router: iRouter(router), - } -} - -func chanWare(ch chan string, s string) func(http.Handler) http.Handler { - return func(h http.Handler) http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - ch <- s - h.ServeHTTP(w, r) - } - return http.HandlerFunc(fn) - } -} - -func simpleRequest(ch chan string, st *mStack) { - defer func() { - ch <- "end" - }() - r, _ := http.NewRequest("GET", "/", nil) - w := httptest.NewRecorder() - cs := st.alloc() - defer st.release(cs) - - cs.ServeHTTP(w, r) -} - -func assertOrder(t *testing.T, ch chan string, strings ...string) { - for i, s := range strings { - var v string - select { - case v = <-ch: - case <-time.After(5 * time.Millisecond): - t.Fatalf("Expected %q as %d'th value, but timed out", s, - i+1) - } - if s != v { - t.Errorf("%d'th value was %q, expected %q", i+1, v, s) - } - } -} - -func TestSimple(t *testing.T) { - t.Parallel() - - ch := make(chan string) - st := makeStack(ch) - st.Use(chanWare(ch, "one")) - st.Use(chanWare(ch, "two")) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "two", "router", "end") -} - -func TestTypes(t *testing.T) { - t.Parallel() - - ch := make(chan string) - st := makeStack(ch) - st.Use(func(h http.Handler) http.Handler { - return h - }) - st.Use(func(c *C, h http.Handler) http.Handler { - return h - }) -} - -func TestAddMore(t *testing.T) { - t.Parallel() - - ch := make(chan string) - st := makeStack(ch) - st.Use(chanWare(ch, "one")) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "router", "end") - - st.Use(chanWare(ch, "two")) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "two", "router", "end") - - st.Use(chanWare(ch, "three")) - st.Use(chanWare(ch, "four")) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "two", "three", "four", "router", "end") -} - -func TestInsert(t *testing.T) { - t.Parallel() - - ch := make(chan string) - st := makeStack(ch) - one := chanWare(ch, "one") - two := chanWare(ch, "two") - st.Use(one) - st.Use(two) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "two", "router", "end") - - err := st.Insert(chanWare(ch, "sloth"), chanWare(ch, "squirrel")) - if err == nil { - t.Error("Expected error when referencing unknown middleware") - } - - st.Insert(chanWare(ch, "middle"), two) - err = st.Insert(chanWare(ch, "start"), one) - if err != nil { - t.Fatal(err) - } - go simpleRequest(ch, st) - assertOrder(t, ch, "start", "one", "middle", "two", "router", "end") -} - -func TestAbandon(t *testing.T) { - t.Parallel() - - ch := make(chan string) - st := makeStack(ch) - one := chanWare(ch, "one") - two := chanWare(ch, "two") - three := chanWare(ch, "three") - st.Use(one) - st.Use(two) - st.Use(three) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "two", "three", "router", "end") - - st.Abandon(two) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "three", "router", "end") - - err := st.Abandon(chanWare(ch, "panda")) - if err == nil { - t.Error("Expected error when deleting unknown middleware") - } - - st.Abandon(one) - st.Abandon(three) - go simpleRequest(ch, st) - assertOrder(t, ch, "router", "end") - - st.Use(one) - go simpleRequest(ch, st) - assertOrder(t, ch, "one", "router", "end") -} - -func TestContext(t *testing.T) { - router := func(c *C, w http.ResponseWriter, r *http.Request) { - if c.Env["reqID"].(int) != 2 { - t.Error("Request id was not 2 :(") - } - } - st := mStack{ - stack: make([]mLayer, 0), - pool: makeCPool(), - router: iRouter(router), - } - st.Use(func(c *C, h http.Handler) http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - if c.Env != nil || c.URLParams != nil { - t.Error("Expected a clean context") - } - c.Env = make(map[interface{}]interface{}) - c.Env["reqID"] = 1 - - h.ServeHTTP(w, r) - } - return http.HandlerFunc(fn) - }) - - st.Use(func(c *C, h http.Handler) http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - if c.Env == nil { - t.Error("Expected env from last middleware") - } - c.Env["reqID"] = c.Env["reqID"].(int) + 1 - - h.ServeHTTP(w, r) - } - return http.HandlerFunc(fn) - }) - ch := make(chan string) - go simpleRequest(ch, &st) - assertOrder(t, ch, "end") -} diff --git a/vendor/github.com/zenazn/goji/web/mutil/mutil.go b/vendor/github.com/zenazn/goji/web/mutil/mutil.go deleted file mode 100644 index e8d5b28..0000000 --- a/vendor/github.com/zenazn/goji/web/mutil/mutil.go +++ /dev/null @@ -1,3 +0,0 @@ -// 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 deleted file mode 100644 index 9f6d776..0000000 --- a/vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go +++ /dev/null @@ -1,139 +0,0 @@ -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 deleted file mode 100644 index 18b9991..0000000 --- a/vendor/github.com/zenazn/goji/web/mux.go +++ /dev/null @@ -1,213 +0,0 @@ -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/mux_test.go b/vendor/github.com/zenazn/goji/web/mux_test.go deleted file mode 100644 index f461452..0000000 --- a/vendor/github.com/zenazn/goji/web/mux_test.go +++ /dev/null @@ -1,45 +0,0 @@ -package web - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -// Sanity check types -var _ http.Handler = &Mux{} -var _ Handler = &Mux{} - -// There's... really not a lot to do here. - -func TestIfItWorks(t *testing.T) { - t.Parallel() - - m := New() - ch := make(chan string, 1) - - m.Get("/hello/:name", func(c C, w http.ResponseWriter, r *http.Request) { - greeting := "Hello " - if c.Env != nil { - if g, ok := c.Env["greeting"]; ok { - greeting = g.(string) - } - } - ch <- greeting + c.URLParams["name"] - }) - - r, _ := http.NewRequest("GET", "/hello/carl", nil) - m.ServeHTTP(httptest.NewRecorder(), r) - out := <-ch - if out != "Hello carl" { - t.Errorf(`Unexpected response %q, expected "Hello carl"`, out) - } - - r, _ = http.NewRequest("GET", "/hello/bob", nil) - env := map[interface{}]interface{}{"greeting": "Yo "} - m.ServeHTTPC(C{Env: env}, httptest.NewRecorder(), r) - out = <-ch - if out != "Yo bob" { - t.Errorf(`Unexpected response %q, expected "Yo bob"`, out) - } -} diff --git a/vendor/github.com/zenazn/goji/web/pattern.go b/vendor/github.com/zenazn/goji/web/pattern.go deleted file mode 100644 index 9f9fc85..0000000 --- a/vendor/github.com/zenazn/goji/web/pattern.go +++ /dev/null @@ -1,58 +0,0 @@ -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/pattern_test.go b/vendor/github.com/zenazn/goji/web/pattern_test.go deleted file mode 100644 index 8e8af29..0000000 --- a/vendor/github.com/zenazn/goji/web/pattern_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package web - -import ( - "net/http" - "reflect" - "regexp" - "testing" -) - -func pt(url string, match bool, params map[string]string) patternTest { - req, err := http.NewRequest("GET", url, nil) - if err != nil { - panic(err) - } - - return patternTest{ - r: req, - match: match, - c: &C{}, - cout: &C{URLParams: params}, - } -} - -type patternTest struct { - r *http.Request - match bool - c *C - cout *C -} - -var patternTests = []struct { - pat Pattern - prefix string - tests []patternTest -}{ - // Regexp tests - {parseRegexpPattern(regexp.MustCompile("^/hello$")), - "/hello", []patternTest{ - pt("/hello", true, nil), - pt("/hell", false, nil), - pt("/hello/", false, nil), - pt("/hello/world", false, nil), - pt("/world", false, nil), - }}, - {parseRegexpPattern(regexp.MustCompile("^/hello/(?P[a-z]+)$")), - "/hello/", []patternTest{ - pt("/hello/world", true, map[string]string{ - "name": "world", - }), - pt("/hello/", false, nil), - pt("/hello/my/love", false, nil), - }}, - {parseRegexpPattern(regexp.MustCompile(`^/a(?P\d+)/b(?P\d+)/?$`)), - "/a", []patternTest{ - pt("/a1/b2", true, map[string]string{ - "a": "1", - "b": "2", - }), - pt("/a9001/b007/", true, map[string]string{ - "a": "9001", - "b": "007", - }), - pt("/a/b", false, nil), - pt("/a", false, nil), - pt("/squirrel", false, nil), - }}, - {parseRegexpPattern(regexp.MustCompile(`^/hello/([a-z]+)$`)), - "/hello/", []patternTest{ - pt("/hello/world", true, map[string]string{ - "$1": "world", - }), - pt("/hello/", false, nil), - }}, - {parseRegexpPattern(regexp.MustCompile("/hello")), - "/hello", []patternTest{ - pt("/hello", true, nil), - pt("/hell", false, nil), - pt("/hello/", true, nil), - pt("/hello/world", true, nil), - pt("/world/hello", false, nil), - }}, - - // String pattern tests - {parseStringPattern("/hello"), - "/hello", []patternTest{ - pt("/hello", true, nil), - pt("/hell", false, nil), - pt("/hello/", false, nil), - pt("/hello/world", false, nil), - }}, - {parseStringPattern("/hello/:name"), - "/hello/", []patternTest{ - pt("/hello/world", true, map[string]string{ - "name": "world", - }), - pt("/hello/my.world;wow", true, map[string]string{ - "name": "my.world;wow", - }), - pt("/hell", false, nil), - pt("/hello/", false, nil), - pt("/hello/my/love", false, nil), - }}, - {parseStringPattern("/a/:a/b/:b"), - "/a/", []patternTest{ - pt("/a/1/b/2", true, map[string]string{ - "a": "1", - "b": "2", - }), - pt("/a", false, nil), - pt("/a//b/", false, nil), - pt("/a/1/b/2/3", false, nil), - }}, - {parseStringPattern("/a/:b.:c"), - "/a/", []patternTest{ - pt("/a/cat.gif", true, map[string]string{ - "b": "cat", - "c": "gif", - }), - pt("/a/cat.tar.gz", true, map[string]string{ - "b": "cat", - "c": "tar.gz", - }), - pt("/a", false, nil), - pt("/a/cat", false, nil), - pt("/a/cat/gif", false, nil), - pt("/a/cat.", false, nil), - pt("/a/cat/dog.gif", false, nil), - }}, - - // String prefix tests - {parseStringPattern("/user/:user/*"), - "/user/", []patternTest{ - pt("/user/bob/", true, map[string]string{ - "user": "bob", - "*": "/", - }), - pt("/user/bob/friends/123", true, map[string]string{ - "user": "bob", - "*": "/friends/123", - }), - pt("/user/bob", false, nil), - pt("/user/", false, nil), - pt("/user//", false, nil), - }}, - {parseStringPattern("/user/:user/friends/*"), - "/user/", []patternTest{ - pt("/user/bob/friends/", true, map[string]string{ - "user": "bob", - "*": "/", - }), - pt("/user/bob/friends/123", true, map[string]string{ - "user": "bob", - "*": "/123", - }), - pt("/user/bob/enemies", false, nil), - }}, -} - -func TestPatterns(t *testing.T) { - t.Parallel() - - for _, pt := range patternTests { - p := pt.pat.Prefix() - if p != pt.prefix { - t.Errorf("Expected prefix %q for %v, got %q", pt.prefix, - pt.pat, p) - } else { - for _, test := range pt.tests { - runTest(t, pt.pat, test) - } - } - } -} - -func runTest(t *testing.T, p Pattern, test patternTest) { - result := p.Match(test.r, test.c) - if result != test.match { - t.Errorf("Expected match(%v, %#v) to return %v", p, - test.r.URL.Path, test.match) - return - } - p.Run(test.r, test.c) - - if !reflect.DeepEqual(test.c, test.cout) { - t.Errorf("Expected a context of %v, instead got %v", test.cout, - test.c) - } -} diff --git a/vendor/github.com/zenazn/goji/web/regexp_pattern.go b/vendor/github.com/zenazn/goji/web/regexp_pattern.go deleted file mode 100644 index 95e7e09..0000000 --- a/vendor/github.com/zenazn/goji/web/regexp_pattern.go +++ /dev/null @@ -1,149 +0,0 @@ -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 deleted file mode 100644 index 1fbc41f..0000000 --- a/vendor/github.com/zenazn/goji/web/router.go +++ /dev/null @@ -1,154 +0,0 @@ -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/router_middleware_test.go b/vendor/github.com/zenazn/goji/web/router_middleware_test.go deleted file mode 100644 index 05dc2fa..0000000 --- a/vendor/github.com/zenazn/goji/web/router_middleware_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package web - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -func TestRouterMiddleware(t *testing.T) { - t.Parallel() - - m := New() - ch := make(chan string, 1) - m.Get("/a", chHandler(ch, "a")) - m.Get("/b", chHandler(ch, "b")) - m.Use(m.Router) - m.Use(func(c *C, h http.Handler) http.Handler { - fn := func(w http.ResponseWriter, r *http.Request) { - m := GetMatch(*c) - if rp := m.RawPattern(); rp != "/a" { - t.Fatalf("RawPattern was not /a: %v", rp) - } - r.URL.Path = "/b" - h.ServeHTTP(w, r) - } - return http.HandlerFunc(fn) - }) - - r, _ := http.NewRequest("GET", "/a", nil) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - if v := <-ch; v != "a" { - t.Errorf("Routing was not frozen! %s", v) - } -} diff --git a/vendor/github.com/zenazn/goji/web/router_test.go b/vendor/github.com/zenazn/goji/web/router_test.go deleted file mode 100644 index 1d2c27e..0000000 --- a/vendor/github.com/zenazn/goji/web/router_test.go +++ /dev/null @@ -1,326 +0,0 @@ -package web - -import ( - "net/http" - "net/http/httptest" - "reflect" - "regexp" - "testing" - "time" -) - -// These tests can probably be DRY'd up a bunch - -func chHandler(ch chan string, s string) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ch <- s - }) -} - -var methods = []string{"CONNECT", "DELETE", "GET", "HEAD", "OPTIONS", "PATCH", - "POST", "PUT", "TRACE", "OTHER"} - -func TestMethods(t *testing.T) { - t.Parallel() - m := New() - ch := make(chan string, 1) - - m.Connect("/", chHandler(ch, "CONNECT")) - m.Delete("/", chHandler(ch, "DELETE")) - m.Head("/", chHandler(ch, "HEAD")) - m.Get("/", chHandler(ch, "GET")) - m.Options("/", chHandler(ch, "OPTIONS")) - m.Patch("/", chHandler(ch, "PATCH")) - m.Post("/", chHandler(ch, "POST")) - m.Put("/", chHandler(ch, "PUT")) - m.Trace("/", chHandler(ch, "TRACE")) - m.Handle("/", chHandler(ch, "OTHER")) - - for _, method := range methods { - r, _ := http.NewRequest(method, "/", nil) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - select { - case val := <-ch: - if val != method { - t.Errorf("Got %q, expected %q", val, method) - } - case <-time.After(5 * time.Millisecond): - t.Errorf("Timeout waiting for method %q", method) - } - } -} - -type testPattern struct{} - -func (t testPattern) Prefix() string { - return "" -} - -func (t testPattern) Match(r *http.Request, c *C) bool { - return true -} -func (t testPattern) Run(r *http.Request, c *C) { -} - -var _ Pattern = testPattern{} - -func TestPatternTypes(t *testing.T) { - t.Parallel() - m := New() - - m.Get("/hello/carl", http.NotFound) - m.Get("/hello/:name", http.NotFound) - m.Get(regexp.MustCompile(`^/hello/(?P.+)$`), http.NotFound) - m.Get(testPattern{}, http.NotFound) -} - -type testHandler chan string - -func (t testHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - t <- "http" -} -func (t testHandler) ServeHTTPC(c C, w http.ResponseWriter, r *http.Request) { - t <- "httpc" -} - -var testHandlerTable = map[string]string{ - "/a": "http fn", - "/b": "http handler", - "/c": "web fn", - "/d": "web handler", - "/e": "httpc", -} - -func TestHandlerTypes(t *testing.T) { - t.Parallel() - m := New() - ch := make(chan string, 1) - - m.Get("/a", func(w http.ResponseWriter, r *http.Request) { - ch <- "http fn" - }) - m.Get("/b", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ch <- "http handler" - })) - m.Get("/c", func(c C, w http.ResponseWriter, r *http.Request) { - ch <- "web fn" - }) - m.Get("/d", HandlerFunc(func(c C, w http.ResponseWriter, r *http.Request) { - ch <- "web handler" - })) - m.Get("/e", testHandler(ch)) - - for route, response := range testHandlerTable { - r, _ := http.NewRequest("GET", route, nil) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - select { - case resp := <-ch: - if resp != response { - t.Errorf("Got %q, expected %q", resp, response) - } - case <-time.After(5 * time.Millisecond): - t.Errorf("Timeout waiting for path %q", route) - } - - } -} - -// The idea behind this test is to comprehensively test if routes are being -// applied in the right order. We define a special pattern type that always -// matches so long as it's greater than or equal to the global test index. By -// incrementing this index, we can invalidate all routes up to some point, and -// therefore test the routing guarantee that Goji provides: for any path P, if -// both A and B match P, and if A was inserted before B, then Goji will route to -// A before it routes to B. -var rsRoutes = []string{ - "/", - "/a", - "/a", - "/b", - "/ab", - "/", - "/ba", - "/b", - "/a", -} - -var rsTests = []struct { - key string - results []int -}{ - {"/", []int{0, 5, 5, 5, 5, 5, -1, -1, -1, -1}}, - {"/a", []int{0, 1, 2, 5, 5, 5, 8, 8, 8, -1}}, - {"/b", []int{0, 3, 3, 3, 5, 5, 7, 7, -1, -1}}, - {"/ab", []int{0, 1, 2, 4, 4, 5, 8, 8, 8, -1}}, - {"/ba", []int{0, 3, 3, 3, 5, 5, 6, 7, -1, -1}}, - {"/c", []int{0, 5, 5, 5, 5, 5, -1, -1, -1, -1}}, - {"nope", []int{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1}}, -} - -type rsPattern struct { - i int - counter *int - prefix string - ichan chan int -} - -func (rs rsPattern) Prefix() string { - return rs.prefix -} -func (rs rsPattern) Match(_ *http.Request, _ *C) bool { - return rs.i >= *rs.counter -} -func (rs rsPattern) Run(_ *http.Request, _ *C) { -} - -func (rs rsPattern) ServeHTTP(_ http.ResponseWriter, _ *http.Request) { - rs.ichan <- rs.i -} - -var _ Pattern = rsPattern{} -var _ http.Handler = rsPattern{} - -func TestRouteSelection(t *testing.T) { - t.Parallel() - m := New() - counter := 0 - ichan := make(chan int, 1) - m.NotFound(func(w http.ResponseWriter, r *http.Request) { - ichan <- -1 - }) - - for i, s := range rsRoutes { - pat := rsPattern{ - i: i, - counter: &counter, - prefix: s, - ichan: ichan, - } - m.Get(pat, pat) - } - - for _, test := range rsTests { - var n int - for counter, n = range test.results { - r, _ := http.NewRequest("GET", test.key, nil) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - actual := <-ichan - if n != actual { - t.Errorf("Expected %q @ %d to be %d, got %d", - test.key, counter, n, actual) - } - } - } -} - -func TestNotFound(t *testing.T) { - t.Parallel() - m := New() - - r, _ := http.NewRequest("post", "/", nil) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - if w.Code != 404 { - t.Errorf("Expected 404, got %d", w.Code) - } - - m.NotFound(func(w http.ResponseWriter, r *http.Request) { - http.Error(w, "I'm a teapot!", http.StatusTeapot) - }) - - r, _ = http.NewRequest("POST", "/", nil) - w = httptest.NewRecorder() - m.ServeHTTP(w, r) - if w.Code != http.StatusTeapot { - t.Errorf("Expected a teapot, got %d", w.Code) - } -} - -func TestPrefix(t *testing.T) { - t.Parallel() - m := New() - ch := make(chan string, 1) - - m.Handle("/hello/*", func(w http.ResponseWriter, r *http.Request) { - ch <- r.URL.Path - }) - - r, _ := http.NewRequest("GET", "/hello/world", nil) - w := httptest.NewRecorder() - m.ServeHTTP(w, r) - select { - case val := <-ch: - if val != "/hello/world" { - t.Errorf("Got %q, expected /hello/world", val) - } - case <-time.After(5 * time.Millisecond): - t.Errorf("Timeout waiting for hello") - } -} - -var validMethodsTable = map[string][]string{ - "/hello/carl": {"DELETE", "GET", "HEAD", "PATCH", "POST", "PUT"}, - "/hello/bob": {"DELETE", "GET", "HEAD", "PATCH", "PUT"}, - "/hola/carl": {"DELETE", "GET", "HEAD", "PUT"}, - "/hola/bob": {"DELETE"}, - "/does/not/compute": {}, -} - -func TestValidMethods(t *testing.T) { - t.Parallel() - m := New() - ch := make(chan []string, 1) - - m.NotFound(func(c C, w http.ResponseWriter, r *http.Request) { - if c.Env == nil { - ch <- []string{} - return - } - methods, ok := c.Env[ValidMethodsKey] - if !ok { - ch <- []string{} - return - } - ch <- methods.([]string) - }) - - m.Get("/hello/carl", http.NotFound) - m.Post("/hello/carl", http.NotFound) - m.Head("/hello/bob", http.NotFound) - m.Get("/hello/:name", http.NotFound) - m.Put("/hello/:name", http.NotFound) - m.Patch("/hello/:name", http.NotFound) - m.Get("/:greet/carl", http.NotFound) - m.Put("/:greet/carl", http.NotFound) - m.Delete("/:greet/:anyone", http.NotFound) - - for path, eMethods := range validMethodsTable { - r, _ := http.NewRequest("BOGUS", path, nil) - m.ServeHTTP(httptest.NewRecorder(), r) - aMethods := <-ch - if !reflect.DeepEqual(eMethods, aMethods) { - t.Errorf("For %q, expected %v, got %v", path, eMethods, - aMethods) - } - } - - // This should also work when c.Env has already been initalized - m.Use(func(c *C, h http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - c.Env = make(map[interface{}]interface{}) - h.ServeHTTP(w, r) - }) - }) - for path, eMethods := range validMethodsTable { - r, _ := http.NewRequest("BOGUS", path, nil) - m.ServeHTTP(httptest.NewRecorder(), r) - aMethods := <-ch - if !reflect.DeepEqual(eMethods, aMethods) { - t.Errorf("For %q, expected %v, got %v", path, eMethods, - aMethods) - } - } -} diff --git a/vendor/github.com/zenazn/goji/web/string_pattern.go b/vendor/github.com/zenazn/goji/web/string_pattern.go deleted file mode 100644 index aa9b33a..0000000 --- a/vendor/github.com/zenazn/goji/web/string_pattern.go +++ /dev/null @@ -1,137 +0,0 @@ -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 deleted file mode 100644 index 21f6fcc..0000000 --- a/vendor/github.com/zenazn/goji/web/web.go +++ /dev/null @@ -1,112 +0,0 @@ -/* -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{}