1
0
mirror of https://github.com/labstack/echo.git synced 2024-11-28 08:38:39 +02:00

Refactored middleware and handlers

Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2015-05-11 20:41:28 -07:00
parent 69a97671ad
commit 6cbabac296
4 changed files with 75 additions and 134 deletions

View File

@ -8,21 +8,18 @@ Echo is a fast HTTP router (zero memory allocation) and micro web framework in G
- Middleware
- `echo.MiddlewareFunc`
- `func(echo.HandlerFunc) echo.HandlerFunc`
- `echo.HandlerFunc`
- `func(*echo.Context) *echo.HTTPError`
- `func(*echo.Context)`
- `func(http.Handler) http.Handler`
- `http.Handler`
- `http.HandlerFunc`
- `func(http.ResponseWriter, *http.Request)`
- `func(http.ResponseWriter, *http.Request) *echo.HTTPError`
- Handler
- `echo.HandlerFunc`
- `func(*echo.Context) *echo.HTTPError`
- `func(*echo.Context)`
- `http.Handler`
- `http.HandlerFunc`
- `func(http.ResponseWriter, *http.Request)`
- `func(http.ResponseWriter, *http.Request) *echo.HTTPError`
- Sub routing with groups.
- Handy encoding/decoding functions.
- Serve static files, including index.

104
echo.go
View File

