Browse Source

Remove goji

Brett Langdon 9 years ago
parent
commit
aaeb008cd4
No known key found for this signature in database GPG Key ID: A2ECAB73CE12147F
77 changed files with 0 additions and 6492 deletions
  1. +0
    -33
      vendor/github.com/zenazn/goji/.travis.yml
  2. +0
    -20
      vendor/github.com/zenazn/goji/LICENSE
  3. +0
    -176
      vendor/github.com/zenazn/goji/README.md
  4. +0
    -145
      vendor/github.com/zenazn/goji/bind/bind.go
  5. +0
    -91
      vendor/github.com/zenazn/goji/bind/einhorn.go
  6. +0
    -12
      vendor/github.com/zenazn/goji/bind/einhorn_stub.go
  7. +0
    -36
      vendor/github.com/zenazn/goji/bind/systemd.go
  8. +0
    -6
      vendor/github.com/zenazn/goji/bind/systemd_stub.go
  9. +0
    -102
      vendor/github.com/zenazn/goji/default.go
  10. +0
    -1
      vendor/github.com/zenazn/goji/example/.gitignore
  11. +0
    -10
      vendor/github.com/zenazn/goji/example/README.md
  12. +0
    -177
      vendor/github.com/zenazn/goji/example/main.go
  13. +0
    -47
      vendor/github.com/zenazn/goji/example/middleware.go
  14. +0
    -49
      vendor/github.com/zenazn/goji/example/models.go
  15. +0
    -36
      vendor/github.com/zenazn/goji/goji.go
  16. +0
    -11
      vendor/github.com/zenazn/goji/graceful/clone.go
  17. +0
    -34
      vendor/github.com/zenazn/goji/graceful/clone16.go
  18. +0
    -21
      vendor/github.com/zenazn/goji/graceful/einhorn.go
  19. +0
    -62
      vendor/github.com/zenazn/goji/graceful/graceful.go
  20. +0
    -151
      vendor/github.com/zenazn/goji/graceful/listener/conn.go
  21. +0
    -198
      vendor/github.com/zenazn/goji/graceful/listener/conn_test.go
  22. +0
    -123
      vendor/github.com/zenazn/goji/graceful/listener/fake_test.go
  23. +0
    -178
      vendor/github.com/zenazn/goji/graceful/listener/listener.go
  24. +0
    -156
      vendor/github.com/zenazn/goji/graceful/listener/listener_test.go
  25. +0
    -103
      vendor/github.com/zenazn/goji/graceful/listener/race_test.go
  26. +0
    -98
      vendor/github.com/zenazn/goji/graceful/listener/shard.go
  27. +0
    -103
      vendor/github.com/zenazn/goji/graceful/middleware.go
  28. +0
    -71
      vendor/github.com/zenazn/goji/graceful/middleware_test.go
  29. +0
    -33
      vendor/github.com/zenazn/goji/graceful/serve.go
  30. +0
    -76
      vendor/github.com/zenazn/goji/graceful/serve13.go
  31. +0
    -108
      vendor/github.com/zenazn/goji/graceful/server.go
  32. +0
    -197
      vendor/github.com/zenazn/goji/graceful/signal.go
  33. +0
    -64
      vendor/github.com/zenazn/goji/serve.go
  34. +0
    -23
      vendor/github.com/zenazn/goji/serve_appengine.go
  35. +0
    -18
      vendor/github.com/zenazn/goji/web/atomic.go
  36. +0
    -14
      vendor/github.com/zenazn/goji/web/atomic_appengine.go
  37. +0
    -166
      vendor/github.com/zenazn/goji/web/bench_test.go
  38. +0
    -265
      vendor/github.com/zenazn/goji/web/bytecode_compiler.go
  39. +0
    -83
      vendor/github.com/zenazn/goji/web/bytecode_runner.go
  40. +0
    -31
      vendor/github.com/zenazn/goji/web/chanpool.go
  41. +0
    -23
      vendor/github.com/zenazn/goji/web/cpool.go
  42. +0
    -69
      vendor/github.com/zenazn/goji/web/example_test.go
  43. +0
    -32
      vendor/github.com/zenazn/goji/web/func_equal.go
  44. +0
    -84
      vendor/github.com/zenazn/goji/web/func_equal_test.go
  45. +0
    -42
      vendor/github.com/zenazn/goji/web/handler.go
  46. +0
    -66
      vendor/github.com/zenazn/goji/web/match.go
  47. +0
    -50
      vendor/github.com/zenazn/goji/web/match_test.go
  48. +0
    -154
      vendor/github.com/zenazn/goji/web/middleware.go
  49. +0
    -27
      vendor/github.com/zenazn/goji/web/middleware/envinit.go
  50. +0
    -92
      vendor/github.com/zenazn/goji/web/middleware/logger.go
  51. +0
    -4
      vendor/github.com/zenazn/goji/web/middleware/middleware.go
  52. +0
    -55
      vendor/github.com/zenazn/goji/web/middleware/nocache.go
  53. +0
    -29
      vendor/github.com/zenazn/goji/web/middleware/nocache_test.go
  54. +0
    -97
      vendor/github.com/zenazn/goji/web/middleware/options.go
  55. +0
    -112
      vendor/github.com/zenazn/goji/web/middleware/options_test.go
  56. +0
    -51
      vendor/github.com/zenazn/goji/web/middleware/realip.go
  57. +0
    -44
      vendor/github.com/zenazn/goji/web/middleware/recoverer.go
  58. +0
    -88
      vendor/github.com/zenazn/goji/web/middleware/request_id.go
  59. +0
    -65
      vendor/github.com/zenazn/goji/web/middleware/subrouter.go
  60. +0
    -28
      vendor/github.com/zenazn/goji/web/middleware/subrouter_test.go
  61. +0
    -60
      vendor/github.com/zenazn/goji/web/middleware/terminal.go
  62. +0
    -24
      vendor/github.com/zenazn/goji/web/middleware/urlquery.go
  63. +0
    -53
      vendor/github.com/zenazn/goji/web/middleware/urlquery_test.go
  64. +0
    -52
      vendor/github.com/zenazn/goji/web/middleware12_test.go
  65. +0
    -204
      vendor/github.com/zenazn/goji/web/middleware_test.go
  66. +0
    -3
      vendor/github.com/zenazn/goji/web/mutil/mutil.go
  67. +0
    -139
      vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go
  68. +0
    -213
      vendor/github.com/zenazn/goji/web/mux.go
  69. +0
    -45
      vendor/github.com/zenazn/goji/web/mux_test.go
  70. +0
    -58
      vendor/github.com/zenazn/goji/web/pattern.go
  71. +0
    -188
      vendor/github.com/zenazn/goji/web/pattern_test.go
  72. +0
    -149
      vendor/github.com/zenazn/goji/web/regexp_pattern.go
  73. +0
    -154
      vendor/github.com/zenazn/goji/web/router.go
  74. +0
    -35
      vendor/github.com/zenazn/goji/web/router_middleware_test.go
  75. +0
    -326
      vendor/github.com/zenazn/goji/web/router_test.go
  76. +0
    -137
      vendor/github.com/zenazn/goji/web/string_pattern.go
  77. +0
    -112
      vendor/github.com/zenazn/goji/web/web.go

