1
0
mirror of https://github.com/labstack/echo.git synced 2025-06-06 23:46:16 +02:00
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2016-04-02 14:19:39 -07:00
parent be5148ae27
commit b5d6c05101
22 changed files with 266 additions and 300 deletions

View File

@ -50,13 +50,6 @@ import (
"github.com/labstack/echo/middleware" "github.com/labstack/echo/middleware"
) )
// Handler
func hello() echo.HandlerFunc {
return func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!\n")
}
}
func main() { func main() {
// Echo instance // Echo instance
e := echo.New() e := echo.New()
@ -65,8 +58,10 @@ func main() {
e.Use(middleware.Logger()) e.Use(middleware.Logger())
e.Use(middleware.Recover()) e.Use(middleware.Recover())
// Routes // Route => handler
e.Get("/", hello()) e.Get("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!\n")
})
// Start server // Start server
e.Run(standard.New(":1323")) e.Run(standard.New(":1323"))

View File

@ -156,7 +156,7 @@ type (
pvalues []string pvalues []string
query url.Values query url.Values
store store store store
handler Handler handler HandlerFunc
echo *Echo echo *Echo
} }
@ -204,7 +204,7 @@ func (c *context) Value(key interface{}) interface{} {
} }
func (c *context) Handle(ctx Context) error { func (c *context) Handle(ctx Context) error {
return c.handler.Handle(ctx) return c.handler(ctx)
} }
func (c *context) Request() engine.Request { func (c *context) Request() engine.Request {

124
echo.go
View File

@ -62,9 +62,9 @@ type (
// Echo is the top-level framework instance. // Echo is the top-level framework instance.
Echo struct { Echo struct {
prefix string prefix string
middleware []Middleware middleware []MiddlewareFunc
head Handler head HandlerFunc
pristineHead Handler pristineHead HandlerFunc
maxParam *int maxParam *int
notFoundHandler HandlerFunc notFoundHandler HandlerFunc
httpErrorHandler HTTPErrorHandler httpErrorHandler HTTPErrorHandler
@ -89,24 +89,10 @@ type (
Message string Message string
} }
// Middleware defines an interface for middleware via `Handle(Handler) Handler` // MiddlewareFunc defines a function to process middleware.
// function. MiddlewareFunc func(HandlerFunc) HandlerFunc
Middleware interface {
Handle(Handler) Handler
}
// MiddlewareFunc is an adapter to allow the use of `func(Handler) Handler` as // HandlerFunc defines a function to server HTTP requests.
// middleware.
MiddlewareFunc func(Handler) Handler
// Handler defines an interface to server HTTP requests via `Handle(Context)`
// function.
Handler interface {
Handle(Context) error
}
// HandlerFunc is an adapter to allow the use of `func(Context)` as an HTTP
// handler.
HandlerFunc func(Context) error HandlerFunc func(Context) error
// HTTPErrorHandler is a centralized HTTP error handler. // HTTPErrorHandler is a centralized HTTP error handler.
@ -212,13 +198,13 @@ var (
// Error handlers // Error handlers
var ( var (
notFoundHandler = HandlerFunc(func(c Context) error { notFoundHandler = func(c Context) error {
return ErrNotFound return ErrNotFound
}) }
methodNotAllowedHandler = HandlerFunc(func(c Context) error { methodNotAllowedHandler = func(c Context) error {
return ErrMethodNotAllowed return ErrMethodNotAllowed
}) }
) )
// New creates an instance of Echo. // New creates an instance of Echo.
@ -228,10 +214,10 @@ func New() (e *Echo) {
return NewContext(nil, nil, e) return NewContext(nil, nil, e)
} }
e.router = NewRouter(e) e.router = NewRouter(e)
e.middleware = []Middleware{e.router} e.middleware = []MiddlewareFunc{e.router.Process}
e.head = HandlerFunc(func(c Context) error { e.head = func(c Context) error {
return c.Handle(c) return c.Handle(c)
}) }
e.pristineHead = e.head e.pristineHead = e.head
e.chainMiddleware() e.chainMiddleware()
@ -244,16 +230,6 @@ func New() (e *Echo) {
return return
} }
// Handle chains middleware.
func (f MiddlewareFunc) Handle(h Handler) Handler {
return f(h)
}
// Handle serves HTTP request.
func (f HandlerFunc) Handle(c Context) error {
return f(c)
}
// Router returns router. // Router returns router.
func (e *Echo) Router() *Router { func (e *Echo) Router() *Router {
return e.router return e.router
@ -323,13 +299,13 @@ func (e *Echo) Debug() bool {
} }
// Pre adds middleware to the chain which is run before router. // Pre adds middleware to the chain which is run before router.
func (e *Echo) Pre(middleware ...Middleware) { func (e *Echo) Pre(middleware ...MiddlewareFunc) {
e.middleware = append(middleware, e.middleware...) e.middleware = append(middleware, e.middleware...)
e.chainMiddleware() e.chainMiddleware()
} }
// Use adds middleware to the chain which is run after router. // Use adds middleware to the chain which is run after router.
func (e *Echo) Use(middleware ...Middleware) { func (e *Echo) Use(middleware ...MiddlewareFunc) {
e.middleware = append(e.middleware, middleware...) e.middleware = append(e.middleware, middleware...)
e.chainMiddleware() e.chainMiddleware()
} }
@ -337,67 +313,67 @@ func (e *Echo) Use(middleware ...Middleware) {
func (e *Echo) chainMiddleware() { func (e *Echo) chainMiddleware() {
e.head = e.pristineHead e.head = e.pristineHead
for i := len(e.middleware) - 1; i >= 0; i-- { for i := len(e.middleware) - 1; i >= 0; i-- {
e.head = e.middleware[i].Handle(e.head) e.head = e.middleware[i](e.head)
} }
} }
// Connect registers a new CONNECT route for a path with matching handler in the // Connect registers a new CONNECT route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Connect(path string, h Handler, m ...Middleware) { func (e *Echo) Connect(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(CONNECT, path, h, m...) e.add(CONNECT, path, h, m...)
} }
// Delete registers a new DELETE route for a path with matching handler in the router // Delete registers a new DELETE route for a path with matching handler in the router
// with optional route-level middleware. // with optional route-level middleware.
func (e *Echo) Delete(path string, h Handler, m ...Middleware) { func (e *Echo) Delete(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(DELETE, path, h, m...) e.add(DELETE, path, h, m...)
} }
// Get registers a new GET route for a path with matching handler in the router // Get registers a new GET route for a path with matching handler in the router
// with optional route-level middleware. // with optional route-level middleware.
func (e *Echo) Get(path string, h Handler, m ...Middleware) { func (e *Echo) Get(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(GET, path, h, m...) e.add(GET, path, h, m...)
} }
// Head registers a new HEAD route for a path with matching handler in the // Head registers a new HEAD route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Head(path string, h Handler, m ...Middleware) { func (e *Echo) Head(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(HEAD, path, h, m...) e.add(HEAD, path, h, m...)
} }
// Options registers a new OPTIONS route for a path with matching handler in the // Options registers a new OPTIONS route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Options(path string, h Handler, m ...Middleware) { func (e *Echo) Options(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(OPTIONS, path, h, m...) e.add(OPTIONS, path, h, m...)
} }
// Patch registers a new PATCH route for a path with matching handler in the // Patch registers a new PATCH route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Patch(path string, h Handler, m ...Middleware) { func (e *Echo) Patch(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(PATCH, path, h, m...) e.add(PATCH, path, h, m...)
} }
// Post registers a new POST route for a path with matching handler in the // Post registers a new POST route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Post(path string, h Handler, m ...Middleware) { func (e *Echo) Post(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(POST, path, h, m...) e.add(POST, path, h, m...)
} }
// Put registers a new PUT route for a path with matching handler in the // Put registers a new PUT route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Put(path string, h Handler, m ...Middleware) { func (e *Echo) Put(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(PUT, path, h, m...) e.add(PUT, path, h, m...)
} }
// Trace registers a new TRACE route for a path with matching handler in the // Trace registers a new TRACE route for a path with matching handler in the
// router with optional route-level middleware. // router with optional route-level middleware.
func (e *Echo) Trace(path string, h Handler, m ...Middleware) { func (e *Echo) Trace(path string, h HandlerFunc, m ...MiddlewareFunc) {
e.add(TRACE, path, h, m...) e.add(TRACE, path, h, m...)
} }
// Any registers a new route for all HTTP methods and path with matching handler // Any registers a new route for all HTTP methods and path with matching handler
// in the router with optional route-level middleware. // in the router with optional route-level middleware.
func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) { func (e *Echo) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
for _, m := range methods { for _, m := range methods {
e.add(m, path, handler, middleware...) e.add(m, path, handler, middleware...)
} }
@ -405,7 +381,7 @@ func (e *Echo) Any(path string, handler Handler, middleware ...Middleware) {
// Match registers a new route for multiple HTTP methods and path with matching // Match registers a new route for multiple HTTP methods and path with matching
// handler in the router with optional route-level middleware. // handler in the router with optional route-level middleware.
func (e *Echo) Match(methods []string, path string, handler Handler, middleware ...Middleware) { func (e *Echo) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
for _, m := range methods { for _, m := range methods {
e.add(m, path, handler, middleware...) e.add(m, path, handler, middleware...)
} }
@ -413,28 +389,28 @@ func (e *Echo) Match(methods []string, path string, handler Handler, middleware
// Static serves files from provided `root` directory for `/<prefix>*` HTTP path. // Static serves files from provided `root` directory for `/<prefix>*` HTTP path.
func (e *Echo) Static(prefix, root string) { func (e *Echo) Static(prefix, root string) {
e.Get(prefix+"*", HandlerFunc(func(c Context) error { e.Get(prefix+"*", func(c Context) error {
return c.File(path.Join(root, c.P(0))) // Param `_` return c.File(path.Join(root, c.P(0))) // Param `_`
})) })
} }
// File serves provided file for `/<path>` HTTP path. // File serves provided file for `/<path>` HTTP path.
func (e *Echo) File(path, file string) { func (e *Echo) File(path, file string) {
e.Get(path, HandlerFunc(func(c Context) error { e.Get(path, func(c Context) error {
return c.File(file) return c.File(file)
})) })
} }
func (e *Echo) add(method, path string, handler Handler, middleware ...Middleware) { func (e *Echo) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
name := handlerName(handler) name := handlerName(handler)
e.router.Add(method, path, HandlerFunc(func(c Context) error { e.router.Add(method, path, func(c Context) error {
h := handler h := handler
// Chain middleware // Chain middleware
for i := len(middleware) - 1; i >= 0; i-- { for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i].Handle(h) h = middleware[i](h)
} }
return h.Handle(c) return h(c)
}), e) }, e)
r := Route{ r := Route{
Method: method, Method: method,
Path: path, Path: path,
@ -444,18 +420,18 @@ func (e *Echo) add(method, path string, handler Handler, middleware ...Middlewar
} }
// Group creates a new router group with prefix and optional group-level middleware. // Group creates a new router group with prefix and optional group-level middleware.
func (e *Echo) Group(prefix string, m ...Middleware) (g *Group) { func (e *Echo) Group(prefix string, m ...MiddlewareFunc) (g *Group) {
g = &Group{prefix: prefix, echo: e} g = &Group{prefix: prefix, echo: e}
g.Use(m...) g.Use(m...)
// Dummy handler so group can be used with static middleware. // Dummy handler so group can be used with static middleware.
g.Get("", HandlerFunc(func(c Context) error { g.Get("", func(c Context) error {
return c.NoContent(http.StatusNotFound) return c.NoContent(http.StatusNotFound)
})) })
return return
} }
// URI generates a URI from handler. // URI generates a URI from handler.
func (e *Echo) URI(handler Handler, params ...interface{}) string { func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string {
uri := new(bytes.Buffer) uri := new(bytes.Buffer)
ln := len(params) ln := len(params)
n := 0 n := 0
@ -480,7 +456,7 @@ func (e *Echo) URI(handler Handler, params ...interface{}) string {
} }
// URL is an alias for `URI` function. // URL is an alias for `URI` function.
func (e *Echo) URL(h Handler, params ...interface{}) string { func (e *Echo) URL(h HandlerFunc, params ...interface{}) string {
return e.URI(h, params...) return e.URI(h, params...)
} }
@ -506,7 +482,7 @@ func (e *Echo) ServeHTTP(rq engine.Request, rs engine.Response) {
c.Reset(rq, rs) c.Reset(rq, rs)
// Execute chain // Execute chain
if err := e.head.Handle(c); err != nil { if err := e.head(c); err != nil {
e.httpErrorHandler(err, c) e.httpErrorHandler(err, c)
} }
@ -551,19 +527,19 @@ func (binder) Bind(i interface{}, c Context) (err error) {
return return
} }
// WrapMiddleware wrap `echo.Handler` into `echo.MiddlewareFunc`. // WrapMiddleware wrap `echo.HandlerFunc` into `echo.MiddlewareFunc`.
func WrapMiddleware(h Handler) MiddlewareFunc { func WrapMiddleware(h HandlerFunc) MiddlewareFunc {
return func(next Handler) Handler { return func(next HandlerFunc) HandlerFunc {
return HandlerFunc(func(c Context) error { return func(c Context) error {
if err := h.Handle(c); err != nil { if err := h(c); err != nil {
return err return err
} }
return next.Handle(c) return next(c)
}) }
} }
} }
func handlerName(h Handler) string { func handlerName(h HandlerFunc) string {
t := reflect.ValueOf(h).Type() t := reflect.ValueOf(h).Type()
if t.Kind() == reflect.Func { if t.Kind() == reflect.Func {
return runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name() return runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()

View File

@ -83,31 +83,31 @@ func TestEchoMiddleware(t *testing.T) {
e := New() e := New()
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
e.Pre(WrapMiddleware(HandlerFunc(func(c Context) error { e.Pre(WrapMiddleware(func(c Context) error {
assert.Empty(t, c.Path()) assert.Empty(t, c.Path())
buf.WriteString("-1") buf.WriteString("-1")
return nil return nil
}))) }))
e.Use(WrapMiddleware(HandlerFunc(func(c Context) error { e.Use(WrapMiddleware(func(c Context) error {
buf.WriteString("1") buf.WriteString("1")
return nil return nil
}))) }))
e.Use(WrapMiddleware(HandlerFunc(func(c Context) error { e.Use(WrapMiddleware(func(c Context) error {
buf.WriteString("2") buf.WriteString("2")
return nil return nil
}))) }))
e.Use(WrapMiddleware(HandlerFunc(func(c Context) error { e.Use(WrapMiddleware(func(c Context) error {
buf.WriteString("3") buf.WriteString("3")
return nil return nil
}))) }))
// Route // Route
e.Get("/", HandlerFunc(func(c Context) error { e.Get("/", func(c Context) error {
return c.String(http.StatusOK, "OK") return c.String(http.StatusOK, "OK")
})) })
c, b := request(GET, "/", e) c, b := request(GET, "/", e)
assert.Equal(t, "-1123", buf.String()) assert.Equal(t, "-1123", buf.String())
@ -117,9 +117,9 @@ func TestEchoMiddleware(t *testing.T) {
func TestEchoMiddlewareError(t *testing.T) { func TestEchoMiddlewareError(t *testing.T) {
e := New() e := New()
e.Use(WrapMiddleware(HandlerFunc(func(c Context) error { e.Use(WrapMiddleware(func(c Context) error {
return errors.New("error") return errors.New("error")
}))) }))
e.Get("/", notFoundHandler) e.Get("/", notFoundHandler)
c, _ := request(GET, "/", e) c, _ := request(GET, "/", e)
assert.Equal(t, http.StatusInternalServerError, c) assert.Equal(t, http.StatusInternalServerError, c)
@ -129,9 +129,9 @@ func TestEchoHandler(t *testing.T) {
e := New() e := New()
// HandlerFunc // HandlerFunc
e.Get("/ok", HandlerFunc(func(c Context) error { e.Get("/ok", func(c Context) error {
return c.String(http.StatusOK, "OK") return c.String(http.StatusOK, "OK")
})) })
c, b := request(GET, "/ok", e) c, b := request(GET, "/ok", e)
assert.Equal(t, http.StatusOK, c) assert.Equal(t, http.StatusOK, c)
@ -185,23 +185,23 @@ func TestEchoTrace(t *testing.T) {
func TestEchoAny(t *testing.T) { // JFC func TestEchoAny(t *testing.T) { // JFC
e := New() e := New()
e.Any("/", HandlerFunc(func(c Context) error { e.Any("/", func(c Context) error {
return c.String(http.StatusOK, "Any") return c.String(http.StatusOK, "Any")
})) })
} }
func TestEchoMatch(t *testing.T) { // JFC func TestEchoMatch(t *testing.T) { // JFC
e := New() e := New()
e.Match([]string{GET, POST}, "/", HandlerFunc(func(c Context) error { e.Match([]string{GET, POST}, "/", func(c Context) error {
return c.String(http.StatusOK, "Match") return c.String(http.StatusOK, "Match")
})) })
} }
func TestEchoURL(t *testing.T) { func TestEchoURL(t *testing.T) {
e := New() e := New()
static := HandlerFunc(func(Context) error { return nil }) static := func(Context) error { return nil }
getUser := HandlerFunc(func(Context) error { return nil }) getUser := func(Context) error { return nil }
getFile := HandlerFunc(func(Context) error { return nil }) getFile := func(Context) error { return nil }
e.Get("/static/file", static) e.Get("/static/file", static)
e.Get("/users/:id", getUser) e.Get("/users/:id", getUser)
@ -224,9 +224,9 @@ func TestEchoRoutes(t *testing.T) {
{POST, "/repos/:owner/:repo/git/tags", ""}, {POST, "/repos/:owner/:repo/git/tags", ""},
} }
for _, r := range routes { for _, r := range routes {
e.add(r.Method, r.Path, HandlerFunc(func(c Context) error { e.add(r.Method, r.Path, func(c Context) error {
return c.String(http.StatusOK, "OK") return c.String(http.StatusOK, "OK")
})) })
} }
for i, r := range e.Routes() { for i, r := range e.Routes() {
@ -238,15 +238,15 @@ func TestEchoRoutes(t *testing.T) {
func TestEchoGroup(t *testing.T) { func TestEchoGroup(t *testing.T) {
e := New() e := New()
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
e.Use(MiddlewareFunc(func(h Handler) Handler { e.Use(MiddlewareFunc(func(h HandlerFunc) HandlerFunc {
return HandlerFunc(func(c Context) error { return func(c Context) error {
buf.WriteString("0") buf.WriteString("0")
return h.Handle(c) return h(c)
}) }
})) }))
h := HandlerFunc(func(c Context) error { h := func(c Context) error {
return c.NoContent(http.StatusOK) return c.NoContent(http.StatusOK)
}) }
//-------- //--------
// Routes // Routes
@ -256,24 +256,23 @@ func TestEchoGroup(t *testing.T) {
// Group // Group
g1 := e.Group("/group1") g1 := e.Group("/group1")
g1.Use(WrapMiddleware(HandlerFunc(func(c Context) error { g1.Use(WrapMiddleware(func(c Context) error {
buf.WriteString("1") buf.WriteString("1")
return h.Handle(c) return h(c)
}))
})))
g1.Get("", h) g1.Get("", h)
// Nested groups with middleware // Nested groups with middleware
g2 := e.Group("/group2") g2 := e.Group("/group2")
g2.Use(WrapMiddleware(HandlerFunc(func(c Context) error { g2.Use(WrapMiddleware(func(c Context) error {
buf.WriteString("2") buf.WriteString("2")
return nil return nil
}))) }))
g3 := g2.Group("/group3") g3 := g2.Group("/group3")
g3.Use(WrapMiddleware(HandlerFunc(func(c Context) error { g3.Use(WrapMiddleware(func(c Context) error {
buf.WriteString("3") buf.WriteString("3")
return nil return nil
}))) }))
g3.Get("", h) g3.Get("", h)
request(GET, "/users", e) request(GET, "/users", e)
@ -298,9 +297,9 @@ func TestEchoNotFound(t *testing.T) {
func TestEchoMethodNotAllowed(t *testing.T) { func TestEchoMethodNotAllowed(t *testing.T) {
e := New() e := New()
e.Get("/", HandlerFunc(func(c Context) error { e.Get("/", func(c Context) error {
return c.String(http.StatusOK, "Echo!") return c.String(http.StatusOK, "Echo!")
})) })
rq := test.NewRequest(POST, "/", nil) rq := test.NewRequest(POST, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
e.ServeHTTP(rq, rec) e.ServeHTTP(rq, rec)
@ -317,9 +316,9 @@ func TestEchoHTTPError(t *testing.T) {
func testMethod(t *testing.T, method, path string, e *Echo) { func testMethod(t *testing.T, method, path string, e *Echo) {
m := fmt.Sprintf("%c%s", method[0], strings.ToLower(method[1:])) m := fmt.Sprintf("%c%s", method[0], strings.ToLower(method[1:]))
p := reflect.ValueOf(path) p := reflect.ValueOf(path)
h := reflect.ValueOf(HandlerFunc(func(c Context) error { h := reflect.ValueOf(func(c Context) error {
return c.String(http.StatusOK, method) return c.String(http.StatusOK, method)
})) })
i := interface{}(e) i := interface{}(e)
reflect.ValueOf(i).MethodByName(m).Call([]reflect.Value{p, h}) reflect.ValueOf(i).MethodByName(m).Call([]reflect.Value{p, h})
_, body := request(method, path, e) _, body := request(method, path, e)

View File

@ -162,15 +162,15 @@ func WrapHandler(h fasthttp.RequestHandler) echo.HandlerFunc {
// WrapMiddleware wraps `fasthttp.RequestHandler` into `echo.MiddlewareFunc` // WrapMiddleware wraps `fasthttp.RequestHandler` into `echo.MiddlewareFunc`
func WrapMiddleware(h fasthttp.RequestHandler) echo.MiddlewareFunc { func WrapMiddleware(h fasthttp.RequestHandler) echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
rq := c.Request().(*Request) rq := c.Request().(*Request)
rs := c.Response().(*Response) rs := c.Response().(*Response)
ctx := rq.RequestCtx ctx := rq.RequestCtx
h(ctx) h(ctx)
rs.status = ctx.Response.StatusCode() rs.status = ctx.Response.StatusCode()
rs.size = int64(ctx.Response.Header.ContentLength()) rs.size = int64(ctx.Response.Header.ContentLength())
return next.Handle(c) return next(c)
}) }
} }
} }

View File

@ -156,14 +156,14 @@ func WrapHandler(h http.Handler) echo.HandlerFunc {
// WrapMiddleware wraps `func(http.Handler) http.Handler` into `echo.MiddlewareFunc` // WrapMiddleware wraps `func(http.Handler) http.Handler` into `echo.MiddlewareFunc`
func WrapMiddleware(m func(http.Handler) http.Handler) echo.MiddlewareFunc { func WrapMiddleware(m func(http.Handler) http.Handler) echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) (err error) { return func(c echo.Context) (err error) {
rq := c.Request().(*Request) rq := c.Request().(*Request)
rs := c.Response().(*Response) rs := c.Response().(*Response)
m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err = next.Handle(c) err = next(c)
})).ServeHTTP(rs.ResponseWriter, rq.Request) })).ServeHTTP(rs.ResponseWriter, rq.Request)
return return
}) }
} }
} }

10
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: 44dfc8aaffca5078e71afdb209a0ef0a359a35f69fb98c7b6a2fb87a5a70e757 hash: 44dfc8aaffca5078e71afdb209a0ef0a359a35f69fb98c7b6a2fb87a5a70e757
updated: 2016-04-01T08:48:26.453457926-07:00 updated: 2016-04-02T13:40:33.226488832-07:00
imports: imports:
- name: github.com/klauspost/compress - name: github.com/klauspost/compress
version: 9d711f4445beb7f6488148ce04e3b4dc6e72242d version: 9d711f4445beb7f6488148ce04e3b4dc6e72242d
@ -11,10 +11,6 @@ imports:
version: 09cded8978dc9e80714c4d85b0322337b0a1e5e0 version: 09cded8978dc9e80714c4d85b0322337b0a1e5e0
- name: github.com/klauspost/crc32 - name: github.com/klauspost/crc32
version: 19b0b332c9e4516a6370a0456e6182c3b5036720 version: 19b0b332c9e4516a6370a0456e6182c3b5036720
- name: github.com/labstack/echo
version: 11134134413a234260d4e9c501803c3cc6c874d1
subpackages:
- engine
- name: github.com/labstack/gommon - name: github.com/labstack/gommon
version: f4ba73f8bcf88df1524069c117f7878cf530ee4e version: f4ba73f8bcf88df1524069c117f7878cf530ee4e
subpackages: subpackages:
@ -29,7 +25,7 @@ imports:
subpackages: subpackages:
- assert - assert
- name: github.com/valyala/fasthttp - name: github.com/valyala/fasthttp
version: ca21b21eba267eac4489fb6b42260129727c4a1b version: 8ae2d3e53c26ff32a2da8ad0c974b29cea0b0c7d
- name: github.com/valyala/fasttemplate - name: github.com/valyala/fasttemplate
version: 3b874956e03f1636d171bda64b130f9135f42cff version: 3b874956e03f1636d171bda64b130f9135f42cff
- name: golang.org/x/net - name: golang.org/x/net
@ -38,7 +34,7 @@ imports:
- context - context
- websocket - websocket
- name: golang.org/x/sys - name: golang.org/x/sys
version: 320cb01ddbbf0473674c2585f9b6e245721de355 version: a60af9cbbc6ab800af4f2be864a31f423a0ae1f2
subpackages: subpackages:
- unix - unix
devImports: [] devImports: []

View File

@ -6,94 +6,94 @@ type (
// from the parent echo instance while still inheriting from it. // from the parent echo instance while still inheriting from it.
Group struct { Group struct {
prefix string prefix string
middleware []Middleware middleware []MiddlewareFunc
echo *Echo echo *Echo
} }
) )
// Use implements `Echo#Use()` for sub-routes within the Group. // Use implements `Echo#Use()` for sub-routes within the Group.
func (g *Group) Use(m ...Middleware) { func (g *Group) Use(m ...MiddlewareFunc) {
g.middleware = append(g.middleware, m...) g.middleware = append(g.middleware, m...)
} }
// Connect implements `Echo#Connect()` for sub-routes within the Group. // Connect implements `Echo#Connect()` for sub-routes within the Group.
func (g *Group) Connect(path string, h Handler, m ...Middleware) { func (g *Group) Connect(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(CONNECT, path, h, m...) g.add(CONNECT, path, h, m...)
} }
// Delete implements `Echo#Delete()` for sub-routes within the Group. // Delete implements `Echo#Delete()` for sub-routes within the Group.
func (g *Group) Delete(path string, h Handler, m ...Middleware) { func (g *Group) Delete(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(DELETE, path, h, m...) g.add(DELETE, path, h, m...)
} }
// Get implements `Echo#Get()` for sub-routes within the Group. // Get implements `Echo#Get()` for sub-routes within the Group.
func (g *Group) Get(path string, h Handler, m ...Middleware) { func (g *Group) Get(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(GET, path, h, m...) g.add(GET, path, h, m...)
} }
// Head implements `Echo#Head()` for sub-routes within the Group. // Head implements `Echo#Head()` for sub-routes within the Group.
func (g *Group) Head(path string, h Handler, m ...Middleware) { func (g *Group) Head(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(HEAD, path, h, m...) g.add(HEAD, path, h, m...)
} }
// Options implements `Echo#Options()` for sub-routes within the Group. // Options implements `Echo#Options()` for sub-routes within the Group.
func (g *Group) Options(path string, h Handler, m ...Middleware) { func (g *Group) Options(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(OPTIONS, path, h, m...) g.add(OPTIONS, path, h, m...)
} }
// Patch implements `Echo#Patch()` for sub-routes within the Group. // Patch implements `Echo#Patch()` for sub-routes within the Group.
func (g *Group) Patch(path string, h Handler, m ...Middleware) { func (g *Group) Patch(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(PATCH, path, h, m...) g.add(PATCH, path, h, m...)
} }
// Post implements `Echo#Post()` for sub-routes within the Group. // Post implements `Echo#Post()` for sub-routes within the Group.
func (g *Group) Post(path string, h Handler, m ...Middleware) { func (g *Group) Post(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(POST, path, h, m...) g.add(POST, path, h, m...)
} }
// Put implements `Echo#Put()` for sub-routes within the Group. // Put implements `Echo#Put()` for sub-routes within the Group.
func (g *Group) Put(path string, h Handler, m ...Middleware) { func (g *Group) Put(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(PUT, path, h, m...) g.add(PUT, path, h, m...)
} }
// Trace implements `Echo#Trace()` for sub-routes within the Group. // Trace implements `Echo#Trace()` for sub-routes within the Group.
func (g *Group) Trace(path string, h Handler, m ...Middleware) { func (g *Group) Trace(path string, h HandlerFunc, m ...MiddlewareFunc) {
g.add(TRACE, path, h, m...) g.add(TRACE, path, h, m...)
} }
// Any implements `Echo#Any()` for sub-routes within the Group. // Any implements `Echo#Any()` for sub-routes within the Group.
func (g *Group) Any(path string, handler Handler, middleware ...Middleware) { func (g *Group) Any(path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
for _, m := range methods { for _, m := range methods {
g.add(m, path, handler, middleware...) g.add(m, path, handler, middleware...)
} }
} }
// Match implements `Echo#Match()` for sub-routes within the Group. // Match implements `Echo#Match()` for sub-routes within the Group.
func (g *Group) Match(methods []string, path string, handler Handler, middleware ...Middleware) { func (g *Group) Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
for _, m := range methods { for _, m := range methods {
g.add(m, path, handler, middleware...) g.add(m, path, handler, middleware...)
} }
} }
// Group creates a new sub-group with prefix and optional sub-group-level middleware. // Group creates a new sub-group with prefix and optional sub-group-level middleware.
func (g *Group) Group(prefix string, m ...Middleware) *Group { func (g *Group) Group(prefix string, m ...MiddlewareFunc) *Group {
m = append(g.middleware, m...) m = append(g.middleware, m...)
return g.echo.Group(g.prefix+prefix, m...) return g.echo.Group(g.prefix+prefix, m...)
} }
func (g *Group) add(method, path string, handler Handler, middleware ...Middleware) { func (g *Group) add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) {
path = g.prefix + path path = g.prefix + path
name := handlerName(handler) name := handlerName(handler)
middleware = append(g.middleware, middleware...) middleware = append(g.middleware, middleware...)
g.echo.router.Add(method, path, HandlerFunc(func(c Context) error { g.echo.router.Add(method, path, func(c Context) error {
h := handler h := handler
// Chain middleware // Chain middleware
for i := len(middleware) - 1; i >= 0; i-- { for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i].Handle(h) h = middleware[i](h)
} }
return h.Handle(c) return h(c)
}), g.echo) }, g.echo)
r := Route{ r := Route{
Method: method, Method: method,
Path: path, Path: path,

View File

@ -4,7 +4,7 @@ import "testing"
func TestGroup(t *testing.T) { func TestGroup(t *testing.T) {
g := New().Group("/group") g := New().Group("/group")
h := HandlerFunc(func(Context) error { return nil }) h := func(Context) error { return nil }
g.Connect("/", h) g.Connect("/", h)
g.Delete("/", h) g.Delete("/", h)
g.Get("/", h) g.Get("/", h)

View File

@ -39,8 +39,8 @@ func BasicAuth(f BasicAuthFunc) echo.MiddlewareFunc {
// BasicAuthFromConfig returns an HTTP basic auth middleware from config. // BasicAuthFromConfig returns an HTTP basic auth middleware from config.
// See `BasicAuth()`. // See `BasicAuth()`.
func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc { func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
auth := c.Request().Header().Get(echo.Authorization) auth := c.Request().Header().Get(echo.Authorization)
l := len(basic) l := len(basic)
@ -52,7 +52,7 @@ func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc {
if cred[i] == ':' { if cred[i] == ':' {
// Verify credentials // Verify credentials
if config.AuthFunc(cred[:i], cred[i+1:]) { if config.AuthFunc(cred[:i], cred[i+1:]) {
return next.Handle(c) return next(c)
} }
} }
} }
@ -60,6 +60,6 @@ func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc {
} }
c.Response().Header().Set(echo.WWWAuthenticate, basic+" realm=Restricted") c.Response().Header().Set(echo.WWWAuthenticate, basic+" realm=Restricted")
return echo.ErrUnauthorized return echo.ErrUnauthorized
}) }
} }
} }

View File

@ -21,14 +21,14 @@ func TestBasicAuth(t *testing.T) {
} }
return false return false
} }
h := BasicAuth(f)(echo.HandlerFunc(func(c echo.Context) error { h := BasicAuth(f)(func(c echo.Context) error {
return c.String(http.StatusOK, "test") return c.String(http.StatusOK, "test")
})) })
// Valid credentials // Valid credentials
auth := basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret")) auth := basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
rq.Header().Set(echo.Authorization, auth) rq.Header().Set(echo.Authorization, auth)
assert.NoError(t, h.Handle(c)) assert.NoError(t, h(c))
//--------------------- //---------------------
// Invalid credentials // Invalid credentials
@ -37,20 +37,20 @@ func TestBasicAuth(t *testing.T) {
// Incorrect password // Incorrect password
auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password")) auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password"))
rq.Header().Set(echo.Authorization, auth) rq.Header().Set(echo.Authorization, auth)
he := h.Handle(c).(*echo.HTTPError) he := h(c).(*echo.HTTPError)
assert.Equal(t, http.StatusUnauthorized, he.Code) assert.Equal(t, http.StatusUnauthorized, he.Code)
assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate)) assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
// Empty Authorization header // Empty Authorization header
rq.Header().Set(echo.Authorization, "") rq.Header().Set(echo.Authorization, "")
he = h.Handle(c).(*echo.HTTPError) he = h(c).(*echo.HTTPError)
assert.Equal(t, http.StatusUnauthorized, he.Code) assert.Equal(t, http.StatusUnauthorized, he.Code)
assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate)) assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
// Invalid Authorization header // Invalid Authorization header
auth = base64.StdEncoding.EncodeToString([]byte("invalid")) auth = base64.StdEncoding.EncodeToString([]byte("invalid"))
rq.Header().Set(echo.Authorization, auth) rq.Header().Set(echo.Authorization, auth)
he = h.Handle(c).(*echo.HTTPError) he = h(c).(*echo.HTTPError)
assert.Equal(t, http.StatusUnauthorized, he.Code) assert.Equal(t, http.StatusUnauthorized, he.Code)
assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate)) assert.Equal(t, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
} }

