1
0
mirror of https://github.com/labstack/echo.git synced 2024-12-24 20:14:31 +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"
)
// Handler
func hello() echo.HandlerFunc {
return func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!\n")
}
}
func main() {
// Echo instance
e := echo.New()
@ -65,8 +58,10 @@ func main() {
e.Use(middleware.Logger())
e.Use(middleware.Recover())
// Routes
e.Get("/", hello())
// Route => handler
e.Get("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World!\n")
})
// Start server
e.Run(standard.New(":1323"))
@ -96,7 +91,7 @@ Hello, World! on the page.
- :star: the project
- [Donate](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=JD5R56K84A8G4&lc=US&item_name=LabStack&item_number=echo&currency_code=USD&bn=PP-DonationsBF:btn_donate_LG.gif:NonHosted)
- :earth_americas: spread the word
- :earth_americas: spread the word
- [Contribute](#contribute) to the project
## Contribute

View File

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

124
echo.go
View File

@ -62,9 +62,9 @@ type (
// Echo is the top-level framework instance.
Echo struct {
prefix string
middleware []Middleware
head Handler
pristineHead Handler
middleware []MiddlewareFunc
head HandlerFunc
pristineHead HandlerFunc
maxParam *int
notFoundHandler HandlerFunc
httpErrorHandler HTTPErrorHandler
@ -89,24 +89,10 @@ type (
Message string
}
// Middleware defines an interface for middleware via `Handle(Handler) Handler`
// function.
Middleware interface {
Handle(Handler) Handler
}
// MiddlewareFunc defines a function to process middleware.
MiddlewareFunc func(HandlerFunc) HandlerFunc
// MiddlewareFunc is an adapter to allow the use of `func(Handler) Handler` as
// 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 defines a function to server HTTP requests.
HandlerFunc func(Context) error
// HTTPErrorHandler is a centralized HTTP error handler.
@ -212,13 +198,13 @@ var (
// Error handlers
var (
notFoundHandler = HandlerFunc(func(c Context) error {
notFoundHandler = func(c Context) error {
return ErrNotFound
})
}
methodNotAllowedHandler = HandlerFunc(func(c Context) error {
methodNotAllowedHandler = func(c Context) error {
return ErrMethodNotAllowed
})
}
)
// New creates an instance of Echo.
@ -228,10 +214,10 @@ func New() (e *Echo) {
return NewContext(nil, nil, e)
}
e.router = NewRouter(e)
e.middleware = []Middleware{e.router}
e.head = HandlerFunc(func(c Context) error {
e.middleware = []MiddlewareFunc{e.router.Process}
e.head = func(c Context) error {
return c.Handle(c)
})
}
e.pristineHead = e.head
e.chainMiddleware()
@ -244,16 +230,6 @@ func New() (e *Echo) {
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.
func (e *Echo) Router() *Router {
return e.router
@ -323,13 +299,13 @@ func (e *Echo) Debug() bool {
}
// 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.chainMiddleware()
}
// 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.chainMiddleware()
}
@ -337,67 +313,67 @@ func (e *Echo) Use(middleware ...Middleware) {
func (e *Echo) chainMiddleware() {
e.head = e.pristineHead
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
// 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...)
}
// Delete registers a new DELETE route for a path with matching handler in the router
// 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...)
}
// Get registers a new GET route for a path with matching handler in the router
// 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...)
}
// Head registers a new HEAD route for a path with matching handler in the
// 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...)
}
// Options registers a new OPTIONS route for a path with matching handler in the
// 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...)
}
// Patch registers a new PATCH route for a path with matching handler in the
// 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...)
}
// Post registers a new POST route for a path with matching handler in the
// 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...)
}
// Put registers a new PUT route for a path with matching handler in the
// 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...)
}
// Trace registers a new TRACE route for a path with matching handler in the
// 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...)
}
// Any registers a new route for all HTTP methods and path with matching handler
// 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 {
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
// 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 {
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.
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 `_`
}))
})
}
// File serves provided file for `/<path>` HTTP path.
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)
}))
})
}
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)
e.router.Add(method, path, HandlerFunc(func(c Context) error {
e.router.Add(method, path, func(c Context) error {
h := handler
// Chain middleware
for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i].Handle(h)
h = middleware[i](h)
}
return h.Handle(c)
}), e)
return h(c)
}, e)
r := Route{
Method: method,
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.
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.Use(m...)
// 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
}
// 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)
ln := len(params)
n := 0
@ -480,7 +456,7 @@ func (e *Echo) URI(handler Handler, params ...interface{}) string {
}
// 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...)
}
@ -506,7 +482,7 @@ func (e *Echo) ServeHTTP(rq engine.Request, rs engine.Response) {
c.Reset(rq, rs)
// Execute chain
if err := e.head.Handle(c); err != nil {
if err := e.head(c); err != nil {
e.httpErrorHandler(err, c)
}
@ -551,19 +527,19 @@ func (binder) Bind(i interface{}, c Context) (err error) {
return
}
// WrapMiddleware wrap `echo.Handler` into `echo.MiddlewareFunc`.
func WrapMiddleware(h Handler) MiddlewareFunc {
return func(next Handler) Handler {
return HandlerFunc(func(c Context) error {
if err := h.Handle(c); err != nil {
// WrapMiddleware wrap `echo.HandlerFunc` into `echo.MiddlewareFunc`.
func WrapMiddleware(h HandlerFunc) MiddlewareFunc {
return func(next HandlerFunc) HandlerFunc {
return func(c Context) error {
if err := h(c); err != nil {
return err
}
return next.Handle(c)
})
return next(c)
}
}
}
func handlerName(h Handler) string {
func handlerName(h HandlerFunc) string {
t := reflect.ValueOf(h).Type()
if t.Kind() == reflect.Func {
return runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()

View File

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

10
glide.lock generated
View File

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

View File

@ -6,94 +6,94 @@ type (
// from the parent echo instance while still inheriting from it.
Group struct {
prefix string
middleware []Middleware
middleware []MiddlewareFunc
echo *Echo
}
)
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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...)
}
// 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 {
g.add(m, path, handler, middleware...)
}
}
// 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 {
g.add(m, path, handler, 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...)
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
name := handlerName(handler)
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
// Chain middleware
for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i].Handle(h)
h = middleware[i](h)
}
return h.Handle(c)
}), g.echo)
return h(c)
}, g.echo)
r := Route{
Method: method,
Path: path,

View File

@ -4,7 +4,7 @@ import "testing"
func TestGroup(t *testing.T) {
g := New().Group("/group")
h := HandlerFunc(func(Context) error { return nil })
h := func(Context) error { return nil }
g.Connect("/", h)
g.Delete("/", 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.
// See `BasicAuth()`.
func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
auth := c.Request().Header().Get(echo.Authorization)
l := len(basic)
@ -52,7 +52,7 @@ func BasicAuthFromConfig(config BasicAuthConfig) echo.MiddlewareFunc {
if cred[i] == ':' {
// Verify credentials
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")
return echo.ErrUnauthorized
})
}
}
}