+ 0
- 33
vendor/github.com/zenazn/goji/.travis.yml View File

@ -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 ./...

+ 0
- 20
vendor/github.com/zenazn/goji/LICENSE View File

@ -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.

+ 0
- 176
vendor/github.com/zenazn/goji/README.md View File

@ -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.

+ 0
- 145
vendor/github.com/zenazn/goji/bind/bind.go View File

@ -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()
})
}

+ 0
- 91
vendor/github.com/zenazn/goji/bind/einhorn.go View File

@ -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)
}
}

+ 0
- 12
vendor/github.com/zenazn/goji/bind/einhorn_stub.go View File

@ -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 }

+ 0
- 36
vendor/github.com/zenazn/goji/bind/systemd.go View File

@ -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
}

+ 0
- 6
vendor/github.com/zenazn/goji/bind/systemd_stub.go View File

@ -1,6 +0,0 @@
// +build windows
package bind
func systemdInit() {}
func usingSystemd() bool { return false }

+ 0
- 102
vendor/github.com/zenazn/goji/default.go View File

@ -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)
}

+ 0
- 1
vendor/github.com/zenazn/goji/example/.gitignore View File

@ -1 +0,0 @@
example

+ 0
- 10
vendor/github.com/zenazn/goji/example/README.md View File