View File

@ -50,8 +50,8 @@ func GzipFromConfig(config GzipConfig) echo.MiddlewareFunc {
pool := gzipPool(config) pool := gzipPool(config)
scheme := "gzip" scheme := "gzip"
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
rs := c.Response() rs := c.Response()
rs.Header().Add(echo.Vary, echo.AcceptEncoding) rs.Header().Add(echo.Vary, echo.AcceptEncoding)
if strings.Contains(c.Request().Header().Get(echo.AcceptEncoding), scheme) { if strings.Contains(c.Request().Header().Get(echo.AcceptEncoding), scheme) {
@ -74,8 +74,8 @@ func GzipFromConfig(config GzipConfig) echo.MiddlewareFunc {
rs.Header().Set(echo.ContentEncoding, scheme) rs.Header().Set(echo.ContentEncoding, scheme)
rs.SetWriter(g) rs.SetWriter(g)
} }
return next.Handle(c) return next(c)
}) }
} }
} }

View File

@ -19,11 +19,11 @@ func TestGzip(t *testing.T) {
c := echo.NewContext(rq, rec, e) c := echo.NewContext(rq, rec, e)
// Skip if no Accept-Encoding header // Skip if no Accept-Encoding header
h := Gzip()(echo.HandlerFunc(func(c echo.Context) error { h := Gzip()(func(c echo.Context) error {
c.Response().Write([]byte("test")) // For Content-Type sniffing c.Response().Write([]byte("test")) // For Content-Type sniffing
return nil return nil
})) })
h.Handle(c) h(c)
assert.Equal(t, "test", rec.Body.String()) assert.Equal(t, "test", rec.Body.String())
rq = test.NewRequest(echo.GET, "/", nil) rq = test.NewRequest(echo.GET, "/", nil)
@ -32,7 +32,7 @@ func TestGzip(t *testing.T) {
c = echo.NewContext(rq, rec, e) c = echo.NewContext(rq, rec, e)
// Gzip // Gzip
h.Handle(c) h(c)
assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding)) assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding))
assert.Contains(t, rec.Header().Get(echo.ContentType), echo.TextPlain) assert.Contains(t, rec.Header().Get(echo.ContentType), echo.TextPlain)
r, err := gzip.NewReader(rec.Body) r, err := gzip.NewReader(rec.Body)
@ -49,10 +49,10 @@ func TestGzipNoContent(t *testing.T) {
rq := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(rq, rec, e) c := echo.NewContext(rq, rec, e)
h := Gzip()(echo.HandlerFunc(func(c echo.Context) error { h := Gzip()(func(c echo.Context) error {
return c.NoContent(http.StatusOK) return c.NoContent(http.StatusOK)
})) })
h.Handle(c) h(c)
assert.Empty(t, rec.Header().Get(echo.ContentEncoding)) assert.Empty(t, rec.Header().Get(echo.ContentEncoding))
assert.Empty(t, rec.Header().Get(echo.ContentType)) assert.Empty(t, rec.Header().Get(echo.ContentType))
@ -65,9 +65,9 @@ func TestGzipNoContent(t *testing.T) {
func TestGzipErrorReturned(t *testing.T) { func TestGzipErrorReturned(t *testing.T) {
e := echo.New() e := echo.New()
e.Use(Gzip()) e.Use(Gzip())
e.Get("/", echo.HandlerFunc(func(c echo.Context) error { e.Get("/", func(c echo.Context) error {
return echo.NewHTTPError(http.StatusInternalServerError, "error") return echo.NewHTTPError(http.StatusInternalServerError, "error")
})) })
rq := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
e.ServeHTTP(rq, rec) e.ServeHTTP(rq, rec)

View File

@ -74,12 +74,12 @@ func LoggerFromConfig(config LoggerConfig) echo.MiddlewareFunc {
config.color.Disable() config.color.Disable()
} }
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) (err error) { return func(c echo.Context) (err error) {
rq := c.Request() rq := c.Request()
rs := c.Response() rs := c.Response()
start := time.Now() start := time.Now()
if err = next.Handle(c); err != nil { if err = next(c); err != nil {
c.Error(err) c.Error(err)
} }
stop := time.Now() stop := time.Now()
@ -129,6 +129,6 @@ func LoggerFromConfig(config LoggerConfig) echo.MiddlewareFunc {
} }
}) })
return return
}) }
} }
} }