@ -132,8 +132,9 @@ func New() (e *Echo) {
//----------
e.MaxParam(5)
e.NotFoundHandler(func(c *Context) {
e.NotFoundHandler(func(c *Context) *HTTPError {
http.Error(c.Response, http.StatusText(http.StatusNotFound), http.StatusNotFound)
return nil
})
e.HTTPErrorHandler(func(he *HTTPError, c *Context) {
if he.Code == 0 {
@ -185,7 +186,7 @@ func (e *Echo) MaxParam(n uint8) {
// NotFoundHandler registers a custom NotFound handler used by router in case it
// doesn't find any registered handler for HTTP method and path.
func (e *Echo) NotFoundHandler(h Handler) {
e.notFoundHandler = wrapH(h)
e.notFoundHandler = wrapHandler(h)
}
// HTTPErrorHandler registers an HTTP error handler.
@ -207,7 +208,7 @@ func (e *Echo) Renderer(r Renderer) {
// Use adds handler to the middleware chain.
func (e *Echo) Use(m ...Middleware) {
for _, h := range m {
e.middleware = append(e.middleware, wrapM(h))
e.middleware = append(e.middleware, wrapMiddleware(h))
}
}
@ -286,7 +287,7 @@ func (e *Echo) URL(h Handler, params ...interface{}) string {
func (e *Echo) add(method, path string, h Handler) {
key := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()
e.uris[key] = path
e.Router.Add(method, e.prefix+path, wrapH(h), e)
e.Router.Add(method, e.prefix+path, wrapHandler(h), e)
}
// Static serves static files.
@ -357,32 +358,17 @@ func (e *Echo) RunTLSServer(server *http.Server, certFile, keyFile string) {
log.Fatal(server.ListenAndServeTLS(certFile, keyFile))
}
// wraps Middleware
func wrapM(m Middleware) MiddlewareFunc {
// wraps middleware
func wrapMiddleware(m Middleware) MiddlewareFunc {
switch m := m.(type) {
case MiddlewareFunc:
return m
case func(HandlerFunc) HandlerFunc:
return m
case HandlerFunc:
return wrapHandlerFuncMW(m)
case func(*Context) *HTTPError:
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
if he := m(c); he != nil {
return he
}
return h(c)
}
}
case func(*Context):
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
m(c)
if !c.Response.committed {
h(c)
}
return nil
}
}
return wrapHandlerFuncMW(m)
case func(http.Handler) http.Handler:
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) (he *HTTPError) {
@ -394,61 +380,53 @@ func wrapM(m Middleware) MiddlewareFunc {
return
}
}
case http.Handler, http.HandlerFunc:
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
m.(http.Handler).ServeHTTP(c.Response.Writer, c.Request)
return h(c)
}
}
case http.Handler:
return wrapHTTPHandlerFuncMW(m.ServeHTTP)
case http.HandlerFunc:
return wrapHTTPHandlerFuncMW(m)
case func(http.ResponseWriter, *http.Request):
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
m(c.Response, c.Request)
if !c.Response.committed {
h(c)
}
return nil
}
}
case func(http.ResponseWriter, *http.Request) *HTTPError:
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
if he := m(c.Response, c.Request); he != nil {
return he
}
if !c.Response.committed {
h(c)
}
return nil
}
}
return wrapHTTPHandlerFuncMW(m)
default:
panic("echo: unknown middleware")
}
}
// wraps Handler
func wrapH(h Handler) HandlerFunc {
// Wraps HandlerFunc middleware
func wrapHandlerFuncMW(m HandlerFunc) MiddlewareFunc {
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
if he := m(c); he != nil {
return he
}
return h(c)
}
}
}
// Wraps http.HandlerFunc middleware
func wrapHTTPHandlerFuncMW(m http.HandlerFunc) MiddlewareFunc {
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
if !c.Response.committed {
m.ServeHTTP(c.Response.Writer, c.Request)
}
return h(c)
}
}
}
// wraps handler
func wrapHandler(h Handler) HandlerFunc {
switch h := h.(type) {
case HandlerFunc:
return h
case func(*Context) *HTTPError:
return h
case func(*Context):
return func(c *Context) *HTTPError {
h(c)
return nil
}
case http.Handler, http.HandlerFunc:
return func(c *Context) *HTTPError {
h.(http.Handler).ServeHTTP(c.Response, c.Request)
return nil
}
case func(http.ResponseWriter, *http.Request) *HTTPError:
return func(c *Context) *HTTPError {
return h(c.Response, c.Request)
}
case func(http.ResponseWriter, *http.Request):
return func(c *Context) *HTTPError {
h(c.Response, c.Request)

View File

@ -62,7 +62,7 @@ func TestEchoMiddleware(t *testing.T) {
}
}))
// func(echo.HandlerFunc) (echo.HandlerFunc, error)
// func(echo.HandlerFunc) echo.HandlerFunc
e.Use(func(h HandlerFunc) HandlerFunc {
return func(c *Context) *HTTPError {
b.WriteString("b")
@ -76,49 +76,38 @@ func TestEchoMiddleware(t *testing.T) {
return nil
})
// func(*echo.Context)
e.Use(func(c *Context) {
b.WriteString("d")
})
// func(http.Handler) http.Handler
e.Use(func(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b.WriteString("e")
b.WriteString("d")
h.ServeHTTP(w, r)
})
})
// http.Handler
e.Use(http.Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b.WriteString("f")
b.WriteString("e")
})))
// http.HandlerFunc
e.Use(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
b.WriteString("g")
b.WriteString("f")
}))
// func(http.ResponseWriter, *http.Request)
e.Use(func(w http.ResponseWriter, r *http.Request) {
b.WriteString("h")
})
// func(http.ResponseWriter, *http.Request) *HTTPError
e.Use(func(w http.ResponseWriter, r *http.Request) *HTTPError {
b.WriteString("i")
return nil
b.WriteString("g")
})
// Route
e.Get("/hello", func(c *Context) {
c.String(http.StatusOK, "world")
e.Get("/hello", func(c *Context) *HTTPError {
return c.String(http.StatusOK, "world")
})
w := httptest.NewRecorder()
r, _ := http.NewRequest(GET, "/hello", nil)
e.ServeHTTP(w, r)
if b.String() != "abcdefghi" {
if b.String() != "abcdefg" {
t.Errorf("buffer should be abcdefghi, found %s", b.String())
}
if w.Body.String() != "world" {
@ -151,10 +140,10 @@ func TestEchoHandler(t *testing.T) {
t.Error("body should be 2")
}
// func(*echo.Context)
e.Get("/3", func(c *Context) {
c.String(http.StatusOK, "3")
})
// http.Handler/http.HandlerFunc
e.Get("/3", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("3"))
}))
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/3", nil)
e.ServeHTTP(w, r)
@ -162,48 +151,26 @@ func TestEchoHandler(t *testing.T) {
t.Error("body should be 3")
}
// http.Handler/http.HandlerFunc
e.Get("/4", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// func(http.ResponseWriter, *http.Request)
e.Get("/4", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("4"))
}))
})
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/4", nil)
e.ServeHTTP(w, r)
if w.Body.String() != "4" {
t.Error("body should be 4")
}
// func(http.ResponseWriter, *http.Request)
e.Get("/5", func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("5"))
})
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/5", nil)
e.ServeHTTP(w, r)
if w.Body.String() != "5" {
t.Error("body should be 5")
}
// func(http.ResponseWriter, *http.Request) *HTTPError
e.Get("/6", func(w http.ResponseWriter, r *http.Request) *HTTPError {
w.Write([]byte("6"))
return nil
})
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/6", nil)
e.ServeHTTP(w, r)
if w.Body.String() != "6" {
t.Error("body should be 6")
}
}
func TestEchoGroup(t *testing.T) {
b := new(bytes.Buffer)
e := New()
e.Use(func(*Context) {
e.Use(func(*Context) *HTTPError {
b.WriteString("1")
return nil
})
e.Get("/users", func(*Context) {})
e.Get("/users", func(*Context) *HTTPError { return nil })
w := httptest.NewRecorder()
r, _ := http.NewRequest(GET, "/users", nil)
e.ServeHTTP(w, r)
@ -213,10 +180,11 @@ func TestEchoGroup(t *testing.T) {
// Group
g1 := e.Group("/group1")
g1.Use(func(*Context) {
g1.Use(func(*Context) *HTTPError {
b.WriteString("2")
return nil
})
g1.Get("/home", func(*Context) {})
g1.Get("/home", func(*Context) *HTTPError { return nil })
b.Reset()
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/group1/home", nil)
@ -226,10 +194,11 @@ func TestEchoGroup(t *testing.T) {
}
// Group with no parent middleware
g2 := e.Group("/group2", func(*Context) {
g2 := e.Group("/group2", func(*Context) *HTTPError {
b.WriteString("3")
return nil
})
g2.Get("/home", func(*Context) {})
g2.Get("/home", func(*Context) *HTTPError { return nil })
b.Reset()
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/group2/home", nil)
@ -241,8 +210,8 @@ func TestEchoGroup(t *testing.T) {
// Nested group
g3 := e.Group("/group3")
g4 := g3.Group("/group4")
g4.Get("/home", func(c *Context) {
c.NoContent(http.StatusOK)
g4.Get("/home", func(c *Context) *HTTPError {
return c.NoContent(http.StatusOK)
})
w = httptest.NewRecorder()
r, _ = http.NewRequest(GET, "/group3/group4/home", nil)
@ -254,7 +223,7 @@ func TestEchoGroup(t *testing.T) {
func TestEchoMethod(t *testing.T) {
e := New()
h := func(*Context) {}
h := func(*Context) *HTTPError { return nil }
e.Connect("/", h)
e.Delete("/", h)
e.Get("/", h)
@ -268,9 +237,9 @@ func TestEchoMethod(t *testing.T) {
func TestEchoURL(t *testing.T) {
e := New()
static := func(*Context) {}
getUser := func(*Context) {}
getFile := func(*Context) {}
static := func(*Context) *HTTPError { return nil }
getUser := func(*Context) *HTTPError { return nil }
getFile := func(*Context) *HTTPError { return nil }
e.Get("/static/file", static)
e.Get("/users/:id", getUser)
e.Get("/users/:uid/files/:fid", getFile)
@ -307,8 +276,8 @@ func TestEchoNotFound(t *testing.T) {
}
// Customized NotFound handler
e.NotFoundHandler(func(c *Context) {
c.String(http.StatusNotFound, "not found")
e.NotFoundHandler(func(c *Context) *HTTPError {
return c.String(http.StatusNotFound, "not found")
})
w = httptest.NewRecorder()
e.ServeHTTP(w, r)

View File

@ -15,21 +15,18 @@ Echo is a fast HTTP router (zero memory allocation) and micro web framework in G
- Middleware
- `echo.MiddlewareFunc`
- `func(echo.HandlerFunc) echo.HandlerFunc`
- `echo.HandlerFunc`
- `func(*echo.Context) *echo.HTTPError`
- `func(*echo.Context)`
- `func(http.Handler) http.Handler`
- `http.Handler`
- `http.HandlerFunc`
- `func(http.ResponseWriter, *http.Request)`
- `func(http.ResponseWriter, *http.Request) *echo.HTTPError`
- Handler
- `echo.HandlerFunc`
- `func(*echo.Context) *echo.HTTPError`
- `func(*echo.Context)`
- `http.Handler`
- `http.HandlerFunc`
- `func(http.ResponseWriter, *http.Request)`
- `func(http.ResponseWriter, *http.Request) *echo.HTTPError`
- Sub routing with groups.
- Handy encoding/decoding functions.
- Serve static files, including index.