mirror of
https://github.com/labstack/echo.git
synced 2025-03-25 21:38:56 +02:00
parent
1a124f8aab
commit
2b87e75870
18
context.go
18
context.go
@ -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
|
||||
|
@ -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")
|
||||
}
|
||||
|
6
echo.go
6
echo.go
@ -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
|
||||
}
|
||||
|
46
router.go
46
router.go
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user