View File

@ -17,37 +17,37 @@ func TestLogger(t *testing.T) {
rq := test.NewRequest(echo.GET, "/", nil) rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder() rec := test.NewResponseRecorder()
c := echo.NewContext(rq, rec, e) c := echo.NewContext(rq, rec, e)
h := Logger()(echo.HandlerFunc(func(c echo.Context) error { h := Logger()(func(c echo.Context) error {
return c.String(http.StatusOK, "test") return c.String(http.StatusOK, "test")
})) })
// Status 2xx // Status 2xx
h.Handle(c) h(c)
// Status 3xx // Status 3xx
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(rq, rec, e) c = echo.NewContext(rq, rec, e)
h = Logger()(echo.HandlerFunc(func(c echo.Context) error { h = Logger()(func(c echo.Context) error {
return c.String(http.StatusTemporaryRedirect, "test") return c.String(http.StatusTemporaryRedirect, "test")
})) })
h.Handle(c) h(c)
// Status 4xx // Status 4xx
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(rq, rec, e) c = echo.NewContext(rq, rec, e)
h = Logger()(echo.HandlerFunc(func(c echo.Context) error { h = Logger()(func(c echo.Context) error {
return c.String(http.StatusNotFound, "test") return c.String(http.StatusNotFound, "test")
})) })
h.Handle(c) h(c)
// Status 5xx with empty path // Status 5xx with empty path
rq = test.NewRequest(echo.GET, "", nil) rq = test.NewRequest(echo.GET, "", nil)
rec = test.NewResponseRecorder() rec = test.NewResponseRecorder()
c = echo.NewContext(rq, rec, e) c = echo.NewContext(rq, rec, e)
h = Logger()(echo.HandlerFunc(func(c echo.Context) error { h = Logger()(func(c echo.Context) error {
return errors.New("error") return errors.New("error")
})) })
h.Handle(c) h(c)
} }
func TestLoggerIPAddress(t *testing.T) { func TestLoggerIPAddress(t *testing.T) {
@ -58,24 +58,24 @@ func TestLoggerIPAddress(t *testing.T) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
e.Logger().SetOutput(buf) e.Logger().SetOutput(buf)
ip := "127.0.0.1" ip := "127.0.0.1"
h := Logger()(echo.HandlerFunc(func(c echo.Context) error { h := Logger()(func(c echo.Context) error {
return c.String(http.StatusOK, "test") return c.String(http.StatusOK, "test")
})) })
// With X-Real-IP // With X-Real-IP
rq.Header().Add(echo.XRealIP, ip) rq.Header().Add(echo.XRealIP, ip)
h.Handle(c) h(c)
assert.Contains(t, ip, buf.String()) assert.Contains(t, ip, buf.String())
// With X-Forwarded-For // With X-Forwarded-For
buf.Reset() buf.Reset()
rq.Header().Del(echo.XRealIP) rq.Header().Del(echo.XRealIP)
rq.Header().Add(echo.XForwardedFor, ip) rq.Header().Add(echo.XForwardedFor, ip)
h.Handle(c) h(c)
assert.Contains(t, ip, buf.String()) assert.Contains(t, ip, buf.String())
// with rq.RemoteAddr // with rq.RemoteAddr
buf.Reset() buf.Reset()
h.Handle(c) h(c)
assert.Contains(t, ip, buf.String()) assert.Contains(t, ip, buf.String())
} }