@ -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`.

+ 0
- 177
vendor/github.com/zenazn/goji/example/main.go View File

@ -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<id>\d+)$`), GetGreet)
// Middleware can be used to inject behavior into your app. The
// middleware for this application are defined in middleware.go, but you
// can put them wherever you like.
goji.Use(PlainText)
// If the patterns ends with "/*", the path is treated as a prefix, and
// can be used to implement sub-routes.
admin := web.New()
goji.Handle("/admin/*", admin)
// The standard SubRouter middleware helps make writing sub-routers
// easy. Ordinarily, Goji does not manipulate the request's URL.Path,
// meaning you'd have to repeat "/admin/" in each of the following
// routes. This middleware allows you to cut down on the repetition by
// eliminating the shared, already-matched prefix.
admin.Use(middleware.SubRouter)
// You can also easily attach extra middleware to sub-routers that are
// not present on the parent router. This one, for instance, presents a
// password prompt to users of the admin endpoints.
admin.Use(SuperSecure)
admin.Get("/", AdminRoot)
admin.Get("/finances", AdminFinances)
// Goji's routing, like Sinatra's, is exact: no effort is made to
// normalize trailing slashes.
goji.Get("/admin", http.RedirectHandler("/admin/", 301))
// Use a custom 404 handler
goji.NotFound(NotFound)
// Sometimes requests take a long time.
goji.Get("/waitforit", WaitForIt)
// Call Serve() at the bottom of your main() function, and it'll take
// care of everything else for you, including binding to a socket (with
// automatic support for systemd and Einhorn) and supporting graceful
// shutdown on SIGINT. Serve() is appropriate for both development and
// production.
goji.Serve()
}
// Root route (GET "/"). Print a list of greets.
func Root(w http.ResponseWriter, r *http.Request) {
// In the real world you'd probably use a template or something.
io.WriteString(w, "Gritter\n======\n\n")
for i := len(Greets) - 1; i >= 0; i-- {
Greets[i].Write(w)
}
}
// NewGreet creates a new greet (POST "/greets"). Creates a greet and redirects
// you to the created greet.
//
// To post a new greet, try this at a shell:
// $ now=$(date +'%Y-%m-%dT%H:%M:%SZ')
// $ curl -i -d "user=carl&message=Hello+World&time=$now" localhost:8000/greets
func NewGreet(w http.ResponseWriter, r *http.Request) {
var greet Greet
// Parse the POST body into the Greet struct. The format is the same as
// is emitted by (e.g.) jQuery.param.
r.ParseForm()
err := param.Parse(r.Form, &greet)
if err != nil || len(greet.Message) > 140 {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// We make no effort to prevent races against other insertions.
Greets = append(Greets, greet)
url := fmt.Sprintf("/greets/%d", len(Greets)-1)
http.Redirect(w, r, url, http.StatusCreated)
}
// GetUser finds a given user and her greets (GET "/user/:name")
func GetUser(c web.C, w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Gritter\n======\n\n")
handle := c.URLParams["name"]
user, ok := Users[handle]
if !ok {
http.Error(w, http.StatusText(404), 404)
return
}
user.Write(w, handle)
io.WriteString(w, "\nGreets:\n")
for i := len(Greets) - 1; i >= 0; i-- {
if Greets[i].User == handle {
Greets[i].Write(w)
}
}
}
// GetGreet finds a particular greet by ID (GET "/greets/\d+"). Does no bounds
// checking, so will probably panic.
func GetGreet(c web.C, w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(c.URLParams["id"])
if err != nil {
http.Error(w, http.StatusText(404), 404)
return
}
// This will panic if id is too big. Try it out!
greet := Greets[id]
io.WriteString(w, "Gritter\n======\n\n")
greet.Write(w)
}
// WaitForIt is a particularly slow handler (GET "/waitforit"). Try loading this
// endpoint and initiating a graceful shutdown (Ctrl-C) or Einhorn reload. The
// old server will stop accepting new connections and will attempt to kill
// outstanding idle (keep-alive) connections, but will patiently stick around
// for this endpoint to finish. How kind of it!
func WaitForIt(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "This is going to be legend... (wait for it)\n")
if fl, ok := w.(http.Flusher); ok {
fl.Flush()
}
time.Sleep(15 * time.Second)
io.WriteString(w, "...dary! Legendary!\n")
}
// AdminRoot is root (GET "/admin/root"). Much secret. Very administrate. Wow.
func AdminRoot(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Gritter\n======\n\nSuper secret admin page!\n")
}
// AdminFinances would answer the question 'How are we doing?'
// (GET "/admin/finances")
func AdminFinances(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "Gritter\n======\n\nWe're broke! :(\n")
}
// NotFound is a 404 handler.
func NotFound(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Umm... have you tried turning it off and on again?", 404)
}

