1
0
mirror of https://github.com/labstack/echo.git synced 2025-03-25 21:38:56 +02:00
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Vishal Rana 2015-04-25 22:32:20 -07:00
parent 1a124f8aab
commit 2b87e75870
6 changed files with 86 additions and 88 deletions

View File

@ -11,7 +11,9 @@ type (
Context struct {
Request *http.Request
Response *response
params Params
pnames []string
pvalues []string
pn int // Param count
store store
echo *Echo
}
@ -19,15 +21,19 @@ type (
)
// P returns path parameter by index.
func (c *Context) P(i uint8) string {
return c.params[i].Value
func (c *Context) P(i int) (value string) {
if i <= c.pn {
value = c.pvalues[i]
}
return
}
// Param returns path parameter by name.
func (c *Context) Param(name string) (value string) {
for _, p := range c.params {
if p.Name == name {
value = p.Value
for i, n := range c.pnames {
if n == name && i <= c.pn {
value = c.pvalues[i]
break
}
}
return

View File

@ -26,7 +26,7 @@ func TestContext(t *testing.T) {
c := &Context{
Response: &response{Writer: httptest.NewRecorder()},
Request: r,
params: make(Params, 5),
pvalues: make([]string, 5),
store: make(store),
echo: New(),
}
@ -64,7 +64,8 @@ func TestContext(t *testing.T) {
//-------
// By id
c.params = Params{{"id", "1"}}
c.pnames = []string{"id"}
c.pvalues = []string{"1"}
if c.P(0) != "1" {
t.Error("param id should be 1")
}

View File

@ -110,7 +110,8 @@ func New() (e *Echo) {
e.pool.New = func() interface{} {
return &Context{
Response: &response{},
params: make(Params, e.maxParam),
pnames: make([]string, e.maxParam),
pvalues: make([]string, e.maxParam),
store: make(store),
}
}
@ -118,6 +119,7 @@ func New() (e *Echo) {
//----------
// Defaults
//----------
e.MaxParam(5)
e.NotFoundHandler(func(c *Context) {
http.Error(c.Response, http.StatusText(http.StatusNotFound), http.StatusNotFound)
@ -289,7 +291,7 @@ func (e *Echo) Index(file string) {
func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := e.pool.Get().(*Context)
h, echo := e.Router.Find(r.Method, r.URL.Path, c.params)
h, echo := e.Router.Find(r.Method, r.URL.Path, c)
if echo != nil {
e = echo
}

View File

@ -21,11 +21,6 @@ type (
}
ntype uint8
children []*node
param struct {
Name string
Value string
}
Params []param
)
const (
@ -204,20 +199,18 @@ func lcp(a, b string) (i int) {
return
}
func (r *router) Find(method, path string, params Params) (h HandlerFunc, echo *Echo) {
func (r *router) Find(method, path string, c *Context) (h HandlerFunc, echo *Echo) {
cn := r.trees[method] // Current node as root
search := path
n := 0 // Param count
c := new(node) // Child node
chn := new(node) // Child node
c.pn = 0 // Param count
// Search order static > param > catch-all
for {
if search == "" || search == cn.prefix {
// Found
h = cn.handler
for i := 0; i < len(cn.pnames); i++ {
params[i].Name = cn.pnames[i]
}
c.pnames = cn.pnames
echo = cn.echo
return
}
@ -232,33 +225,32 @@ func (r *router) Find(method, path string, params Params) (h HandlerFunc, echo *
}
// Static node
c = cn.findSchild(search[0])
if c != nil {
cn = c
chn = cn.findSchild(search[0])
if chn != nil {
cn = chn
continue
}
// Param node
Param:
c = cn.findPchild()
if c != nil {
cn = c
chn = cn.findPchild()
if chn != nil {
cn = chn
i, l := 0, len(search)
for ; i < l && search[i] != '/'; i++ {
}
params[n].Value = search[:i]
n++
c.pvalues[c.pn] = search[:i]
c.pn++
search = search[i:]
continue
}
// Catch-all node
c = cn.findCchild()
if c != nil {
cn = c
p := params[:n+1]
p[n].Name = "_name"
p[n].Value = search
chn = cn.findCchild()
if chn != nil {
cn = chn
c.pnames[c.pn] = "_name"
c.pvalues[c.pn] = search
search = "" // End search
continue
}
@ -281,8 +273,8 @@ func (r *router) Find(method, path string, params Params) (h HandlerFunc, echo *
func (r *router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c := r.echo.pool.Get().(*Context)
h, _ := r.Find(req.Method, req.URL.Path, c.params)
c.Response.Writer = w
h, _ := r.Find(req.Method, req.URL.Path, c)
c.reset(w, req, nil)
if h != nil {
h(c)
} else {

View File

@ -23,8 +23,8 @@ var (
)
var (
params = make(Params, 5)
api = []route{
context = &Context{pvalues: make([]string, 5)}
api = []route{
// OAuth Authorizations
{"GET", "/authorizations"},
{"GET", "/authorizations/:id"},
@ -296,7 +296,7 @@ func TestRouterStatic(t *testing.T) {
b.WriteString(path)
return nil
}, nil)
h, _ := r.Find(GET, path, params)
h, _ := r.Find(GET, path, context)
if h == nil {
t.Fatal("handler not found")
}
@ -311,11 +311,11 @@ func TestRouterParam(t *testing.T) {
r.Add(GET, "/users/:id", func(c *Context) error {
return nil
}, nil)
h, _ := r.Find(GET, "/users/1", params)
h, _ := r.Find(GET, "/users/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param id should be 1")
}
}
@ -326,14 +326,14 @@ func TestRouterTwoParam(t *testing.T) {
return nil
}, nil)
h, _ := r.Find(GET, "/users/1/files/1", params)
h, _ := r.Find(GET, "/users/1/files/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param uid should be 1")
}
if params[1].Value != "1" {
if context.pvalues[1] != "1" {
t.Error("param fid should be 1")
}
}
@ -343,11 +343,11 @@ func TestRouterCatchAll(t *testing.T) {
r.Add(GET, "/static/*", func(*Context) error {
return nil
}, nil)
h, _ := r.Find(GET, "/static/echo.gif", params)
h, _ := r.Find(GET, "/static/echo.gif", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "echo.gif" {
if context.pvalues[0] != "echo.gif" {
t.Error("value should be echo.gif")
}
}
@ -357,17 +357,17 @@ func TestRouterMicroParam(t *testing.T) {
r.Add(GET, "/:a/:b/:c", func(c *Context) error {
return nil
}, nil)
h, _ := r.Find(GET, "/1/2/3", params)
h, _ := r.Find(GET, "/1/2/3", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param a should be 1")
}
if params[1].Value != "2" {
if context.pvalues[1] != "2" {
t.Error("param b should be 2")
}
if params[2].Value != "3" {
if context.pvalues[2] != "3" {
t.Error("param c should be 3")
}
}
@ -386,7 +386,7 @@ func TestRouterMultiRoute(t *testing.T) {
}, nil)
// Route > /users
h, _ := r.Find(GET, "/users", params)
h, _ := r.Find(GET, "/users", context)
if h == nil {
t.Fatal("handler not found")
}
@ -396,16 +396,16 @@ func TestRouterMultiRoute(t *testing.T) {
}
// Route > /users/:id > /users/1
h, _ = r.Find(GET, "/users/1", params)
h, _ = r.Find(GET, "/users/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param id should be 1")
}
// Route > /user
h, _ = r.Find(GET, "/user", params)
h, _ = r.Find(GET, "/user", context)
if h != nil {
t.Fatal("handler should be nil")
}
@ -438,13 +438,13 @@ func TestRouterConflictingRoute(t *testing.T) {
}, nil)
// Route > /users
h, _ := r.Find(GET, "/users", params)
h, _ := r.Find(GET, "/users", context)
if h == nil {
t.Fatal("handler not found")
}
// Route > /users/new
h, _ = r.Find(GET, "/users/new", params)
h, _ = r.Find(GET, "/users/new", context)
if h == nil {
t.Fatal("handler not found")
}
@ -454,29 +454,29 @@ func TestRouterConflictingRoute(t *testing.T) {
}
// Route > /users/:id > /users/1
h, _ = r.Find(GET, "/users/1", params)
h, _ = r.Find(GET, "/users/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param id should be 1")
}
// Route > /users/:id > /users/nil
h, _ = r.Find(GET, "/users/nil", params)
h, _ = r.Find(GET, "/users/nil", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "nil" {
if context.pvalues[0] != "nil" {
t.Error("param id should be nil")
}
// Route > /users/:id > /users/news
h, _ = r.Find(GET, "/users/news", params)
h, _ = r.Find(GET, "/users/news", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "news" {
if context.pvalues[0] != "news" {
t.Error("param id should be news")
}
@ -485,7 +485,7 @@ func TestRouterConflictingRoute(t *testing.T) {
//-----------
// Route > /users/new/moon > /users/new/moon
h, _ = r.Find(GET, "/users/new/moon", params)
h, _ = r.Find(GET, "/users/new/moon", context)
if h == nil {
t.Fatal("handler not found")
}
@ -495,29 +495,29 @@ func TestRouterConflictingRoute(t *testing.T) {
}
// Route > /users/new/:id > /users/new/1
h, _ = r.Find(GET, "/users/new/1", params)
h, _ = r.Find(GET, "/users/new/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param id should be 1")
}
// Route > /users/new/:id > /users/new/me
h, _ = r.Find(GET, "/users/new/me", params)
h, _ = r.Find(GET, "/users/new/me", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "me" {
if context.pvalues[0] != "me" {
t.Error("param id should be me")
}
// Route > /users/new/:id > /users/new/moons
h, _ = r.Find(GET, "/users/new/moons", params)
h, _ = r.Find(GET, "/users/new/moons", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Value != "moons" {
if context.pvalues[0] != "moons" {
t.Error("param id should be moons")
}
}
@ -539,7 +539,7 @@ func TestRouterParamNames(t *testing.T) {
}, nil)
// Route > /users
h, _ := r.Find(GET, "/users", params)
h, _ := r.Find(GET, "/users", context)
if h == nil {
t.Fatal("handler not found")
}
@ -549,32 +549,32 @@ func TestRouterParamNames(t *testing.T) {
}
// Route > /users/:id > /users/1
h, _ = r.Find(GET, "/users/1", params)
h, _ = r.Find(GET, "/users/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Name != "id" {
if context.pnames[0] != "id" {
t.Error("param name should be id")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param id should be 1")
}
// Route > /users/:uid/files/:fid > /users/1/files/1
h, _ = r.Find(GET, "/users/1/files/1", params)
h, _ = r.Find(GET, "/users/1/files/1", context)
if h == nil {
t.Fatal("handler not found")
}
if params[0].Name != "uid" {
if context.pnames[0] != "uid" {
t.Error("param name should be id")
}
if params[0].Value != "1" {
if context.pvalues[0] != "1" {
t.Error("param id should be 1")
}
if params[1].Name != "fid" {
if context.pnames[1] != "fid" {
t.Error("param name should be id")
}
if params[1].Value != "1" {
if context.pvalues[1] != "1" {
t.Error("param id should be 1")
}
}
@ -583,23 +583,20 @@ func TestRouterAPI(t *testing.T) {
r := New().Router
for _, route := range api {
r.Add(route.method, route.path, func(c *Context) error {
for _, p := range c.params {
if p.Name != "" {
if ":"+p.Name != p.Value {
for i, n := range c.pnames {
if n != "" {
if ":"+n != c.pvalues[i] {
t.Errorf("param not found, method=%s, path=%s", route.method, route.path)
}
}
}
return nil
}, nil)
// Reset params
params = make(Params, 5)
c := &Context{params: params}
h, _ := r.Find(route.method, route.path, params)
h, _ := r.Find(route.method, route.path, context)
if h == nil {
t.Fatalf("handler not found, method=%s, path=%s", route.method, route.path)
}
h(c)
h(context)
}
}

View File

@ -10,7 +10,7 @@
Echo has been developed and tested using Go `1.4.x`
Install latest version of Echo via `go get`
Install the latest version of Echo via `go get`
```sh
$ go get github.com/labstack/echo