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 2015-04-28 23:09:30 -07:00
parent 6a1ba5883c
commit 02ca5e4443
5 changed files with 94 additions and 59 deletions

View File

@ -65,19 +65,19 @@ func (c *Context) JSON(code int, v interface{}) error {
}
// String sends a text/plain response with status code.
func (c *Context) String(code int, s string) (err error) {
func (c *Context) String(code int, s string) error {
c.Response.Header().Set(HeaderContentType, MIMEText+"; charset=utf-8")
c.Response.WriteHeader(code)
_, err = c.Response.Write([]byte(s))
return
_, err := c.Response.Write([]byte(s))
return err
}
// HTML sends a text/html response with status code.
func (c *Context) HTML(code int, html string) (err error) {
func (c *Context) HTML(code int, html string) error {
c.Response.Header().Set(HeaderContentType, MIMEHTML+"; charset=utf-8")
c.Response.WriteHeader(code)
_, err = c.Response.Write([]byte(html))
return
_, err := c.Response.Write([]byte(html))
return err
}
// NoContent sends a response with no body and a status code.

View File

@ -144,7 +144,7 @@ func New() (e *Echo) {
return
}
// Group creates a new sub router with prefix and inherits all properties from
// Group creates a new sub router with prefix. It inherits all properties from
// the parent. Passing middleware overrides parent middleware.
func (e *Echo) Group(pfx string, m ...Middleware) *Echo {
g := *e

View File

@ -13,11 +13,11 @@ type (
prefix string
parent *node
children children
pchild *node // Param child
cchild *node // Catch-all child
handler HandlerFunc
pnames []string
echo *Echo
// pchild *node // Param child
// mchild *node // Match-any child
handler HandlerFunc
pnames []string
echo *Echo
}
ntype uint8
children []*node
@ -26,7 +26,7 @@ type (
const (
stype ntype = iota
ptype
ctype
mtype
)
func NewRouter(e *Echo) (r *router) {
@ -64,9 +64,8 @@ func (r *router) Add(method, path string, h HandlerFunc, echo *Echo) {
}
r.insert(method, path[:i], nil, ptype, pnames, echo)
} else if path[i] == '*' {
r.insert(method, path[:i], nil, stype, nil, echo)
pnames = append(pnames, "_name")
r.insert(method, path[:l], h, ctype, pnames, echo)
r.insert(method, path[:i], h, mtype, pnames, echo)
return
}
}
@ -201,7 +200,7 @@ func (n *node) findPchild() *node {
func (n *node) findCchild() *node {
for _, c := range n.children {
if c.typ == ctype {
if c.typ == mtype {
return c
}
}
@ -226,16 +225,21 @@ func (r *router) Find(method, path string, ctx *Context) (h HandlerFunc, echo *E
c := new(node) // Child node
n := 0 // Param counter
// Search order static > param > catch-all
// Search order static > param > match-any
for {
if search == "" || search == cn.prefix {
if cn.handler != nil {
// Found
h = cn.handler
ctx.pnames = cn.pnames
echo = cn.echo
return
if search == "" || search == cn.prefix || cn.typ == mtype {
// Found
h = cn.handler
echo = cn.echo
ctx.pnames = cn.pnames
// Match-any
if cn.typ == mtype {
println(search, cn.prefix)
ctx.pvalues[0] = search[len(cn.prefix):]
}
return
}
pl := len(cn.prefix)
@ -247,11 +251,6 @@ func (r *router) Find(method, path string, ctx *Context) (h HandlerFunc, echo *E
goto Up
}
// Catch-all with empty value
if len(search) == 0 {
goto CatchAll
}
// Static node
c = cn.findSchild(search[0])
if c != nil {
@ -274,17 +273,6 @@ func (r *router) Find(method, path string, ctx *Context) (h HandlerFunc, echo *E
continue
}
// Catch-all node
CatchAll:
// c = cn.cchild
c = cn.findCchild()
if c != nil {
cn = c
ctx.pvalues[n] = search
search = "" // End search
continue
}
Up:
tn := cn // Save current node
cn = cn.parent

View File

@ -326,19 +326,24 @@ func TestRouterTwoParam(t *testing.T) {
return nil
}, nil)
h, _ := r.Find(GET, "/users/1/files/1", context)
if h == nil {
t.Fatal("handler not found")
}
if context.pvalues[0] != "1" {
t.Error("param uid should be 1")
}
if context.pvalues[1] != "1" {
t.Error("param fid should be 1")
// h, _ := r.Find(GET, "/users/1/files/1", context)
// if h == nil {
// t.Fatal("handler not found")
// }
// if context.pvalues[0] != "1" {
// t.Error("param uid should be 1")
// }
// if context.pvalues[1] != "1" {
// t.Error("param fid should be 1")
// }
h, _ := r.Find(GET, "/users/1", context)
if h != nil {
t.Error("should not found handler")
}
}
func TestRouterCatchAll(t *testing.T) {
func TestRouterMatchAny(t *testing.T) {
r := New().Router
r.Add(GET, "/users/*", func(*Context) error {
return nil
@ -349,6 +354,7 @@ func TestRouterCatchAll(t *testing.T) {
t.Fatal("handler not found")
}
if context.pvalues[0] != "" {
println(context.pvalues[0])
t.Error("value should be joe")
}

View File

@ -39,8 +39,8 @@ for many use cases. Restricting path parameters allows us to use memory efficien
`echo.NotFoundHandler(h Handler)`
Registers a custom NotFound handler used by
router in case it doesn't find any registered handler for HTTP method and path.
Registers a custom NotFound handler. This handler is called in case router doesn't
find matching route for the request.
Default handler sends 404 "Not Found" response.
@ -70,6 +70,12 @@ echo.Get("/hello", func(*echo.Context) {
})
```
Echo's default handler is `func(*echo.Context) error` where `echo.Context` primarily
holds request and response objects. Echo also has a support for other types of
handlers.
<!-- TODO mention about not able to take advantage -->
<!-- ### Groups -->
### Path parameters
@ -90,7 +96,7 @@ echo.Get("/users/:id", func(c *echo.Context) {
})
```
### Match any
### Match-any
Matches zero or more characters in the path. For example, pattern `/users/*` will
match
@ -100,14 +106,36 @@ match
- `/users/1/files/1`
- `/users/anything...`
<!-- Test it -->
### Path matching order
- Static
- Param
- Match any
#### Example
```go
e.Get("/users/:id", func(c *echo.Context) {
c.String(http.StatusOK, "/users/:id")
})
e.Get("/users/new", func(c *echo.Context) {
c.String(http.StatusOK, "/users/new")
})
e.Get("/users/1/files/*", func(c *echo.Context) {
c.String(http.StatusOK, "/users/1/files/*")
})
```
Above routes would resolve in order
- `/users/new`
- `/users/:id`
- `/users/1/files/*`
Routes can be written in any order.
<!-- Different use cases -->
### URI building
@ -128,13 +156,24 @@ h := func(*echo.Context) {
e.Get("/users/:id", h)
```
<!-- ## Request -->
<!-- ## Middleware -->
<!-- ## Response -->
## Response
## Static Content
### JSON
`context.JSON(code int, v interface{}) error` can be used to send a JSON response
with status code.
### String
`context.String(code int, s string) error` can be used to send plain text response
with status code.
### HTML
`func (c *Context) HTML(code int, html string) error` can be used to send an HTML
response with status code.
### Static files
@ -165,3 +204,5 @@ e.Index("index.html")
```
<!-- ## Error Handling -->
<!-- Deployment -->