+ 0
- 47
vendor/github.com/zenazn/goji/example/middleware.go View File

@ -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"))
}

+ 0
- 49
vendor/github.com/zenazn/goji/example/models.go View File

@ -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)
}

+ 0
- 36
vendor/github.com/zenazn/goji/goji.go View File

@ -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

+ 0
- 11
vendor/github.com/zenazn/goji/graceful/clone.go View File

@ -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
}

+ 0
- 34
vendor/github.com/zenazn/goji/graceful/clone16.go View File

@ -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,
}
}

+ 0
- 21
vendor/github.com/zenazn/goji/graceful/einhorn.go View File

@ -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)
}

+ 0
- 62
vendor/github.com/zenazn/goji/graceful/graceful.go View File

@ -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
}

+ 0
- 151
vendor/github.com/zenazn/goji/graceful/listener/conn.go View File

@ -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
}

+ 0
- 198
vendor/github.com/zenazn/goji/graceful/listener/conn_test.go View File

@ -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)
}
}

+ 0
- 123
vendor/github.com/zenazn/goji/graceful/listener/fake_test.go View File

@ -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{}{}
}

+ 0
- 178
vendor/github.com/zenazn/goji/graceful/listener/listener.go View File

@ -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
}

+ 0
- 156
vendor/github.com/zenazn/goji/graceful/listener/listener_test.go View File

@ -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?")
}
}

+ 0
- 103
vendor/github.com/zenazn/goji/graceful/listener/race_test.go View File

@ -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)
}
}

+ 0
- 98
vendor/github.com/zenazn/goji/graceful/listener/shard.go View File

@ -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()
}

+ 0
- 103
vendor/github.com/zenazn/goji/graceful/middleware.go View File

@ -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{}

+ 0
- 71
vendor/github.com/zenazn/goji/graceful/middleware_test.go View File

@ -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)
}

+ 0
- 33
vendor/github.com/zenazn/goji/graceful/serve.go View File

@ -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)
}

+ 0
- 76
vendor/github.com/zenazn/goji/graceful/serve13.go View File

@ -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)
}

+ 0
- 108
vendor/github.com/zenazn/goji/graceful/server.go View File

@ -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)
}

+ 0
- 197
vendor/github.com/zenazn/goji/graceful/signal.go View File

@ -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)
}
}

+ 0
- 64
vendor/github.com/zenazn/goji/serve.go View File

@ -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()
}

+ 0
- 23
vendor/github.com/zenazn/goji/serve_appengine.go View File

@ -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)
}

+ 0
- 18
vendor/github.com/zenazn/goji/web/atomic.go View File

@ -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))
}

+ 0
- 14
vendor/github.com/zenazn/goji/web/atomic_appengine.go View File

@ -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
}

+ 0
- 166
vendor/github.com/zenazn/goji/web/bench_test.go View File

@ -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)
}

+ 0
- 265
vendor/github.com/zenazn/goji/web/bytecode_compiler.go View File

@ -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
}

+ 0
- 83
vendor/github.com/zenazn/goji/web/bytecode_runner.go View File

@ -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++
}
}
}

+ 0
- 31
vendor/github.com/zenazn/goji/web/chanpool.go View File

@ -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:
}
}

+ 0
- 23
vendor/github.com/zenazn/goji/web/cpool.go View File

@ -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)
}

+ 0
- 69
vendor/github.com/zenazn/goji/web/example_test.go View File

@ -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<name>[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)
}

+ 0
- 32
vendor/github.com/zenazn/goji/web/func_equal.go View File

@ -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()
}

+ 0
- 84
vendor/github.com/zenazn/goji/web/func_equal_test.go View File

@ -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")
}
}

+ 0
- 42
vendor/github.com/zenazn/goji/web/handler.go View File

@ -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")
}
}