View File

@ -21,14 +21,14 @@ func TestBasicAuth(t *testing.T) {
}
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")
}))
})
// Valid credentials
auth := basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:secret"))
rq.Header().Set(echo.Authorization, auth)
assert.NoError(t, h.Handle(c))
assert.NoError(t, h(c))
//---------------------
// Invalid credentials
@ -37,20 +37,20 @@ func TestBasicAuth(t *testing.T) {
// Incorrect password
auth = basic + " " + base64.StdEncoding.EncodeToString([]byte("joe:password"))
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, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
// Empty Authorization header
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, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
// Invalid Authorization header
auth = base64.StdEncoding.EncodeToString([]byte("invalid"))
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, basic+" realm=Restricted", rs.Header().Get(echo.WWWAuthenticate))
}

View File

@ -50,8 +50,8 @@ func GzipFromConfig(config GzipConfig) echo.MiddlewareFunc {
pool := gzipPool(config)
scheme := "gzip"
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
rs := c.Response()
rs.Header().Add(echo.Vary, echo.AcceptEncoding)
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.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)
// 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
return nil
}))
h.Handle(c)
})
h(c)
assert.Equal(t, "test", rec.Body.String())
rq = test.NewRequest(echo.GET, "/", nil)
@ -32,7 +32,7 @@ func TestGzip(t *testing.T) {
c = echo.NewContext(rq, rec, e)
// Gzip
h.Handle(c)
h(c)
assert.Equal(t, "gzip", rec.Header().Get(echo.ContentEncoding))
assert.Contains(t, rec.Header().Get(echo.ContentType), echo.TextPlain)
r, err := gzip.NewReader(rec.Body)
@ -49,10 +49,10 @@ func TestGzipNoContent(t *testing.T) {
rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder()
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)
}))
h.Handle(c)
})
h(c)
assert.Empty(t, rec.Header().Get(echo.ContentEncoding))
assert.Empty(t, rec.Header().Get(echo.ContentType))
@ -65,9 +65,9 @@ func TestGzipNoContent(t *testing.T) {
func TestGzipErrorReturned(t *testing.T) {
e := echo.New()
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")
}))
})
rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder()
e.ServeHTTP(rq, rec)

View File

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

View File