View File

@ -49,8 +49,8 @@ func RecoverFromConfig(config RecoverConfig) echo.MiddlewareFunc {
config.StackSize = DefaultRecoverConfig.StackSize config.StackSize = DefaultRecoverConfig.StackSize
} }
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
var err error var err error
@ -68,7 +68,7 @@ func RecoverFromConfig(config RecoverConfig) echo.MiddlewareFunc {
c.Error(err) c.Error(err)
} }
}() }()
return next.Handle(c) return next(c)
}) }
} }
} }

View File

@ -20,7 +20,7 @@ func TestRecover(t *testing.T) {
h := Recover()(echo.HandlerFunc(func(c echo.Context) error { h := Recover()(echo.HandlerFunc(func(c echo.Context) error {
panic("test") panic("test")
})) }))
h.Handle(c) h(c)
assert.Equal(t, http.StatusInternalServerError, rec.Status()) assert.Equal(t, http.StatusInternalServerError, rec.Status())
assert.Contains(t, buf.String(), "PANIC RECOVER") assert.Contains(t, buf.String(), "PANIC RECOVER")
} }

View File

@ -9,15 +9,15 @@ import (
// //
// Usage `Echo#Pre(AddTrailingSlash())` // Usage `Echo#Pre(AddTrailingSlash())`
func AddTrailingSlash() echo.MiddlewareFunc { func AddTrailingSlash() echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
url := c.Request().URL() url := c.Request().URL()
path := url.Path() path := url.Path()
if path != "/" && path[len(path)-1] != '/' { if path != "/" && path[len(path)-1] != '/' {
url.SetPath(path + "/") url.SetPath(path + "/")
} }
return next.Handle(c) return next(c)
}) }
} }
} }
@ -26,15 +26,15 @@ func AddTrailingSlash() echo.MiddlewareFunc {
// //
// Usage `Echo#Pre(RemoveTrailingSlash())` // Usage `Echo#Pre(RemoveTrailingSlash())`
func RemoveTrailingSlash() echo.MiddlewareFunc { func RemoveTrailingSlash() echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
url := c.Request().URL() url := c.Request().URL()
path := url.Path() path := url.Path()
l := len(path) - 1 l := len(path) - 1
if path != "/" && path[l] == '/' { if path != "/" && path[l] == '/' {
url.SetPath(path[:l]) url.SetPath(path[:l])
} }
return next.Handle(c) return next(c)
}) }
} }
} }