+ 0
- 66
vendor/github.com/zenazn/goji/web/match.go View File

@ -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
}
}

+ 0
- 50
vendor/github.com/zenazn/goji/web/match_test.go View File

@ -1,50 +0,0 @@
package web
import (
"net/http"
"regexp"
"testing"
)
var rawPatterns = []PatternType{
"/hello/:name",
regexp.MustCompile("^/hello/(?P<name>[^/]+)$"),
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)
}
}
}

+ 0
- 154
vendor/github.com/zenazn/goji/web/middleware.go View File

@ -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
}

+ 0
- 27
vendor/github.com/zenazn/goji/web/middleware/envinit.go View File

@ -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}
}

+ 0
- 92
vendor/github.com/zenazn/goji/web/middleware/logger.go View File

@ -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())
}

+ 0
- 4
vendor/github.com/zenazn/goji/web/middleware/middleware.go View File

@ -1,4 +0,0 @@
/*
Package middleware provides several standard middleware implementations.
*/
package middleware

+ 0
- 55
vendor/github.com/zenazn/goji/web/middleware/nocache.go View File

@ -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)
}

+ 0
- 29
vendor/github.com/zenazn/goji/web/middleware/nocache_test.go View File

@ -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)
}
}
}

+ 0
- 97
vendor/github.com/zenazn/goji/web/middleware/options.go View File

@ -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)
}

+ 0
- 112
vendor/github.com/zenazn/goji/web/middleware/options_test.go View File

@ -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)
}
}

+ 0
- 51
vendor/github.com/zenazn/goji/web/middleware/realip.go View File

@ -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
}

+ 0
- 44
vendor/github.com/zenazn/goji/web/middleware/recoverer.go View File

@ -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())
}

+ 0
- 88
vendor/github.com/zenazn/goji/web/middleware/request_id.go View File

@ -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 ""
}

+ 0
- 65
vendor/github.com/zenazn/goji/web/middleware/subrouter.go View File

@ -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}
}

+ 0
- 28
vendor/github.com/zenazn/goji/web/middleware/subrouter_test.go View File

@ -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)
}

+ 0
- 60
vendor/github.com/zenazn/goji/web/middleware/terminal.go View File

@ -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)
}
}

+ 0
- 24
vendor/github.com/zenazn/goji/web/middleware/urlquery.go View File

@ -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)
}

+ 0
- 53
vendor/github.com/zenazn/goji/web/middleware/urlquery_test.go View File

@ -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'})
},
)
}
}

+ 0
- 52
vendor/github.com/zenazn/goji/web/middleware12_test.go View File

@ -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")
}
}

+ 0
- 204
vendor/github.com/zenazn/goji/web/middleware_test.go View File

@ -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")
}

+ 0
- 3
vendor/github.com/zenazn/goji/web/mutil/mutil.go View File

@ -1,3 +0,0 @@
// Package mutil contains various functions that are helpful when writing http
// middleware.
package mutil

+ 0
- 139
vendor/github.com/zenazn/goji/web/mutil/writer_proxy.go View File

@ -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{}

+ 0
- 213
vendor/github.com/zenazn/goji/web/mux.go View File

@ -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()
}

+ 0
- 45
vendor/github.com/zenazn/goji/web/mux_test.go View File

@ -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)
}
}

+ 0
- 58
vendor/github.com/zenazn/goji/web/pattern.go View File

@ -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")
}
}

+ 0
- 188
vendor/github.com/zenazn/goji/web/pattern_test.go View File

@ -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<name>[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<a>\d+)/b(?P<b>\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)
}
}

+ 0
- 149
vendor/github.com/zenazn/goji/web/regexp_pattern.go View File

@ -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,
}
}

+ 0
- 154
vendor/github.com/zenazn/goji/web/router.go View File

@ -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
}

+ 0
- 35
vendor/github.com/zenazn/goji/web/router_middleware_test.go View File

@ -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)
}
}

+ 0
- 326
vendor/github.com/zenazn/goji/web/router_test.go View File

@ -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<name>.+)$`), 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)
}
}
}

+ 0
- 137
vendor/github.com/zenazn/goji/web/string_pattern.go View File

@ -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,
}
}

+ 0
- 112
vendor/github.com/zenazn/goji/web/web.go View File

@ -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{}

Loading…
Cancel
Save