@ -17,37 +17,37 @@ func TestLogger(t *testing.T) {
rq := test.NewRequest(echo.GET, "/", nil)
rec := test.NewResponseRecorder()
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")
}))
})
// Status 2xx
h.Handle(c)
h(c)
// Status 3xx
rec = test.NewResponseRecorder()
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")
}))
h.Handle(c)
})
h(c)
// Status 4xx
rec = test.NewResponseRecorder()
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")
}))
h.Handle(c)
})
h(c)
// Status 5xx with empty path
rq = test.NewRequest(echo.GET, "", nil)
rec = test.NewResponseRecorder()
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")
}))
h.Handle(c)
})
h(c)
}
func TestLoggerIPAddress(t *testing.T) {
@ -58,24 +58,24 @@ func TestLoggerIPAddress(t *testing.T) {
buf := new(bytes.Buffer)
e.Logger().SetOutput(buf)
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")
}))
})
// With X-Real-IP
rq.Header().Add(echo.XRealIP, ip)
h.Handle(c)
h(c)
assert.Contains(t, ip, buf.String())
// With X-Forwarded-For
buf.Reset()
rq.Header().Del(echo.XRealIP)
rq.Header().Add(echo.XForwardedFor, ip)
h.Handle(c)
h(c)
assert.Contains(t, ip, buf.String())
// with rq.RemoteAddr
buf.Reset()
h.Handle(c)
h(c)
assert.Contains(t, ip, buf.String())
}

View File

@ -49,8 +49,8 @@ func RecoverFromConfig(config RecoverConfig) echo.MiddlewareFunc {
config.StackSize = DefaultRecoverConfig.StackSize
}
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
defer func() {
if r := recover(); r != nil {
var err error
@ -68,7 +68,7 @@ func RecoverFromConfig(config RecoverConfig) echo.MiddlewareFunc {
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 {
panic("test")
}))
h.Handle(c)
h(c)
assert.Equal(t, http.StatusInternalServerError, rec.Status())
assert.Contains(t, buf.String(), "PANIC RECOVER")
}

View File

@ -9,15 +9,15 @@ import (
//
// Usage `Echo#Pre(AddTrailingSlash())`
func AddTrailingSlash() echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
url := c.Request().URL()
path := url.Path()
if path != "/" && path[len(path)-1] != '/' {
url.SetPath(path + "/")
}
return next.Handle(c)
})
return next(c)
}
}
}
@ -26,15 +26,15 @@ func AddTrailingSlash() echo.MiddlewareFunc {
//
// Usage `Echo#Pre(RemoveTrailingSlash())`
func RemoveTrailingSlash() echo.MiddlewareFunc {
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
url := c.Request().URL()
path := url.Path()
l := len(path) - 1
if path != "/" && 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)
rc := test.NewResponseRecorder()
c := echo.NewContext(rq, rc, e)
h := AddTrailingSlash()(echo.HandlerFunc(func(c echo.Context) error {
h := AddTrailingSlash()(func(c echo.Context) error {
return nil
}))
h.Handle(c)
})
h(c)
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)
rc := test.NewResponseRecorder()
c := echo.NewContext(rq, rc, e)
h := RemoveTrailingSlash()(echo.HandlerFunc(func(c echo.Context) error {
h := RemoveTrailingSlash()(func(c echo.Context) error {
return nil
}))
h.Handle(c)
})
h(c)
assert.Equal(t, "/remove-slash", rq.URL().Path())
}

View File

@ -51,8 +51,8 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
config.Index = DefaultStaticConfig.Index
}
return func(next echo.Handler) echo.Handler {
return echo.HandlerFunc(func(c echo.Context) error {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
fs := http.Dir(config.Root)
p := c.Request().URL().Path()
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)
f, err := fs.Open(file)
if err != nil {
return next.Handle(c)
return next(c)
}
defer f.Close()
@ -108,11 +108,11 @@ func StaticFromConfig(config StaticConfig) echo.MiddlewareFunc {
_, err = fmt.Fprintf(rs, "</pre>\n")
return err
}
return next.Handle(c)
return next(c)
}
fi, _ = f.Stat() // Index file stat
}
return c.ServeContent(f, fi.Name(), fi.ModTime())
})
}
}
}

View File

@ -21,15 +21,15 @@ type (
kind uint8
children []*node
methodHandler struct {
connect Handler
delete Handler
get Handler
head Handler
options Handler
patch Handler
post Handler
put Handler
trace Handler
connect HandlerFunc
delete HandlerFunc
get HandlerFunc
head HandlerFunc
options HandlerFunc
patch HandlerFunc
post HandlerFunc
put HandlerFunc
trace HandlerFunc
}
)
@ -50,14 +50,14 @@ func NewRouter(e *Echo) *Router {
}
}
// Handle implements `echo.Middleware` which makes router a middleware.
func (r *Router) Handle(next Handler) Handler {
return HandlerFunc(func(c Context) error {
// Process implements `echo.MiddlewareFunc` which makes router a middleware.
func (r *Router) Process(next HandlerFunc) HandlerFunc {
return func(c Context) error {
method := c.Request().Method()
path := c.Request().URL().Path()
r.Find(method, path, c)
return next.Handle(c)
})
return next(c)
}
}
// 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.
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
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)
}
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
l := len(pnames)
if *e.maxParam < l {
@ -229,7 +229,7 @@ func (n *node) findChildByKind(t kind) *node {
return nil
}
func (n *node) addHandler(method string, h Handler) {
func (n *node) addHandler(method string, h HandlerFunc) {
switch method {
case GET:
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 {
case GET:
return n.methodHandler.get

View File

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