diff --git a/vendor/manifest b/vendor/manifest index 92430d2..27c30ce 100644 --- a/vendor/manifest +++ b/vendor/manifest @@ -13,6 +13,12 @@ "revision": "1128ce320b775e8e3fa2b8095b9c2116aa6869db", "branch": "master" }, + { + "importpath": "github.com/codegangsta/negroni", + "repository": "https://github.com/codegangsta/negroni", + "revision": "c7477ad8e330bef55bf1ebe300cf8aa67c492d1b", + "branch": "master" + }, { "importpath": "github.com/layeh/gopher-json", "repository": "https://github.com/layeh/gopher-json", diff --git a/vendor/src/github.com/codegangsta/negroni/LICENSE b/vendor/src/github.com/codegangsta/negroni/LICENSE new file mode 100644 index 0000000..08b5e20 --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jeremy Saenz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/src/github.com/codegangsta/negroni/README.md b/vendor/src/github.com/codegangsta/negroni/README.md new file mode 100644 index 0000000..9294d70 --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/README.md @@ -0,0 +1,181 @@ +# Negroni [![GoDoc](https://godoc.org/github.com/codegangsta/negroni?status.svg)](http://godoc.org/github.com/codegangsta/negroni) [![wercker status](https://app.wercker.com/status/13688a4a94b82d84a0b8d038c4965b61/s "wercker status")](https://app.wercker.com/project/bykey/13688a4a94b82d84a0b8d038c4965b61) + +Negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of `net/http` Handlers. + +If you like the idea of [Martini](http://github.com/go-martini/martini), but you think it contains too much magic, then Negroni is a great fit. + + +Language Translations: +* [Português Brasileiro (pt_BR)](translations/README_pt_br.md) + +## Getting Started + +After installing Go and setting up your [GOPATH](http://golang.org/doc/code.html#GOPATH), create your first `.go` file. We'll call it `server.go`. + +~~~ go +package main + +import ( + "github.com/codegangsta/negroni" + "net/http" + "fmt" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) + + n := negroni.Classic() + n.UseHandler(mux) + n.Run(":3000") +} +~~~ + +Then install the Negroni package (**go 1.1** and greater is required): +~~~ +go get github.com/codegangsta/negroni +~~~ + +Then run your server: +~~~ +go run server.go +~~~ + +You will now have a Go net/http webserver running on `localhost:3000`. + +## Need Help? +If you have a question or feature request, [go ask the mailing list](https://groups.google.com/forum/#!forum/negroni-users). The GitHub issues for Negroni will be used exclusively for bug reports and pull requests. + +## Is Negroni a Framework? +Negroni is **not** a framework. It is a library that is designed to work directly with net/http. + +## Routing? +Negroni is BYOR (Bring your own Router). The Go community already has a number of great http routers available, Negroni tries to play well with all of them by fully supporting `net/http`. For instance, integrating with [Gorilla Mux](http://github.com/gorilla/mux) looks like so: + +~~~ go +router := mux.NewRouter() +router.HandleFunc("/", HomeHandler) + +n := negroni.New(Middleware1, Middleware2) +// Or use a middleware with the Use() function +n.Use(Middleware3) +// router goes last +n.UseHandler(router) + +n.Run(":3000") +~~~ + +## `negroni.Classic()` +`negroni.Classic()` provides some default middleware that is useful for most applications: + +* `negroni.Recovery` - Panic Recovery Middleware. +* `negroni.Logging` - Request/Response Logging Middleware. +* `negroni.Static` - Static File serving under the "public" directory. + +This makes it really easy to get started with some useful features from Negroni. + +## Handlers +Negroni provides a bidirectional middleware flow. This is done through the `negroni.Handler` interface: + +~~~ go +type Handler interface { + ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) +} +~~~ + +If a middleware hasn't already written to the ResponseWriter, it should call the next `http.HandlerFunc` in the chain to yield to the next middleware handler. This can be used for great good: + +~~~ go +func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + // do some stuff before + next(rw, r) + // do some stuff after +} +~~~ + +And you can map it to the handler chain with the `Use` function: + +~~~ go +n := negroni.New() +n.Use(negroni.HandlerFunc(MyMiddleware)) +~~~ + +You can also map plain old `http.Handler`s: + +~~~ go +n := negroni.New() + +mux := http.NewServeMux() +// map your routes + +n.UseHandler(mux) + +n.Run(":3000") +~~~ + +## `Run()` +Negroni has a convenience function called `Run`. `Run` takes an addr string identical to [http.ListenAndServe](http://golang.org/pkg/net/http#ListenAndServe). + +~~~ go +n := negroni.Classic() +// ... +log.Fatal(http.ListenAndServe(":8080", n)) +~~~ + +## Route Specific Middleware +If you have a route group of routes that need specific middleware to be executed, you can simply create a new Negroni instance and use it as your route handler. + +~~~ go +router := mux.NewRouter() +adminRoutes := mux.NewRouter() +// add admin routes here + +// Create a new negroni for the admin middleware +router.Handle("/admin", negroni.New( + Middleware1, + Middleware2, + negroni.Wrap(adminRoutes), +)) +~~~ + +## Third Party Middleware + +Here is a current list of Negroni compatible middlware. Feel free to put up a PR linking your middleware if you have built one: + + +| Middleware | Author | Description | +| -----------|--------|-------------| +| [RestGate](https://github.com/pjebs/restgate) | [Prasanga Siripala](https://github.com/pjebs) | Secure authentication for REST API endpoints | +| [Graceful](https://github.com/stretchr/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown | +| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Middleware that implements a few quick security wins | +| [JWT Middleware](https://github.com/auth0/go-jwt-middleware) | [Auth0](https://github.com/auth0) | Middleware checks for a JWT on the `Authorization` header on incoming requests and decodes it| +| [binding](https://github.com/mholt/binding) | [Matt Holt](https://github.com/mholt) | Data binding from HTTP requests into structs | +| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger | +| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Render JSON, XML and HTML templates | +| [gorelic](https://github.com/jingweno/negroni-gorelic) | [Jingwen Owen Ou](https://github.com/jingweno) | New Relic agent for Go runtime | +| [gzip](https://github.com/phyber/negroni-gzip) | [phyber](https://github.com/phyber) | GZIP response compression | +| [oauth2](https://github.com/goincremental/negroni-oauth2) | [David Bochenski](https://github.com/bochenski) | oAuth2 middleware | +| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Session Management | +| [permissions2](https://github.com/xyproto/permissions2) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, users and permissions | +| [onthefly](https://github.com/xyproto/onthefly) | [Alexander Rødseth](https://github.com/xyproto) | Generate TinySVG, HTML and CSS on the fly | +| [cors](https://github.com/rs/cors) | [Olivier Poitrey](https://github.com/rs) | [Cross Origin Resource Sharing](http://www.w3.org/TR/cors/) (CORS) support | +| [xrequestid](https://github.com/pilu/xrequestid) | [Andrea Franz](https://github.com/pilu) | Middleware that assigns a random X-Request-Id header to each request | +| [VanGoH](https://github.com/auroratechnologies/vangoh) | [Taylor Wrobel](https://github.com/twrobel3) | Configurable [AWS-Style](http://docs.aws.amazon.com/AmazonS3/latest/dev/RESTAuthentication.html) HMAC authentication middleware | +| [stats](https://github.com/thoas/stats) | [Florent Messa](https://github.com/thoas) | Store information about your web application (response time, etc.) | + +## Examples +[Alexander Rødseth](https://github.com/xyproto) created [mooseware](https://github.com/xyproto/mooseware), a skeleton for writing a Negroni middleware handler. + +## Live code reload? +[gin](https://github.com/codegangsta/gin) and [fresh](https://github.com/pilu/fresh) both live reload negroni apps. + +## Essential Reading for Beginners of Go & Negroni + +* [Using a Context to pass information from middleware to end handler](http://elithrar.github.io/article/map-string-interface/) +* [Understanding middleware](http://mattstauffer.co/blog/laravel-5.0-middleware-replacing-filters) + +## About + +Negroni is obsessively designed by none other than the [Code Gangsta](http://codegangsta.io/) diff --git a/vendor/src/github.com/codegangsta/negroni/doc.go b/vendor/src/github.com/codegangsta/negroni/doc.go new file mode 100644 index 0000000..24d6572 --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/doc.go @@ -0,0 +1,25 @@ +// Package negroni is an idiomatic approach to web middleware in Go. It is tiny, non-intrusive, and encourages use of net/http Handlers. +// +// If you like the idea of Martini, but you think it contains too much magic, then Negroni is a great fit. +// +// For a full guide visit http://github.com/codegangsta/negroni +// +// package main +// +// import ( +// "github.com/codegangsta/negroni" +// "net/http" +// "fmt" +// ) +// +// func main() { +// mux := http.NewServeMux() +// mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { +// fmt.Fprintf(w, "Welcome to the home page!") +// }) +// +// n := negroni.Classic() +// n.UseHandler(mux) +// n.Run(":3000") +// } +package negroni diff --git a/vendor/src/github.com/codegangsta/negroni/logger.go b/vendor/src/github.com/codegangsta/negroni/logger.go new file mode 100644 index 0000000..e3828ef --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/logger.go @@ -0,0 +1,29 @@ +package negroni + +import ( + "log" + "net/http" + "os" + "time" +) + +// Logger is a middleware handler that logs the request as it goes in and the response as it goes out. +type Logger struct { + // Logger inherits from log.Logger used to log messages with the Logger middleware + *log.Logger +} + +// NewLogger returns a new Logger instance +func NewLogger() *Logger { + return &Logger{log.New(os.Stdout, "[negroni] ", 0)} +} + +func (l *Logger) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + start := time.Now() + l.Printf("Started %s %s", r.Method, r.URL.Path) + + next(rw, r) + + res := rw.(ResponseWriter) + l.Printf("Completed %v %s in %v", res.Status(), http.StatusText(res.Status()), time.Since(start)) +} diff --git a/vendor/src/github.com/codegangsta/negroni/logger_test.go b/vendor/src/github.com/codegangsta/negroni/logger_test.go new file mode 100644 index 0000000..880337d --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/logger_test.go @@ -0,0 +1,33 @@ +package negroni + +import ( + "bytes" + "log" + "net/http" + "net/http/httptest" + "testing" +) + +func Test_Logger(t *testing.T) { + buff := bytes.NewBufferString("") + recorder := httptest.NewRecorder() + + l := NewLogger() + l.Logger = log.New(buff, "[negroni] ", 0) + + n := New() + // replace log for testing + n.Use(l) + n.UseHandler(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + rw.WriteHeader(http.StatusNotFound) + })) + + req, err := http.NewRequest("GET", "http://localhost:3000/foobar", nil) + if err != nil { + t.Error(err) + } + + n.ServeHTTP(recorder, req) + expect(t, recorder.Code, http.StatusNotFound) + refute(t, len(buff.String()), 0) +} diff --git a/vendor/src/github.com/codegangsta/negroni/negroni.go b/vendor/src/github.com/codegangsta/negroni/negroni.go new file mode 100644 index 0000000..57d15eb --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/negroni.go @@ -0,0 +1,129 @@ +package negroni + +import ( + "log" + "net/http" + "os" +) + +// Handler handler is an interface that objects can implement to be registered to serve as middleware +// in the Negroni middleware stack. +// ServeHTTP should yield to the next middleware in the chain by invoking the next http.HandlerFunc +// passed in. +// +// If the Handler writes to the ResponseWriter, the next http.HandlerFunc should not be invoked. +type Handler interface { + ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) +} + +// HandlerFunc is an adapter to allow the use of ordinary functions as Negroni handlers. +// If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f. +type HandlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) + +func (h HandlerFunc) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + h(rw, r, next) +} + +type middleware struct { + handler Handler + next *middleware +} + +func (m middleware) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + m.handler.ServeHTTP(rw, r, m.next.ServeHTTP) +} + +// Wrap converts a http.Handler into a negroni.Handler so it can be used as a Negroni +// middleware. The next http.HandlerFunc is automatically called after the Handler +// is executed. +func Wrap(handler http.Handler) Handler { + return HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + handler.ServeHTTP(rw, r) + next(rw, r) + }) +} + +// Negroni is a stack of Middleware Handlers that can be invoked as an http.Handler. +// Negroni middleware is evaluated in the order that they are added to the stack using +// the Use and UseHandler methods. +type Negroni struct { + middleware middleware + handlers []Handler +} + +// New returns a new Negroni instance with no middleware preconfigured. +func New(handlers ...Handler) *Negroni { + return &Negroni{ + handlers: handlers, + middleware: build(handlers), + } +} + +// Classic returns a new Negroni instance with the default middleware already +// in the stack. +// +// Recovery - Panic Recovery Middleware +// Logger - Request/Response Logging +// Static - Static File Serving +func Classic() *Negroni { + return New(NewRecovery(), NewLogger(), NewStatic(http.Dir("public"))) +} + +func (n *Negroni) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + n.middleware.ServeHTTP(NewResponseWriter(rw), r) +} + +// Use adds a Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. +func (n *Negroni) Use(handler Handler) { + n.handlers = append(n.handlers, handler) + n.middleware = build(n.handlers) +} + +// UseFunc adds a Negroni-style handler function onto the middleware stack. +func (n *Negroni) UseFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc)) { + n.Use(HandlerFunc(handlerFunc)) +} + +// UseHandler adds a http.Handler onto the middleware stack. Handlers are invoked in the order they are added to a Negroni. +func (n *Negroni) UseHandler(handler http.Handler) { + n.Use(Wrap(handler)) +} + +// UseHandler adds a http.HandlerFunc-style handler function onto the middleware stack. +func (n *Negroni) UseHandlerFunc(handlerFunc func(rw http.ResponseWriter, r *http.Request)) { + n.UseHandler(http.HandlerFunc(handlerFunc)) +} + +// Run is a convenience function that runs the negroni stack as an HTTP +// server. The addr string takes the same format as http.ListenAndServe. +func (n *Negroni) Run(addr string) { + l := log.New(os.Stdout, "[negroni] ", 0) + l.Printf("listening on %s", addr) + l.Fatal(http.ListenAndServe(addr, n)) +} + +// Returns a list of all the handlers in the current Negroni middleware chain. +func (n *Negroni) Handlers() []Handler { + return n.handlers +} + +func build(handlers []Handler) middleware { + var next middleware + + if len(handlers) == 0 { + return voidMiddleware() + } else if len(handlers) > 1 { + next = build(handlers[1:]) + } else { + next = voidMiddleware() + } + + return middleware{handlers[0], &next} +} + +func voidMiddleware() middleware { + return middleware{ + HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {}), + &middleware{}, + } +} diff --git a/vendor/src/github.com/codegangsta/negroni/negroni_test.go b/vendor/src/github.com/codegangsta/negroni/negroni_test.go new file mode 100644 index 0000000..0f6607a --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/negroni_test.go @@ -0,0 +1,75 @@ +package negroni + +import ( + "net/http" + "net/http/httptest" + "reflect" + "testing" +) + +/* Test Helpers */ +func expect(t *testing.T, a interface{}, b interface{}) { + if a != b { + t.Errorf("Expected %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) + } +} + +func refute(t *testing.T, a interface{}, b interface{}) { + if a == b { + t.Errorf("Did not expect %v (type %v) - Got %v (type %v)", b, reflect.TypeOf(b), a, reflect.TypeOf(a)) + } +} + +func TestNegroniRun(t *testing.T) { + // just test that Run doesn't bomb + go New().Run(":3000") +} + +func TestNegroniServeHTTP(t *testing.T) { + result := "" + response := httptest.NewRecorder() + + n := New() + n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + result += "foo" + next(rw, r) + result += "ban" + })) + n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + result += "bar" + next(rw, r) + result += "baz" + })) + n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + result += "bat" + rw.WriteHeader(http.StatusBadRequest) + })) + + n.ServeHTTP(response, (*http.Request)(nil)) + + expect(t, result, "foobarbatbazban") + expect(t, response.Code, http.StatusBadRequest) +} + +// Ensures that a Negroni middleware chain +// can correctly return all of its handlers. +func TestHandlers(t *testing.T) { + response := httptest.NewRecorder() + n := New() + handlers := n.Handlers() + expect(t, 0, len(handlers)) + + n.Use(HandlerFunc(func(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + rw.WriteHeader(http.StatusOK) + })) + + // Expects the length of handlers to be exactly 1 + // after adding exactly one handler to the middleware chain + handlers = n.Handlers() + expect(t, 1, len(handlers)) + + // Ensures that the first handler that is in sequence behaves + // exactly the same as the one that was registered earlier + handlers[0].ServeHTTP(response, (*http.Request)(nil), nil) + expect(t, response.Code, http.StatusOK) +} \ No newline at end of file diff --git a/vendor/src/github.com/codegangsta/negroni/recovery.go b/vendor/src/github.com/codegangsta/negroni/recovery.go new file mode 100644 index 0000000..d790cad --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/recovery.go @@ -0,0 +1,46 @@ +package negroni + +import ( + "fmt" + "log" + "net/http" + "os" + "runtime" +) + +// Recovery is a Negroni middleware that recovers from any panics and writes a 500 if there was one. +type Recovery struct { + Logger *log.Logger + PrintStack bool + StackAll bool + StackSize int +} + +// NewRecovery returns a new instance of Recovery +func NewRecovery() *Recovery { + return &Recovery{ + Logger: log.New(os.Stdout, "[negroni] ", 0), + PrintStack: true, + StackAll: false, + StackSize: 1024 * 8, + } +} + +func (rec *Recovery) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + defer func() { + if err := recover(); err != nil { + rw.WriteHeader(http.StatusInternalServerError) + stack := make([]byte, rec.StackSize) + stack = stack[:runtime.Stack(stack, rec.StackAll)] + + f := "PANIC: %s\n%s" + rec.Logger.Printf(f, err, stack) + + if rec.PrintStack { + fmt.Fprintf(rw, f, err, stack) + } + } + }() + + next(rw, r) +} diff --git a/vendor/src/github.com/codegangsta/negroni/recovery_test.go b/vendor/src/github.com/codegangsta/negroni/recovery_test.go new file mode 100644 index 0000000..3fa264a --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/recovery_test.go @@ -0,0 +1,28 @@ +package negroni + +import ( + "bytes" + "log" + "net/http" + "net/http/httptest" + "testing" +) + +func TestRecovery(t *testing.T) { + buff := bytes.NewBufferString("") + recorder := httptest.NewRecorder() + + rec := NewRecovery() + rec.Logger = log.New(buff, "[negroni] ", 0) + + n := New() + // replace log for testing + n.Use(rec) + n.UseHandler(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + panic("here is a panic!") + })) + n.ServeHTTP(recorder, (*http.Request)(nil)) + expect(t, recorder.Code, http.StatusInternalServerError) + refute(t, recorder.Body.Len(), 0) + refute(t, len(buff.String()), 0) +} diff --git a/vendor/src/github.com/codegangsta/negroni/response_writer.go b/vendor/src/github.com/codegangsta/negroni/response_writer.go new file mode 100644 index 0000000..ea86a26 --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/response_writer.go @@ -0,0 +1,96 @@ +package negroni + +import ( + "bufio" + "fmt" + "net" + "net/http" +) + +// ResponseWriter is a wrapper around http.ResponseWriter that provides extra information about +// the response. It is recommended that middleware handlers use this construct to wrap a responsewriter +// if the functionality calls for it. +type ResponseWriter interface { + http.ResponseWriter + http.Flusher + // Status returns the status code of the response or 0 if the response has not been written. + Status() int + // Written returns whether or not the ResponseWriter has been written. + Written() bool + // Size returns the size of the response body. + Size() int + // Before allows for a function to be called before the ResponseWriter has been written to. This is + // useful for setting headers or any other operations that must happen before a response has been written. + Before(func(ResponseWriter)) +} + +type beforeFunc func(ResponseWriter) + +// NewResponseWriter creates a ResponseWriter that wraps an http.ResponseWriter +func NewResponseWriter(rw http.ResponseWriter) ResponseWriter { + return &responseWriter{rw, 0, 0, nil} +} + +type responseWriter struct { + http.ResponseWriter + status int + size int + beforeFuncs []beforeFunc +} + +func (rw *responseWriter) WriteHeader(s int) { + rw.status = s + rw.callBefore() + rw.ResponseWriter.WriteHeader(s) +} + +func (rw *responseWriter) Write(b []byte) (int, error) { + if !rw.Written() { + // The status will be StatusOK if WriteHeader has not been called yet + rw.WriteHeader(http.StatusOK) + } + size, err := rw.ResponseWriter.Write(b) + rw.size += size + return size, err +} + +func (rw *responseWriter) Status() int { + return rw.status +} + +func (rw *responseWriter) Size() int { + return rw.size +} + +func (rw *responseWriter) Written() bool { + return rw.status != 0 +} + +func (rw *responseWriter) Before(before func(ResponseWriter)) { + rw.beforeFuncs = append(rw.beforeFuncs, before) +} + +func (rw *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { + hijacker, ok := rw.ResponseWriter.(http.Hijacker) + if !ok { + return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface") + } + return hijacker.Hijack() +} + +func (rw *responseWriter) CloseNotify() <-chan bool { + return rw.ResponseWriter.(http.CloseNotifier).CloseNotify() +} + +func (rw *responseWriter) callBefore() { + for i := len(rw.beforeFuncs) - 1; i >= 0; i-- { + rw.beforeFuncs[i](rw) + } +} + +func (rw *responseWriter) Flush() { + flusher, ok := rw.ResponseWriter.(http.Flusher) + if ok { + flusher.Flush() + } +} diff --git a/vendor/src/github.com/codegangsta/negroni/response_writer_test.go b/vendor/src/github.com/codegangsta/negroni/response_writer_test.go new file mode 100644 index 0000000..ed1ee70 --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/response_writer_test.go @@ -0,0 +1,150 @@ +package negroni + +import ( + "bufio" + "net" + "net/http" + "net/http/httptest" + "testing" + "time" +) + +type closeNotifyingRecorder struct { + *httptest.ResponseRecorder + closed chan bool +} + +func newCloseNotifyingRecorder() *closeNotifyingRecorder { + return &closeNotifyingRecorder{ + httptest.NewRecorder(), + make(chan bool, 1), + } +} + +func (c *closeNotifyingRecorder) close() { + c.closed <- true +} + +func (c *closeNotifyingRecorder) CloseNotify() <-chan bool { + return c.closed +} + +type hijackableResponse struct { + Hijacked bool +} + +func newHijackableResponse() *hijackableResponse { + return &hijackableResponse{} +} + +func (h *hijackableResponse) Header() http.Header { return nil } +func (h *hijackableResponse) Write(buf []byte) (int, error) { return 0, nil } +func (h *hijackableResponse) WriteHeader(code int) {} +func (h *hijackableResponse) Flush() {} +func (h *hijackableResponse) Hijack() (net.Conn, *bufio.ReadWriter, error) { + h.Hijacked = true + return nil, nil, nil +} + +func TestResponseWriterWritingString(t *testing.T) { + rec := httptest.NewRecorder() + rw := NewResponseWriter(rec) + + rw.Write([]byte("Hello world")) + + expect(t, rec.Code, rw.Status()) + expect(t, rec.Body.String(), "Hello world") + expect(t, rw.Status(), http.StatusOK) + expect(t, rw.Size(), 11) + expect(t, rw.Written(), true) +} + +func TestResponseWriterWritingStrings(t *testing.T) { + rec := httptest.NewRecorder() + rw := NewResponseWriter(rec) + + rw.Write([]byte("Hello world")) + rw.Write([]byte("foo bar bat baz")) + + expect(t, rec.Code, rw.Status()) + expect(t, rec.Body.String(), "Hello worldfoo bar bat baz") + expect(t, rw.Status(), http.StatusOK) + expect(t, rw.Size(), 26) +} + +func TestResponseWriterWritingHeader(t *testing.T) { + rec := httptest.NewRecorder() + rw := NewResponseWriter(rec) + + rw.WriteHeader(http.StatusNotFound) + + expect(t, rec.Code, rw.Status()) + expect(t, rec.Body.String(), "") + expect(t, rw.Status(), http.StatusNotFound) + expect(t, rw.Size(), 0) +} + +func TestResponseWriterBefore(t *testing.T) { + rec := httptest.NewRecorder() + rw := NewResponseWriter(rec) + result := "" + + rw.Before(func(ResponseWriter) { + result += "foo" + }) + rw.Before(func(ResponseWriter) { + result += "bar" + }) + + rw.WriteHeader(http.StatusNotFound) + + expect(t, rec.Code, rw.Status()) + expect(t, rec.Body.String(), "") + expect(t, rw.Status(), http.StatusNotFound) + expect(t, rw.Size(), 0) + expect(t, result, "barfoo") +} + +func TestResponseWriterHijack(t *testing.T) { + hijackable := newHijackableResponse() + rw := NewResponseWriter(hijackable) + hijacker, ok := rw.(http.Hijacker) + expect(t, ok, true) + _, _, err := hijacker.Hijack() + if err != nil { + t.Error(err) + } + expect(t, hijackable.Hijacked, true) +} + +func TestResponseWriteHijackNotOK(t *testing.T) { + hijackable := new(http.ResponseWriter) + rw := NewResponseWriter(*hijackable) + hijacker, ok := rw.(http.Hijacker) + expect(t, ok, true) + _, _, err := hijacker.Hijack() + + refute(t, err, nil) +} + +func TestResponseWriterCloseNotify(t *testing.T) { + rec := newCloseNotifyingRecorder() + rw := NewResponseWriter(rec) + closed := false + notifier := rw.(http.CloseNotifier).CloseNotify() + rec.close() + select { + case <-notifier: + closed = true + case <-time.After(time.Second): + } + expect(t, closed, true) +} + +func TestResponseWriterFlusher(t *testing.T) { + rec := httptest.NewRecorder() + rw := NewResponseWriter(rec) + + _, ok := rw.(http.Flusher) + expect(t, ok, true) +} diff --git a/vendor/src/github.com/codegangsta/negroni/static.go b/vendor/src/github.com/codegangsta/negroni/static.go new file mode 100644 index 0000000..c5af4e6 --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/static.go @@ -0,0 +1,84 @@ +package negroni + +import ( + "net/http" + "path" + "strings" +) + +// Static is a middleware handler that serves static files in the given directory/filesystem. +type Static struct { + // Dir is the directory to serve static files from + Dir http.FileSystem + // Prefix is the optional prefix used to serve the static directory content + Prefix string + // IndexFile defines which file to serve as index if it exists. + IndexFile string +} + +// NewStatic returns a new instance of Static +func NewStatic(directory http.FileSystem) *Static { + return &Static{ + Dir: directory, + Prefix: "", + IndexFile: "index.html", + } +} + +func (s *Static) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + if r.Method != "GET" && r.Method != "HEAD" { + next(rw, r) + return + } + file := r.URL.Path + // if we have a prefix, filter requests by stripping the prefix + if s.Prefix != "" { + if !strings.HasPrefix(file, s.Prefix) { + next(rw, r) + return + } + file = file[len(s.Prefix):] + if file != "" && file[0] != '/' { + next(rw, r) + return + } + } + f, err := s.Dir.Open(file) + if err != nil { + // discard the error? + next(rw, r) + return + } + defer f.Close() + + fi, err := f.Stat() + if err != nil { + next(rw, r) + return + } + + // try to serve index file + if fi.IsDir() { + // redirect if missing trailing slash + if !strings.HasSuffix(r.URL.Path, "/") { + http.Redirect(rw, r, r.URL.Path+"/", http.StatusFound) + return + } + + file = path.Join(file, s.IndexFile) + f, err = s.Dir.Open(file) + if err != nil { + next(rw, r) + return + } + defer f.Close() + + fi, err = f.Stat() + if err != nil || fi.IsDir() { + next(rw, r) + return + } + } + + http.ServeContent(rw, r, file, fi.ModTime(), f) +} diff --git a/vendor/src/github.com/codegangsta/negroni/static_test.go b/vendor/src/github.com/codegangsta/negroni/static_test.go new file mode 100644 index 0000000..637cfcd --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/static_test.go @@ -0,0 +1,113 @@ +package negroni + +import ( + "bytes" + "net/http" + "net/http/httptest" + "testing" +) + +func TestStatic(t *testing.T) { + response := httptest.NewRecorder() + response.Body = new(bytes.Buffer) + + n := New() + n.Use(NewStatic(http.Dir("."))) + + req, err := http.NewRequest("GET", "http://localhost:3000/negroni.go", nil) + if err != nil { + t.Error(err) + } + n.ServeHTTP(response, req) + expect(t, response.Code, http.StatusOK) + expect(t, response.Header().Get("Expires"), "") + if response.Body.Len() == 0 { + t.Errorf("Got empty body for GET request") + } +} + +func TestStaticHead(t *testing.T) { + response := httptest.NewRecorder() + response.Body = new(bytes.Buffer) + + n := New() + n.Use(NewStatic(http.Dir("."))) + n.UseHandler(http.NotFoundHandler()) + + req, err := http.NewRequest("HEAD", "http://localhost:3000/negroni.go", nil) + if err != nil { + t.Error(err) + } + + n.ServeHTTP(response, req) + expect(t, response.Code, http.StatusOK) + if response.Body.Len() != 0 { + t.Errorf("Got non-empty body for HEAD request") + } +} + +func TestStaticAsPost(t *testing.T) { + response := httptest.NewRecorder() + + n := New() + n.Use(NewStatic(http.Dir("."))) + n.UseHandler(http.NotFoundHandler()) + + req, err := http.NewRequest("POST", "http://localhost:3000/negroni.go", nil) + if err != nil { + t.Error(err) + } + + n.ServeHTTP(response, req) + expect(t, response.Code, http.StatusNotFound) +} + +func TestStaticBadDir(t *testing.T) { + response := httptest.NewRecorder() + + n := Classic() + n.UseHandler(http.NotFoundHandler()) + + req, err := http.NewRequest("GET", "http://localhost:3000/negroni.go", nil) + if err != nil { + t.Error(err) + } + + n.ServeHTTP(response, req) + refute(t, response.Code, http.StatusOK) +} + +func TestStaticOptionsServeIndex(t *testing.T) { + response := httptest.NewRecorder() + + n := New() + s := NewStatic(http.Dir(".")) + s.IndexFile = "negroni.go" + n.Use(s) + + req, err := http.NewRequest("GET", "http://localhost:3000/", nil) + if err != nil { + t.Error(err) + } + + n.ServeHTTP(response, req) + expect(t, response.Code, http.StatusOK) +} + +func TestStaticOptionsPrefix(t *testing.T) { + response := httptest.NewRecorder() + + n := New() + s := NewStatic(http.Dir(".")) + s.Prefix = "/public" + n.Use(s) + + // Check file content behaviour + req, err := http.NewRequest("GET", "http://localhost:3000/public/negroni.go", nil) + if err != nil { + t.Error(err) + } + + n.ServeHTTP(response, req) + expect(t, response.Code, http.StatusOK) +} diff --git a/vendor/src/github.com/codegangsta/negroni/translations/README_pt_br.md b/vendor/src/github.com/codegangsta/negroni/translations/README_pt_br.md new file mode 100644 index 0000000..d5b02fa --- /dev/null +++ b/vendor/src/github.com/codegangsta/negroni/translations/README_pt_br.md @@ -0,0 +1,170 @@ +# Negroni [![GoDoc](https://godoc.org/github.com/codegangsta/negroni?status.svg)](http://godoc.org/github.com/codegangsta/negroni) [![wercker status](https://app.wercker.com/status/13688a4a94b82d84a0b8d038c4965b61/s "wercker status")](https://app.wercker.com/project/bykey/13688a4a94b82d84a0b8d038c4965b61) + +Negroni é uma abordagem idiomática para middleware web em Go. É pequeno, não intrusivo, e incentiva uso da biblioteca `net/http`. + +Se gosta da idéia do [Martini](http://github.com/go-martini/martini), mas acha que contém muita mágica, então Negroni é ideal. + +## Começando + +Depois de instalar Go e definir seu [GOPATH](http://golang.org/doc/code.html#GOPATH), criar seu primeirto arquivo `.go`. Iremos chamá-lo `server.go`. + +~~~ go +package main + +import ( + "github.com/codegangsta/negroni" + "net/http" + "fmt" +) + +func main() { + mux := http.NewServeMux() + mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + fmt.Fprintf(w, "Welcome to the home page!") + }) + + n := negroni.Classic() + n.UseHandler(mux) + n.Run(":3000") +} +~~~ + +Depois instale o pacote Negroni (**go 1.1** ou superior) +~~~ +go get github.com/codegangsta/negroni +~~~ + +Depois execute seu servidor: +~~~ +go run server.go +~~~ + +Agora terá um servidor web Go net/http rodando em `localhost:3000`. + +## Precisa de Ajuda? +Se você tem uma pergunta ou pedido de recurso,[go ask the mailing list](https://groups.google.com/forum/#!forum/negroni-users). O Github issues para o Negroni será usado exclusivamente para Reportar bugs e pull requests. + +## Negroni é um Framework? +Negroni **não** é a framework. É uma biblioteca que é desenhada para trabalhar diretamente com net/http. + +## Roteamento? +Negroni é TSPR(Traga seu próprio Roteamento). A comunidade Go já tem um grande número de roteadores http disponíveis, Negroni tenta rodar bem com todos eles pelo suporte total `net/http`/ Por exemplo, a integração com [Gorilla Mux](http://github.com/gorilla/mux) se parece com isso: + +~~~ go +router := mux.NewRouter() +router.HandleFunc("/", HomeHandler) + +n := negroni.New(Middleware1, Middleware2) +// Or use a middleware with the Use() function +n.Use(Middleware3) +// router goes last +n.UseHandler(router) + +n.Run(":3000") +~~~ + +## `negroni.Classic()` +`negroni.Classic()` fornece alguns middlewares padrão que são úteis para maioria das aplicações: + +* `negroni.Recovery` - Panic Recovery Middleware. +* `negroni.Logging` - Request/Response Logging Middleware. +* `negroni.Static` - Static File serving under the "public" directory. + +Isso torna muito fácil começar com alguns recursos úteis do Negroni. + +## Handlers +Negroni fornece um middleware de fluxo bidirecional. Isso é feito através da interface `negroni.Handler`: + +~~~ go +type Handler interface { + ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) +} +~~~ + +Se um middleware não tenha escrito o ResponseWriter, ele deve chamar a próxima `http.HandlerFunc` na cadeia para produzir o próximo handler middleware. Isso pode ser usado muito bem: + +~~~ go +func MyMiddleware(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) { + // do some stuff before + next(rw, r) + // do some stuff after +} +~~~ + +E pode mapear isso para a cadeia de handler com a função `Use`: + +~~~ go +n := negroni.New() +n.Use(negroni.HandlerFunc(MyMiddleware)) +~~~ + +Você também pode mapear `http.Handler` antigos: + +~~~ go +n := negroni.New() + +mux := http.NewServeMux() +// map your routes + +n.UseHandler(mux) + +n.Run(":3000") +~~~ + +## `Run()` +Negroni tem uma função de conveniência chamada `Run`. `Run` pega um endereço de string idêntico para [http.ListenAndServe](http://golang.org/pkg/net/http#ListenAndServe). + +~~~ go +n := negroni.Classic() +// ... +log.Fatal(http.ListenAndServe(":8080", n)) +~~~ + +## Middleware para Rotas Específicas +Se você tem um grupo de rota com rotas que precisam ser executadas por um middleware específico, pode simplesmente criar uma nova instância de Negroni e usar no seu Manipulador de rota. + +~~~ go +router := mux.NewRouter() +adminRoutes := mux.NewRouter() +// add admin routes here + +// Criar um middleware negroni para admin +router.Handle("/admin", negroni.New( + Middleware1, + Middleware2, + negroni.Wrap(adminRoutes), +)) +~~~ + +## Middleware de Terceiros + +Aqui está uma lista atual de Middleware Compatíveis com Negroni. Sinta se livre para mandar um PR vinculando seu middleware se construiu um: + + +| Middleware | Autor | Descrição | +| -----------|--------|-------------| +| [Graceful](https://github.com/stretchr/graceful) | [Tyler Bunnell](https://github.com/tylerb) | Graceful HTTP Shutdown | +| [secure](https://github.com/unrolled/secure) | [Cory Jacobsen](https://github.com/unrolled) | Implementa rapidamente itens de segurança.| +| [binding](https://github.com/mholt/binding) | [Matt Holt](https://github.com/mholt) | Handler para mapeamento/validação de um request a estrutura. | +| [logrus](https://github.com/meatballhat/negroni-logrus) | [Dan Buch](https://github.com/meatballhat) | Logrus-based logger | +| [render](https://github.com/unrolled/render) | [Cory Jacobsen](https://github.com/unrolled) | Pacote para renderizar JSON, XML, e templates HTML. | +| [gorelic](https://github.com/jingweno/negroni-gorelic) | [Jingwen Owen Ou](https://github.com/jingweno) | New Relic agent for Go runtime | +| [gzip](https://github.com/phyber/negroni-gzip) | [phyber](https://github.com/phyber) | Handler para adicionar compreção gzip para as requisições | +| [oauth2](https://github.com/goincremental/negroni-oauth2) | [David Bochenski](https://github.com/bochenski) | Handler que prove sistema de login OAuth 2.0 para aplicações Martini. Google Sign-in, Facebook Connect e Github login são suportados. | +| [sessions](https://github.com/goincremental/negroni-sessions) | [David Bochenski](https://github.com/bochenski) | Handler que provê o serviço de sessão. | +| [permissions](https://github.com/xyproto/permissions) | [Alexander Rødseth](https://github.com/xyproto) | Cookies, usuários e permissões. | +| [onthefly](https://github.com/xyproto/onthefly) | [Alexander Rødseth](https://github.com/xyproto) | Pacote para gerar TinySVG, HTML e CSS em tempo real. | + +## Exemplos +[Alexander Rødseth](https://github.com/xyproto) criou [mooseware](https://github.com/xyproto/mooseware), uma estrutura para escrever um handler middleware Negroni. + +## Servidor com autoreload? +[gin](https://github.com/codegangsta/gin) e [fresh](https://github.com/pilu/fresh) são aplicativos para autoreload do Negroni. + +## Leitura Essencial para Iniciantes em Go & Negroni +* [Usando um contexto para passar informação de um middleware para o manipulador final](http://elithrar.github.io/article/map-string-interface/) +* [Entendendo middleware](http://mattstauffer.co/blog/laravel-5.0-middleware-replacing-filters) + + +## Sobre +Negroni é obsessivamente desenhado por ninguém menos que [Code Gangsta](http://codegangsta.io/)