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

Step towards v2

Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2015-12-03 17:23:53 -08:00
parent 5cd194b6b0
commit 72459fe299
14 changed files with 211 additions and 160 deletions

View File

@ -5,20 +5,48 @@ import (
"encoding/xml"
"net/http"
"path/filepath"
"time"
"net/url"
"bytes"
"golang.org/x/net/context"
xcontext "golang.org/x/net/context"
"golang.org/x/net/websocket"
)
type (
// Context represents context for the current request. It holds request and
// response objects, path parameters, data and registered handler.
Context struct {
context.Context
Context interface {
xcontext.Context
Request() *http.Request
Response() *Response
Socket() *websocket.Conn
Path() string
P(int) string
Param(string) string
Query(string) string
Form(string) string
Set(string, interface{})
Get(string) interface{}
Bind(interface{}) error
Render(int, string, interface{}) error
HTML(int, string) error
String(int, string) error
JSON(int, interface{}) error
JSONIndent(int, interface{}, string, string) error
JSONP(int, string, interface{}) error
XML(int, interface{}) error
XMLIndent(int, interface{}, string, string) error
File(string, string, bool) error
NoContent(int) error
Redirect(int, string) error
Error(err error)
Echo() *Echo
}
context struct {
request *http.Request
response *Response
socket *websocket.Conn
@ -29,12 +57,13 @@ type (
store store
echo *Echo
}
store map[string]interface{}
)
// NewContext creates a Context object.
func NewContext(req *http.Request, res *Response, e *Echo) *Context {
return &Context{
func NewContext(req *http.Request, res *Response, e *Echo) Context {
return &context{
request: req,
response: res,
echo: e,
@ -43,28 +72,44 @@ func NewContext(req *http.Request, res *Response, e *Echo) *Context {
}
}
func (c *context) Deadline() (deadline time.Time, ok bool) {
return
}
func (c *context) Done() <-chan struct{} {
return nil
}
func (c *context) Err() error {
return nil
}
func (c *context) Value(key interface{}) interface{} {
return nil
}
// Request returns *http.Request.
func (c *Context) Request() *http.Request {
func (c *context) Request() *http.Request {
return c.request
}
// Response returns *Response.
func (c *Context) Response() *Response {
func (c *context) Response() *Response {
return c.response
}
// Socket returns *websocket.Conn.
func (c *Context) Socket() *websocket.Conn {
func (c *context) Socket() *websocket.Conn {
return c.socket
}
// Path returns the registered path for the handler.
func (c *Context) Path() string {
func (c *context) Path() string {
return c.path
}
// P returns path parameter by index.
func (c *Context) P(i int) (value string) {
func (c *context) P(i int) (value string) {
l := len(c.pnames)
if i < l {
value = c.pvalues[i]
@ -73,7 +118,7 @@ func (c *Context) P(i int) (value string) {
}
// Param returns path parameter by name.
func (c *Context) Param(name string) (value string) {
func (c *context) Param(name string) (value string) {
l := len(c.pnames)
for i, n := range c.pnames {
if n == name && i < l {
@ -85,7 +130,7 @@ func (c *Context) Param(name string) (value string) {
}
// Query returns query parameter by name.
func (c *Context) Query(name string) string {
func (c *context) Query(name string) string {
if c.query == nil {
c.query = c.request.URL.Query()
}
@ -93,17 +138,17 @@ func (c *Context) Query(name string) string {
}
// Form returns form parameter by name.
func (c *Context) Form(name string) string {
func (c *context) Form(name string) string {
return c.request.FormValue(name)
}
// Get retrieves data from the context.
func (c *Context) Get(key string) interface{} {
func (c *context) Get(key string) interface{} {
return c.store[key]
}
// Set saves data in the context.
func (c *Context) Set(key string, val interface{}) {
func (c *context) Set(key string, val interface{}) {
if c.store == nil {
c.store = make(store)
}
@ -112,13 +157,13 @@ func (c *Context) Set(key string, val interface{}) {
// Bind binds the request body into specified type `i`. The default binder does
// it based on Content-Type header.
func (c *Context) Bind(i interface{}) error {
func (c *context) Bind(i interface{}) error {
return c.echo.binder.Bind(c.request, i)
}
// Render renders a template with data and sends a text/html response with status
// code. Templates can be registered using `Echo.SetRenderer()`.
func (c *Context) Render(code int, name string, data interface{}) (err error) {
func (c *context) Render(code int, name string, data interface{}) (err error) {
if c.echo.renderer == nil {
return RendererNotRegistered
}
@ -133,7 +178,7 @@ func (c *Context) Render(code int, name string, data interface{}) (err error) {
}
// HTML sends an HTTP response with status code.
func (c *Context) HTML(code int, html string) (err error) {
func (c *context) HTML(code int, html string) (err error) {
c.response.Header().Set(ContentType, TextHTMLCharsetUTF8)
c.response.WriteHeader(code)
c.response.Write([]byte(html))
@ -141,7 +186,7 @@ func (c *Context) HTML(code int, html string) (err error) {
}
// String sends a string response with status code.
func (c *Context) String(code int, s string) (err error) {
func (c *context) String(code int, s string) (err error) {
c.response.Header().Set(ContentType, TextPlainCharsetUTF8)
c.response.WriteHeader(code)
c.response.Write([]byte(s))
@ -149,7 +194,7 @@ func (c *Context) String(code int, s string) (err error) {
}
// JSON sends a JSON response with status code.
func (c *Context) JSON(code int, i interface{}) (err error) {
func (c *context) JSON(code int, i interface{}) (err error) {
b, err := json.Marshal(i)
if err != nil {
return err
@ -161,7 +206,7 @@ func (c *Context) JSON(code int, i interface{}) (err error) {
}
// JSONIndent sends a JSON response with status code, but it applies prefix and indent to format the output.
func (c *Context) JSONIndent(code int, i interface{}, prefix string, indent string) (err error) {
func (c *context) JSONIndent(code int, i interface{}, prefix string, indent string) (err error) {
b, err := json.MarshalIndent(i, prefix, indent)
if err != nil {
return err
@ -170,7 +215,7 @@ func (c *Context) JSONIndent(code int, i interface{}, prefix string, indent stri
return
}
func (c *Context) json(code int, b []byte) {
func (c *context) json(code int, b []byte) {
c.response.Header().Set(ContentType, ApplicationJSONCharsetUTF8)
c.response.WriteHeader(code)
c.response.Write(b)
@ -178,7 +223,7 @@ func (c *Context) json(code int, b []byte) {
// JSONP sends a JSONP response with status code. It uses `callback` to construct
// the JSONP payload.
func (c *Context) JSONP(code int, callback string, i interface{}) (err error) {
func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
b, err := json.Marshal(i)
if err != nil {
return err
@ -192,7 +237,7 @@ func (c *Context) JSONP(code int, callback string, i interface{}) (err error) {
}
// XML sends an XML response with status code.
func (c *Context) XML(code int, i interface{}) (err error) {
func (c *context) XML(code int, i interface{}) (err error) {
b, err := xml.Marshal(i)
if err != nil {
return err
@ -205,7 +250,7 @@ func (c *Context) XML(code int, i interface{}) (err error) {
}
// XMLIndent sends an XML response with status code, but it applies prefix and indent to format the output.
func (c *Context) XMLIndent(code int, i interface{}, prefix string, indent string) (err error) {
func (c *context) XMLIndent(code int, i interface{}, prefix string, indent string) (err error) {
b, err := xml.MarshalIndent(i, prefix, indent)
if err != nil {
return err
@ -214,7 +259,7 @@ func (c *Context) XMLIndent(code int, i interface{}, prefix string, indent strin
return
}
func (c *Context) xml(code int, b []byte) {
func (c *context) xml(code int, b []byte) {
c.response.Header().Set(ContentType, ApplicationXMLCharsetUTF8)
c.response.WriteHeader(code)
c.response.Write([]byte(xml.Header))
@ -224,7 +269,7 @@ func (c *Context) xml(code int, b []byte) {
// File sends a response with the content of the file. If `attachment` is set
// to true, the client is prompted to save the file with provided `name`,
// name can be empty, in that case name of the file is used.
func (c *Context) File(path, name string, attachment bool) (err error) {
func (c *context) File(path, name string, attachment bool) (err error) {
dir, file := filepath.Split(path)
if attachment {
c.response.Header().Set(ContentDisposition, "attachment; filename="+name)
@ -236,13 +281,13 @@ func (c *Context) File(path, name string, attachment bool) (err error) {
}
// NoContent sends a response with no body and a status code.
func (c *Context) NoContent(code int) error {
func (c *context) NoContent(code int) error {
c.response.WriteHeader(code)
return nil
}
// Redirect redirects the request using http.Redirect with status code.
func (c *Context) Redirect(code int, url string) error {
func (c *context) Redirect(code int, url string) error {
if code < http.StatusMultipleChoices || code > http.StatusTemporaryRedirect {
return InvalidRedirectCode
}
@ -251,16 +296,16 @@ func (c *Context) Redirect(code int, url string) error {
}
// Error invokes the registered HTTP error handler. Generally used by middleware.
func (c *Context) Error(err error) {
func (c *context) Error(err error) {
c.echo.httpErrorHandler(err, c)
}
// Echo returns the `Echo` instance.
func (c *Context) Echo() *Echo {
func (c *context) Echo() *Echo {
return c.echo
}
func (c *Context) reset(r *http.Request, w http.ResponseWriter, e *Echo) {
func (c *context) reset(r *http.Request, w http.ResponseWriter, e *Echo) {
c.request = r
c.response.reset(w, e)
c.query = nil

View File

@ -10,8 +10,6 @@ import (
"strings"
"golang.org/x/net/context"
"net/url"
"encoding/xml"
@ -40,7 +38,7 @@ func TestContext(t *testing.T) {
e := New()
req, _ := http.NewRequest(POST, "/", strings.NewReader(userJSON))
rec := httptest.NewRecorder()
c := NewContext(req, NewResponse(rec, e), e)
c := NewContext(req, NewResponse(rec, e), e).(*context)
// Request
assert.NotNil(t, c.Request())
@ -97,7 +95,7 @@ func TestContext(t *testing.T) {
// JSON
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.JSON(http.StatusOK, user{"1", "Joe"})
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -107,14 +105,14 @@ func TestContext(t *testing.T) {
// JSON (error)
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
val := make(chan bool)
err = c.JSON(http.StatusOK, val)
assert.Error(t, err)
// JSONIndent
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.JSONIndent(http.StatusOK, user{"1", "Joe"}, "_", "?")
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -124,13 +122,13 @@ func TestContext(t *testing.T) {
// JSONIndent (error)
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.JSONIndent(http.StatusOK, nonMarshallableChannel, "_", "?")
assert.Error(t, err)
// JSONP
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
callback := "callback"
err = c.JSONP(http.StatusOK, callback, user{"1", "Joe"})
if assert.NoError(t, err) {
@ -141,7 +139,7 @@ func TestContext(t *testing.T) {
// XML
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.XML(http.StatusOK, user{"1", "Joe"})
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -151,13 +149,13 @@ func TestContext(t *testing.T) {
// XML (error)
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.XML(http.StatusOK, nonMarshallableChannel)
assert.Error(t, err)
// XMLIndent
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.XMLIndent(http.StatusOK, user{"1", "Joe"}, "_", "?")
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -167,13 +165,13 @@ func TestContext(t *testing.T) {
// XMLIndent (error)
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.XMLIndent(http.StatusOK, nonMarshallableChannel, "_", "?")
assert.Error(t, err)
// String
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.String(http.StatusOK, "Hello, World!")
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -183,7 +181,7 @@ func TestContext(t *testing.T) {
// HTML
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.HTML(http.StatusOK, "Hello, <strong>World!</strong>")
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -193,7 +191,7 @@ func TestContext(t *testing.T) {
// File
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.File("test/fixture/walle.png", "", false)
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -202,7 +200,7 @@ func TestContext(t *testing.T) {
// File as attachment
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
err = c.File("test/fixture/walle.png", "WALLE.PNG", true)
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
@ -212,18 +210,18 @@ func TestContext(t *testing.T) {
// NoContent
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
c.NoContent(http.StatusOK)
assert.Equal(t, http.StatusOK, c.response.status)
// Redirect
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
assert.Equal(t, nil, c.Redirect(http.StatusMovedPermanently, "http://labstack.github.io/echo"))
// Error
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec, e), e)
c = NewContext(req, NewResponse(rec, e), e).(*context)
c.Error(errors.New("error"))
assert.Equal(t, http.StatusInternalServerError, c.response.status)
@ -236,12 +234,12 @@ func TestContextPath(t *testing.T) {
r := e.Router()
r.Add(GET, "/users/:id", nil, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
r.Find(GET, "/users/1", c)
assert.Equal(t, c.Path(), "/users/:id")
r.Add(GET, "/users/:uid/files/:fid", nil, e)
c = NewContext(nil, nil, e)
c = NewContext(nil, nil, e).(*context)
r.Find(GET, "/users/1/files/1", c)
assert.Equal(t, c.Path(), "/users/:uid/files/:fid")
}
@ -275,12 +273,12 @@ func TestContextForm(t *testing.T) {
}
func TestContextNetContext(t *testing.T) {
c := new(Context)
c.Context = context.WithValue(nil, "key", "val")
assert.Equal(t, "val", c.Value("key"))
// c := new(context)
// c.Context = xcontext.WithValue(nil, "key", "val")
// assert.Equal(t, "val", c.Value("key"))
}
func testBind(t *testing.T, c *Context, ct string) {
func testBind(t *testing.T, c *context, ct string) {
c.request.Header.Set(ContentType, ct)
u := new(user)
err := c.Bind(u)

71
echo.go
View File

@ -54,10 +54,10 @@ type (
Middleware interface{}
MiddlewareFunc func(HandlerFunc) HandlerFunc
Handler interface{}
HandlerFunc func(*Context) error
HandlerFunc func(Context) error
// HTTPErrorHandler is a centralized HTTP error handler.
HTTPErrorHandler func(error, *Context)
HTTPErrorHandler func(error, Context)
// Binder is the interface that wraps the Bind method.
Binder interface {
@ -173,11 +173,11 @@ var (
// Error handlers
//----------------
notFoundHandler = func(c *Context) error {
notFoundHandler = func(c Context) error {
return NewHTTPError(http.StatusNotFound)
}
methodNotAllowedHandler = func(c *Context) error {
methodNotAllowedHandler = func(c Context) error {
return NewHTTPError(http.StatusMethodNotAllowed)
}
@ -197,7 +197,8 @@ func New() (e *Echo) {
//----------
e.HTTP2(true)
e.defaultHTTPErrorHandler = func(err error, c *Context) {
e.defaultHTTPErrorHandler = func(err error, c Context) {
x := c.(*context)
code := http.StatusInternalServerError
msg := http.StatusText(code)
if he, ok := err.(*HTTPError); ok {
@ -207,8 +208,8 @@ func New() (e *Echo) {
if e.debug {
msg = err.Error()
}
if !c.response.committed {
http.Error(c.response, msg, code)
if !x.response.committed {
http.Error(x.response, msg, code)
}
e.logger.Error(err)
}
@ -253,7 +254,7 @@ func (e *Echo) HTTP2(on bool) {
}
// DefaultHTTPErrorHandler invokes the default HTTP error handler.
func (e *Echo) DefaultHTTPErrorHandler(err error, c *Context) {
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context) {
e.defaultHTTPErrorHandler(err, c)
}
@ -362,15 +363,16 @@ func (e *Echo) Match(methods []string, path string, h Handler) {
// WebSocket adds a WebSocket route > handler to the router.
func (e *Echo) WebSocket(path string, h HandlerFunc) {
e.Get(path, func(c *Context) (err error) {
e.Get(path, func(c Context) (err error) {
x, _ := c.(*context)
wss := websocket.Server{
Handler: func(ws *websocket.Conn) {
c.socket = ws
c.response.status = http.StatusSwitchingProtocols
x.socket = ws
x.response.status = http.StatusSwitchingProtocols
err = h(c)
},
}
wss.ServeHTTP(c.response, c.request)
wss.ServeHTTP(x.response, x.request)
return err
})
}
@ -403,20 +405,21 @@ func (e *Echo) Static(path, dir string) {
// ServeDir serves files from a directory.
func (e *Echo) ServeDir(path, dir string) {
e.Get(path+"*", func(c *Context) error {
e.Get(path+"*", func(c Context) error {
return e.serveFile(dir, c.P(0), c) // Param `_*`
})
}
// ServeFile serves a file.
func (e *Echo) ServeFile(path, file string) {
e.Get(path, func(c *Context) error {
e.Get(path, func(c Context) error {
dir, file := filepath.Split(file)
return e.serveFile(dir, file, c)
})
}
func (e *Echo) serveFile(dir, file string, c *Context) (err error) {
func (e *Echo) serveFile(dir, file string, c Context) (err error) {
x := c.(*context)
fs := http.Dir(dir)
f, err := fs.Open(file)
if err != nil {
@ -445,11 +448,11 @@ func (e *Echo) serveFile(dir, file string, c *Context) (err error) {
fi, _ = f.Stat() // Index file stat
}
http.ServeContent(c.response, c.request, fi.Name(), fi.ModTime(), f)
http.ServeContent(x.response, x.request, fi.Name(), fi.ModTime(), f)
return
}
func listDir(d http.File, c *Context) (err error) {
func listDir(d http.File, c Context) (err error) {
dirs, err := d.Readdir(-1)
if err != nil {
return err
@ -529,7 +532,7 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
e.hook(w, r)
}
c := e.pool.Get().(*Context)
c := e.pool.Get().(*context)
h, e := e.router.Find(r.Method, r.URL.Path, c)
c.reset(r, w, e)
@ -624,16 +627,17 @@ func wrapMiddleware(m Middleware) MiddlewareFunc {
return m
case HandlerFunc:
return wrapHandlerFuncMW(m)
case func(*Context) error:
case func(Context) error:
return wrapHandlerFuncMW(m)
case func(http.Handler) http.Handler:
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) (err error) {
return func(c Context) (err error) {
x := c.(*context)
m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c.response.writer = w
c.request = r
x.response.writer = w
x.request = r
err = h(c)
})).ServeHTTP(c.response.writer, c.request)
})).ServeHTTP(x.response.writer, x.request)
return
}
}
@ -649,7 +653,7 @@ func wrapMiddleware(m Middleware) MiddlewareFunc {
// wrapHandlerFuncMW wraps HandlerFunc middleware.
func wrapHandlerFuncMW(m HandlerFunc) MiddlewareFunc {
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) error {
return func(c Context) error {
if err := m(c); err != nil {
return err
}
@ -661,9 +665,10 @@ func wrapHandlerFuncMW(m HandlerFunc) MiddlewareFunc {
// wrapHTTPHandlerFuncMW wraps http.HandlerFunc middleware.
func wrapHTTPHandlerFuncMW(m http.HandlerFunc) MiddlewareFunc {
return func(h HandlerFunc) HandlerFunc {
return func(c *Context) error {
if !c.response.committed {
m.ServeHTTP(c.response.writer, c.request)
return func(c Context) error {
x := c.(*context)
if !x.response.committed {
m.ServeHTTP(x.response.writer, x.request)
}
return h(c)
}
@ -675,16 +680,18 @@ func wrapHandler(h Handler) HandlerFunc {
switch h := h.(type) {
case HandlerFunc:
return h
case func(*Context) error:
case func(Context) error:
return h
case http.Handler, http.HandlerFunc:
return func(c *Context) error {
h.(http.Handler).ServeHTTP(c.response, c.request)
return func(c Context) error {
x := c.(*context)
h.(http.Handler).ServeHTTP(x.response, x.request)
return nil
}
case func(http.ResponseWriter, *http.Request):
return func(c *Context) error {
h(c.response, c.request)
return func(c Context) error {
x := c.(*context)
h(x.response, x.request)
return nil
}
default:

View File

@ -94,7 +94,7 @@ func TestEchoMiddleware(t *testing.T) {
// echo.MiddlewareFunc
e.Use(MiddlewareFunc(func(h HandlerFunc) HandlerFunc {
return func(c *Context) error {
return func(c Context) error {
buf.WriteString("a")
return h(c)
}
@ -102,20 +102,20 @@ func TestEchoMiddleware(t *testing.T) {
// func(echo.HandlerFunc) echo.HandlerFunc
e.Use(func(h HandlerFunc) HandlerFunc {
return func(c *Context) error {
return func(c Context) error {
buf.WriteString("b")
return h(c)
}
})
// echo.HandlerFunc
e.Use(HandlerFunc(func(c *Context) error {
e.Use(HandlerFunc(func(c Context) error {
buf.WriteString("c")
return nil
}))
// func(*echo.Context) error
e.Use(func(c *Context) error {
e.Use(func(c Context) error {
buf.WriteString("d")
return nil
})
@ -149,7 +149,7 @@ func TestEchoMiddleware(t *testing.T) {
})
// Route
e.Get("/", func(c *Context) error {
e.Get("/", func(c Context) error {
return c.String(http.StatusOK, "Hello!")
})
@ -159,7 +159,7 @@ func TestEchoMiddleware(t *testing.T) {
assert.Equal(t, "Hello!", b)
// Error
e.Use(func(*Context) error {
e.Use(func(Context) error {
return errors.New("error")
})
c, b = request(GET, "/", e)
@ -170,12 +170,12 @@ func TestEchoHandler(t *testing.T) {
e := New()
// HandlerFunc
e.Get("/1", HandlerFunc(func(c *Context) error {
e.Get("/1", HandlerFunc(func(c Context) error {
return c.String(http.StatusOK, "1")
}))
// func(*echo.Context) error
e.Get("/2", func(c *Context) error {
e.Get("/2", func(c Context) error {
return c.String(http.StatusOK, "2")
})
@ -248,22 +248,23 @@ func TestEchoTrace(t *testing.T) {
func TestEchoAny(t *testing.T) { // JFC
e := New()
e.Any("/", 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}, "/", func(c *Context) error {
e.Match([]string{GET, POST}, "/", func(c Context) error {
return c.String(http.StatusOK, "Match")
})
}
func TestEchoWebSocket(t *testing.T) {
e := New()
e.WebSocket("/ws", func(c *Context) error {
c.socket.Write([]byte("test"))
e.WebSocket("/ws", func(c Context) error {
x := c.(*context)
x.socket.Write([]byte("test"))
return nil
})
srv := httptest.NewServer(e)
@ -302,7 +303,7 @@ func TestEchoURL(t *testing.T) {
func TestEchoRoutes(t *testing.T) {
e := New()
h := func(*Context) error { return nil }
h := func(Context) error { return nil }
routes := []Route{
{GET, "/users/:user/events", h},
{GET, "/users/:user/events/public", h},
@ -322,7 +323,7 @@ func TestEchoRoutes(t *testing.T) {
func TestEchoGroup(t *testing.T) {
e := New()
buf := new(bytes.Buffer)
e.Use(func(*Context) error {
e.Use(func(Context) error {
buf.WriteString("0")
return nil
})
@ -336,7 +337,7 @@ func TestEchoGroup(t *testing.T) {
// Group
g1 := e.Group("/group1")
g1.Use(func(*Context) error {
g1.Use(func(Context) error {
buf.WriteString("1")
return nil
})
@ -352,7 +353,7 @@ func TestEchoGroup(t *testing.T) {
// Nested groups
g3 := e.Group("/group3")
g4 := g3.Group("/group4")
g4.Get("/", func(c *Context) error {
g4.Get("/", func(c Context) error {
return c.NoContent(http.StatusOK)
})
@ -384,7 +385,7 @@ func TestEchoNotFound(t *testing.T) {
func TestEchoMethodNotAllowed(t *testing.T) {
e := New()
e.Get("/", func(c *Context) error {
e.Get("/", func(c Context) error {
return c.String(http.StatusOK, "Echo!")
})
r, _ := http.NewRequest(POST, "/", nil)
@ -408,7 +409,7 @@ func TestEchoServer(t *testing.T) {
func TestEchoHook(t *testing.T) {
e := New()
e.Get("/test", func(c *Context) error {
e.Get("/test", func(c Context) error {
return c.NoContent(http.StatusNoContent)
})
e.Hook(func(w http.ResponseWriter, r *http.Request) {
@ -427,7 +428,7 @@ func TestEchoHook(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(func(c *Context) error {
h := reflect.ValueOf(func(c Context) error {
return c.String(http.StatusOK, method)
})
i := interface{}(e)

View File

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

View File

@ -20,7 +20,7 @@ const (
// For valid credentials it calls the next handler.
// For invalid credentials, it sends "401 - Unauthorized" response.
func BasicAuth(fn BasicValidateFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
return func(c echo.Context) error {
// Skip WebSocket
if (c.Request().Header.Get(echo.Upgrade)) == echo.WebSocket {
return nil

View File

@ -51,7 +51,7 @@ func Gzip() echo.MiddlewareFunc {
scheme := "gzip"
return func(h echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
return func(c echo.Context) error {
c.Response().Header().Add(echo.Vary, echo.AcceptEncoding)
if strings.Contains(c.Request().Header.Get(echo.AcceptEncoding), scheme) {
w := writerPool.Get().(*gzip.Writer)

View File

@ -37,7 +37,7 @@ func TestGzip(t *testing.T) {
req, _ := http.NewRequest(echo.GET, "/", nil)
rec := httptest.NewRecorder()
c := echo.NewContext(req, echo.NewResponse(rec, e), e)
h := func(c *echo.Context) error {
h := func(c echo.Context) error {
c.Response().Write([]byte("test")) // For Content-Type sniffing
return nil
}
@ -125,7 +125,7 @@ func BenchmarkGzip(b *testing.B) {
b.StopTimer()
b.ReportAllocs()
h := func(c *echo.Context) error {
h := func(c echo.Context) error {
c.Response().Write([]byte("test")) // For Content-Type sniffing
return nil
}

View File

@ -10,7 +10,7 @@ import (
func Logger() echo.MiddlewareFunc {
return func(h echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
return func(c echo.Context) error {
req := c.Request()
res := c.Response()
logger := c.Echo().Logger()

View File

@ -19,7 +19,7 @@ func TestLogger(t *testing.T) {
c := echo.NewContext(req, echo.NewResponse(rec, e), e)
// Status 2xx
h := func(c *echo.Context) error {
h := func(c echo.Context) error {
return c.String(http.StatusOK, "test")
}
Logger()(h)(c)
@ -27,7 +27,7 @@ func TestLogger(t *testing.T) {
// Status 3xx
rec = httptest.NewRecorder()
c = echo.NewContext(req, echo.NewResponse(rec, e), e)
h = func(c *echo.Context) error {
h = func(c echo.Context) error {
return c.String(http.StatusTemporaryRedirect, "test")
}
Logger()(h)(c)
@ -35,7 +35,7 @@ func TestLogger(t *testing.T) {
// Status 4xx
rec = httptest.NewRecorder()
c = echo.NewContext(req, echo.NewResponse(rec, e), e)
h = func(c *echo.Context) error {
h = func(c echo.Context) error {
return c.String(http.StatusNotFound, "test")
}
Logger()(h)(c)
@ -44,7 +44,7 @@ func TestLogger(t *testing.T) {
req, _ = http.NewRequest(echo.GET, "", nil)
rec = httptest.NewRecorder()
c = echo.NewContext(req, echo.NewResponse(rec, e), e)
h = func(c *echo.Context) error {
h = func(c echo.Context) error {
return errors.New("error")
}
Logger()(h)(c)
@ -58,7 +58,7 @@ func TestLoggerIPAddress(t *testing.T) {
buf := new(bytes.Buffer)
e.Logger().SetOutput(buf)
ip := "127.0.0.1"
h := func(c *echo.Context) error {
h := func(c echo.Context) error {
return c.String(http.StatusOK, "test")
}

View File

@ -13,7 +13,7 @@ import (
func Recover() echo.MiddlewareFunc {
// TODO: Provide better stack trace `https://github.com/go-errors/errors` `https://github.com/docker/libcontainer/tree/master/stacktrace`
return func(h echo.HandlerFunc) echo.HandlerFunc {
return func(c *echo.Context) error {
return func(c echo.Context) error {
defer func() {
if err := recover(); err != nil {
trace := make([]byte, 1<<16)

View File

@ -15,7 +15,7 @@ func TestRecover(t *testing.T) {
req, _ := http.NewRequest(echo.GET, "/", nil)
rec := httptest.NewRecorder()
c := echo.NewContext(req, echo.NewResponse(rec, e), e)
h := func(c *echo.Context) error {
h := func(c echo.Context) error {
panic("test")
}
Recover()(h)(c)

View File

@ -275,7 +275,7 @@ func (n *node) check405() HandlerFunc {
return notFoundHandler
}
func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo) {
func (r *Router) Find(method, path string, x *context) (h HandlerFunc, e *Echo) {
h = notFoundHandler
e = r.echo
cn := r.tree // Current node as root
@ -358,7 +358,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo
i, l := 0, len(search)
for ; i < l && search[i] != '/'; i++ {
}
ctx.pvalues[n] = search[:i]
x.pvalues[n] = search[:i]
n++
search = search[i:]
continue
@ -371,13 +371,13 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo
// Not found
return
}
ctx.pvalues[len(cn.pnames)-1] = search
x.pvalues[len(cn.pnames)-1] = search
goto End
}
End:
ctx.path = cn.ppath
ctx.pnames = cn.pnames
x.path = cn.ppath
x.pnames = cn.pnames
h = cn.findHandler(method)
if cn.echo != nil {
e = cn.echo
@ -392,7 +392,7 @@ End:
if cn = cn.findChildByKind(mkind); cn == nil {
return
}
ctx.pvalues[len(cn.pnames)-1] = ""
x.pvalues[len(cn.pnames)-1] = ""
if h = cn.findHandler(method); h == nil {
h = cn.check405()
}
@ -401,7 +401,7 @@ End:
}
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := r.echo.pool.Get().(*Context)
c := r.echo.pool.Get().(*context)
h, _ := r.Find(req.Method, req.URL.Path, c)
c.reset(req, w, r.echo)
if err := h(c); err != nil {

View File

@ -278,12 +278,12 @@ func TestRouterStatic(t *testing.T) {
e := New()
r := e.router
path := "/folders/a/files/echo.gif"
r.Add(GET, path, func(c *Context) error {
r.Add(GET, path, func(c Context) error {
c.Set("path", path)
return nil
}, e)
c := NewContext(nil, nil, e)
h, _ := r.Find(GET, path, c)
h, _ := r.Find(GET, path, c.(*context))
if assert.NotNil(t, h) {
h(c)
assert.Equal(t, path, c.Get("path"))
@ -293,10 +293,10 @@ func TestRouterStatic(t *testing.T) {
func TestRouterParam(t *testing.T) {
e := New()
r := e.router
r.Add(GET, "/users/:id", func(c *Context) error {
r.Add(GET, "/users/:id", func(c Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
h, _ := r.Find(GET, "/users/1", c)
if assert.NotNil(t, h) {
assert.Equal(t, "1", c.P(0))
@ -306,10 +306,10 @@ func TestRouterParam(t *testing.T) {
func TestRouterTwoParam(t *testing.T) {
e := New()
r := e.router
r.Add(GET, "/users/:uid/files/:fid", func(*Context) error {
r.Add(GET, "/users/:uid/files/:fid", func(Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
h, _ := r.Find(GET, "/users/1/files/1", c)
if assert.NotNil(t, h) {
@ -323,16 +323,16 @@ func TestRouterMatchAny(t *testing.T) {
r := e.router
// Routes
r.Add(GET, "/", func(*Context) error {
r.Add(GET, "/", func(Context) error {
return nil
}, e)
r.Add(GET, "/*", func(*Context) error {
r.Add(GET, "/*", func(Context) error {
return nil
}, e)
r.Add(GET, "/users/*", func(*Context) error {
r.Add(GET, "/users/*", func(Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
h, _ := r.Find(GET, "/", c)
if assert.NotNil(t, h) {
@ -353,10 +353,10 @@ func TestRouterMatchAny(t *testing.T) {
func TestRouterMicroParam(t *testing.T) {
e := New()
r := e.router
r.Add(GET, "/:a/:b/:c", func(c *Context) error {
r.Add(GET, "/:a/:b/:c", func(c Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
h, _ := r.Find(GET, "/1/2/3", c)
if assert.NotNil(t, h) {
assert.Equal(t, "1", c.P(0))
@ -370,10 +370,10 @@ func TestRouterMixParamMatchAny(t *testing.T) {
r := e.router
// Route
r.Add(GET, "/users/:id/*", func(c *Context) error {
r.Add(GET, "/users/:id/*", func(c Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
h, _ := r.Find(GET, "/users/joe/comments", c)
if assert.NotNil(t, h) {
@ -387,14 +387,14 @@ func TestRouterMultiRoute(t *testing.T) {
r := e.router
// Routes
r.Add(GET, "/users", func(c *Context) error {
r.Add(GET, "/users", func(c Context) error {
c.Set("path", "/users")
return nil
}, e)
r.Add(GET, "/users/:id", func(c *Context) error {
r.Add(GET, "/users/:id", func(c Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
// Route > /users
h, _ := r.Find(GET, "/users", c)
@ -422,35 +422,35 @@ func TestRouterPriority(t *testing.T) {
r := e.router
// Routes
r.Add(GET, "/users", func(c *Context) error {
r.Add(GET, "/users", func(c Context) error {
c.Set("a", 1)
return nil
}, e)
r.Add(GET, "/users/new", func(c *Context) error {
r.Add(GET, "/users/new", func(c Context) error {
c.Set("b", 2)
return nil
}, e)
r.Add(GET, "/users/:id", func(c *Context) error {
r.Add(GET, "/users/:id", func(c Context) error {
c.Set("c", 3)
return nil
}, e)
r.Add(GET, "/users/dew", func(c *Context) error {
r.Add(GET, "/users/dew", func(c Context) error {
c.Set("d", 4)
return nil
}, e)
r.Add(GET, "/users/:id/files", func(c *Context) error {
r.Add(GET, "/users/:id/files", func(c Context) error {
c.Set("e", 5)
return nil
}, e)
r.Add(GET, "/users/newsee", func(c *Context) error {
r.Add(GET, "/users/newsee", func(c Context) error {
c.Set("f", 6)
return nil
}, e)
r.Add(GET, "/users/*", func(c *Context) error {
r.Add(GET, "/users/*", func(c Context) error {
c.Set("g", 7)
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
// Route > /users
h, _ := r.Find(GET, "/users", c)
@ -508,17 +508,17 @@ func TestRouterParamNames(t *testing.T) {
r := e.router
// Routes
r.Add(GET, "/users", func(c *Context) error {
r.Add(GET, "/users", func(c Context) error {
c.Set("path", "/users")
return nil
}, e)
r.Add(GET, "/users/:id", func(c *Context) error {
r.Add(GET, "/users/:id", func(c Context) error {
return nil
}, e)
r.Add(GET, "/users/:uid/files/:fid", func(c *Context) error {
r.Add(GET, "/users/:uid/files/:fid", func(c Context) error {
return nil
}, e)
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
// Route > /users
h, _ := r.Find(GET, "/users", c)
@ -549,11 +549,11 @@ func TestRouterAPI(t *testing.T) {
r := e.router
for _, route := range api {
r.Add(route.Method, route.Path, func(c *Context) error {
r.Add(route.Method, route.Path, func(c Context) error {
return nil
}, e)
}
c := NewContext(nil, nil, e)
c := NewContext(nil, nil, e).(*context)
for _, route := range api {
h, _ := r.Find(route.Method, route.Path, c)
if assert.NotNil(t, h) {
@ -571,7 +571,7 @@ func TestRouterServeHTTP(t *testing.T) {
e := New()
r := e.router
r.Add(GET, "/users", func(*Context) error {
r.Add(GET, "/users", func(Context) error {
return nil
}, e)