View File

@ -13,10 +13,10 @@ func TestAddTrailingSlash(t *testing.T) {
rq := test.NewRequest(echo.GET, "/add-slash", nil) rq := test.NewRequest(echo.GET, "/add-slash", nil)
rc := test.NewResponseRecorder() rc := test.NewResponseRecorder()
c := echo.NewContext(rq, rc, e) c := echo.NewContext(rq, rc, e)
h := AddTrailingSlash()(echo.HandlerFunc(func(c echo.Context) error { h := AddTrailingSlash()(func(c echo.Context) error {
return nil return nil
})) })
h.Handle(c) h(c)
assert.Equal(t, "/add-slash/", rq.URL().Path()) assert.Equal(t, "/add-slash/", rq.URL().Path())
} }
@ -25,9 +25,9 @@ func TestRemoveTrailingSlash(t *testing.T) {
rq := test.NewRequest(echo.GET, "/remove-slash/", nil) rq := test.NewRequest(echo.GET, "/remove-slash/", nil)
rc := test.NewResponseRecorder() rc := test.NewResponseRecorder()
c := echo.NewContext(rq, rc, e) c := echo.NewContext(rq, rc, e)
h := RemoveTrailingSlash()(echo.HandlerFunc(func(c echo.Context) error { h := RemoveTrailingSlash()(func(c echo.Context) error {
return nil return nil
})) })
h.Handle(c) h(c)
assert.Equal(t, "/remove-slash", rq.URL().Path()) assert.Equal(t, "/remove-slash", rq.URL().Path())
} }

View File

@ -51,8 +51,8 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
config.Index = DefaultStaticConfig.Index config.Index = DefaultStaticConfig.Index
} }
return func(next echo.Handler) echo.Handler { return func(next echo.HandlerFunc) echo.HandlerFunc {
return echo.HandlerFunc(func(c echo.Context) error { return func(c echo.Context) error {
fs := http.Dir(config.Root) fs := http.Dir(config.Root)
p := c.Request().URL().Path() p := c.Request().URL().Path()
if c.P(0) != "" { // If serving from `Group`, e.g. `/static/*` if c.P(0) != "" { // If serving from `Group`, e.g. `/static/*`
@ -61,7 +61,7 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
file := path.Clean(p) file := path.Clean(p)
f, err := fs.Open(file) f, err := fs.Open(file)
if err != nil { if err != nil {
return next.Handle(c) return next(c)
} }
defer f.Close() defer f.Close()
@ -108,11 +108,11 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
_, err = fmt.Fprintf(rs, "</pre>\n") _, err = fmt.Fprintf(rs, "</pre>\n")
return err return err
} }
return next.Handle(c) return next(c)
} }
fi, _ = f.Stat() // Index file stat fi, _ = f.Stat() // Index file stat
} }
return c.ServeContent(f, fi.Name(), fi.ModTime()) return c.ServeContent(f, fi.Name(), fi.ModTime())
}) }
} }
} }

View File

@ -21,15 +21,15 @@ type (
kind uint8 kind uint8
children []*node children []*node
methodHandler struct { methodHandler struct {
connect Handler connect HandlerFunc
delete Handler delete HandlerFunc
get Handler get HandlerFunc
head Handler head HandlerFunc
options Handler options HandlerFunc
patch Handler patch HandlerFunc
post Handler post HandlerFunc
put Handler put HandlerFunc
trace Handler trace HandlerFunc
} }
) )
@ -50,14 +50,14 @@ func NewRouter(e *Echo) *Router {
} }
} }
// Handle implements `echo.Middleware` which makes router a middleware. // Process implements `echo.MiddlewareFunc` which makes router a middleware.
func (r *Router) Handle(next Handler) Handler { func (r *Router) Process(next HandlerFunc) HandlerFunc {
return HandlerFunc(func(c Context) error { return func(c Context) error {
method := c.Request().Method() method := c.Request().Method()
path := c.Request().URL().Path() path := c.Request().URL().Path()
r.Find(method, path, c) r.Find(method, path, c)
return next.Handle(c) return next(c)
}) }
} }
// Priority is super secret. // Priority is super secret.
@ -66,7 +66,7 @@ func (r *Router) Priority() int {
} }
// Add registers a new route for method and path with matching handler. // Add registers a new route for method and path with matching handler.
func (r *Router) Add(method, path string, h Handler, e *Echo) { func (r *Router) Add(method, path string, h HandlerFunc, e *Echo) {
ppath := path // Pristine path ppath := path // Pristine path
pnames := []string{} // Param names pnames := []string{} // Param names
@ -98,7 +98,7 @@ func (r *Router) Add(method, path string, h Handler, e *Echo) {
r.insert(method, path, h, skind, ppath, pnames, e) r.insert(method, path, h, skind, ppath, pnames, e)
} }
func (r *Router) insert(method, path string, h Handler, t kind, ppath string, pnames []string, e *Echo) { func (r *Router) insert(method, path string, h HandlerFunc, t kind, ppath string, pnames []string, e *Echo) {
// Adjust max param // Adjust max param
l := len(pnames) l := len(pnames)
if *e.maxParam < l { if *e.maxParam < l {
@ -229,7 +229,7 @@ func (n *node) findChildByKind(t kind) *node {
return nil return nil
} }
func (n *node) addHandler(method string, h Handler) { func (n *node) addHandler(method string, h HandlerFunc) {
switch method { switch method {
case GET: case GET:
n.methodHandler.get = h n.methodHandler.get = h
@ -252,7 +252,7 @@ func (n *node) addHandler(method string, h Handler) {
} }
} }
func (n *node) findHandler(method string) Handler { func (n *node) findHandler(method string) HandlerFunc {
switch method { switch method {
case GET: case GET:
return n.methodHandler.get return n.methodHandler.get

View File

@ -277,10 +277,10 @@ func TestRouterStatic(t *testing.T) {
e := New() e := New()
r := e.router r := e.router
path := "/folders/a/files/echo.gif" path := "/folders/a/files/echo.gif"
r.Add(GET, path, HandlerFunc(func(c Context) error { r.Add(GET, path, func(c Context) error {
c.Set("path", path) c.Set("path", path)
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
r.Find(GET, path, c) r.Find(GET, path, c)
c.Handle(c) c.Handle(c)
@ -290,9 +290,9 @@ func TestRouterStatic(t *testing.T) {
func TestRouterParam(t *testing.T) { func TestRouterParam(t *testing.T) {
e := New() e := New()
r := e.router r := e.router
r.Add(GET, "/users/:id", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:id", func(c Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
r.Find(GET, "/users/1", c) r.Find(GET, "/users/1", c)
assert.Equal(t, "1", c.P(0)) assert.Equal(t, "1", c.P(0))
@ -301,9 +301,9 @@ func TestRouterParam(t *testing.T) {
func TestRouterTwoParam(t *testing.T) { func TestRouterTwoParam(t *testing.T) {
e := New() e := New()
r := e.router r := e.router
r.Add(GET, "/users/:uid/files/:fid", HandlerFunc(func(Context) error { r.Add(GET, "/users/:uid/files/:fid", func(Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
r.Find(GET, "/users/1/files/1", c) r.Find(GET, "/users/1/files/1", c)
@ -316,13 +316,13 @@ func TestRouterParamWithSlash(t *testing.T) {
e := New() e := New()
r := e.router r := e.router
r.Add(GET, "/a/:b/c/d/:e", HandlerFunc(func(c Context) error { r.Add(GET, "/a/:b/c/d/:e", func(c Context) error {
return nil return nil
}), e) }, e)
r.Add(GET, "/a/:b/c/:d/:f", HandlerFunc(func(c Context) error { r.Add(GET, "/a/:b/c/:d/:f", func(c Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
assert.NotPanics(t, func() { assert.NotPanics(t, func() {
@ -335,15 +335,15 @@ func TestRouterMatchAny(t *testing.T) {
r := e.router r := e.router
// Routes // Routes
r.Add(GET, "/", HandlerFunc(func(Context) error { r.Add(GET, "/", func(Context) error {
return nil return nil
}), e) }, e)
r.Add(GET, "/*", HandlerFunc(func(Context) error { r.Add(GET, "/*", func(Context) error {
return nil return nil
}), e) }, e)
r.Add(GET, "/users/*", HandlerFunc(func(Context) error { r.Add(GET, "/users/*", func(Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
r.Find(GET, "/", c) r.Find(GET, "/", c)
@ -359,9 +359,9 @@ func TestRouterMatchAny(t *testing.T) {
func TestRouterMicroParam(t *testing.T) { func TestRouterMicroParam(t *testing.T) {
e := New() e := New()
r := e.router r := e.router
r.Add(GET, "/:a/:b/:c", HandlerFunc(func(c Context) error { r.Add(GET, "/:a/:b/:c", func(c Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
r.Find(GET, "/1/2/3", c) r.Find(GET, "/1/2/3", c)
assert.Equal(t, "1", c.P(0)) assert.Equal(t, "1", c.P(0))
@ -374,9 +374,9 @@ func TestRouterMixParamMatchAny(t *testing.T) {
r := e.router r := e.router
// Route // Route
r.Add(GET, "/users/:id/*", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:id/*", func(c Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
r.Find(GET, "/users/joe/comments", c) r.Find(GET, "/users/joe/comments", c)
@ -389,13 +389,13 @@ func TestRouterMultiRoute(t *testing.T) {
r := e.router r := e.router
// Routes // Routes
r.Add(GET, "/users", HandlerFunc(func(c Context) error { r.Add(GET, "/users", func(c Context) error {
c.Set("path", "/users") c.Set("path", "/users")
return nil return nil
}), e) }, e)
r.Add(GET, "/users/:id", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:id", func(c Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
// Route > /users // Route > /users
@ -419,34 +419,34 @@ func TestRouterPriority(t *testing.T) {
r := e.router r := e.router
// Routes // Routes
r.Add(GET, "/users", HandlerFunc(func(c Context) error { r.Add(GET, "/users", func(c Context) error {
c.Set("a", 1) c.Set("a", 1)
return nil return nil
}), e) }, e)
r.Add(GET, "/users/new", HandlerFunc(func(c Context) error { r.Add(GET, "/users/new", func(c Context) error {
c.Set("b", 2) c.Set("b", 2)
return nil return nil
}), e) }, e)
r.Add(GET, "/users/:id", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:id", func(c Context) error {
c.Set("c", 3) c.Set("c", 3)
return nil return nil
}), e) }, e)
r.Add(GET, "/users/dew", HandlerFunc(func(c Context) error { r.Add(GET, "/users/dew", func(c Context) error {
c.Set("d", 4) c.Set("d", 4)
return nil return nil
}), e) }, e)
r.Add(GET, "/users/:id/files", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:id/files", func(c Context) error {
c.Set("e", 5) c.Set("e", 5)
return nil return nil
}), e) }, e)
r.Add(GET, "/users/newsee", HandlerFunc(func(c Context) error { r.Add(GET, "/users/newsee", func(c Context) error {
c.Set("f", 6) c.Set("f", 6)
return nil return nil
}), e) }, e)
r.Add(GET, "/users/*", HandlerFunc(func(c Context) error { r.Add(GET, "/users/*", func(c Context) error {
c.Set("g", 7) c.Set("g", 7)
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
// Route > /users // Route > /users
@ -493,14 +493,14 @@ func TestRouterPriorityNotFound(t *testing.T) {
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
// Add // Add
r.Add(GET, "/a/foo", HandlerFunc(func(c Context) error { r.Add(GET, "/a/foo", func(c Context) error {
c.Set("a", 1) c.Set("a", 1)
return nil return nil
}), e) }, e)
r.Add(GET, "/a/bar", HandlerFunc(func(c Context) error { r.Add(GET, "/a/bar", func(c Context) error {
c.Set("b", 2) c.Set("b", 2)
return nil return nil
}), e) }, e)
// Find // Find
r.Find(GET, "/a/foo", c) r.Find(GET, "/a/foo", c)
@ -522,16 +522,16 @@ func TestRouterParamNames(t *testing.T) {
r := e.router r := e.router
// Routes // Routes
r.Add(GET, "/users", HandlerFunc(func(c Context) error { r.Add(GET, "/users", func(c Context) error {
c.Set("path", "/users") c.Set("path", "/users")
return nil return nil
}), e) }, e)
r.Add(GET, "/users/:id", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:id", func(c Context) error {
return nil return nil
}), e) }, e)
r.Add(GET, "/users/:uid/files/:fid", HandlerFunc(func(c Context) error { r.Add(GET, "/users/:uid/files/:fid", func(c Context) error {
return nil return nil
}), e) }, e)
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
// Route > /users // Route > /users
@ -557,9 +557,9 @@ func TestRouterAPI(t *testing.T) {
r := e.router r := e.router
for _, route := range api { for _, route := range api {
r.Add(route.Method, route.Path, HandlerFunc(func(c Context) error { r.Add(route.Method, route.Path, func(c Context) error {
return nil return nil
}), e) }, e)
} }
c := NewContext(nil, nil, e) c := NewContext(nil, nil, e)
for _, route := range api { for _, route := range api {
@ -579,9 +579,9 @@ func BenchmarkRouterGitHubAPI(b *testing.B) {
// Add routes // Add routes
for _, route := range api { for _, route := range api {
r.Add(route.Method, route.Path, HandlerFunc(func(c Context) error { r.Add(route.Method, route.Path, func(c Context) error {
return nil return nil
}), e) }, e)
} }
// Find routes // Find routes