From 1efe837fdde3b9084936d8a22596f38445029695 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Mon, 5 Oct 2015 15:52:07 -0700 Subject: [PATCH 1/5] Updated docs Signed-off-by: Vishal Rana --- echo.go | 2 ++ website/Makefile | 17 +++++++++++++++ website/content/guide/customization.md | 2 +- website/content/guide/error-handling.md | 2 +- website/content/guide/installation.md | 2 +- website/content/guide/middleware.md | 2 +- website/content/guide/request.md | 2 +- website/content/guide/response.md | 2 +- website/content/guide/routing.md | 2 +- website/layouts/_default/single.html | 2 +- website/layouts/index.html | 2 +- website/layouts/partials/footer.html | 1 + website/layouts/partials/head.html | 1 + website/rc.json | 29 +++++++++++++++++++++++++ website/service.json | 18 +++++++++++++++ website/static/scripts/echo.js | 10 +++++++++ website/static/styles/echo.css | 17 +++++++++++---- 17 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 website/Makefile create mode 100644 website/rc.json create mode 100644 website/service.json create mode 100644 website/static/scripts/echo.js diff --git a/echo.go b/echo.go index c29b1c3d..7232d65e 100644 --- a/echo.go +++ b/echo.go @@ -462,11 +462,13 @@ func (e *Echo) Routes() []Route { // ServeHTTP implements `http.Handler` interface, which serves HTTP requests. func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { + println(r.Method) c := e.pool.Get().(*Context) h, echo := e.router.Find(r.Method, r.URL.Path, c) if echo != nil { e = echo } + println(echo) c.reset(r, w, e) // Chain middleware with handler in the end diff --git a/website/Makefile b/website/Makefile new file mode 100644 index 00000000..0a3fb293 --- /dev/null +++ b/website/Makefile @@ -0,0 +1,17 @@ +.PHONY: build push deploy + +NAME := echo +TAG := $(shell date +'%Y.%m.%dT%H.%M') + +build: + rm -rf public + hugo + gox -osarch=linux/amd64 -output server + docker build -t gcr.io/$(PROJECT_ID)/$(NAME):$(TAG) . + +push: build + gcloud docker push gcr.io/$(PROJECT_ID)/$(NAME):$(TAG) + +deploy: push + # https://github.com/kubernetes/kubernetes/blob/release-1.0/docs/user-guide/kubectl/kubectl_rolling-update.md + kubectl rolling-update $(NAME) --image=gcr.io/$(PROJECT_ID)/$(NAME):$(TAG) diff --git a/website/content/guide/customization.md b/website/content/guide/customization.md index 12e56bcf..ca87257c 100644 --- a/website/content/guide/customization.md +++ b/website/content/guide/customization.md @@ -3,7 +3,7 @@ title: Customization menu: main: parent: guide - weight: 20 + weight: 2 --- ### HTTP error handler diff --git a/website/content/guide/error-handling.md b/website/content/guide/error-handling.md index 3649d313..e629e09b 100644 --- a/website/content/guide/error-handling.md +++ b/website/content/guide/error-handling.md @@ -3,7 +3,7 @@ title: Error Handling menu: main: parent: guide - weight: 70 + weight: 7 --- Echo advocates centralized HTTP error handling by returning `error` from middleware diff --git a/website/content/guide/installation.md b/website/content/guide/installation.md index 0711b790..688aca44 100644 --- a/website/content/guide/installation.md +++ b/website/content/guide/installation.md @@ -3,7 +3,7 @@ title: Installation menu: main: parent: guide - weight: 10 + weight: 1 --- Echo has been developed and tested using Go `1.4.x` diff --git a/website/content/guide/middleware.md b/website/content/guide/middleware.md index d8117d15..eeeec813 100644 --- a/website/content/guide/middleware.md +++ b/website/content/guide/middleware.md @@ -3,7 +3,7 @@ title: Middleware menu: main: parent: guide - weight: 40 + weight: 4 --- Middleware is a function which is chained in the HTTP request-response cycle. Middleware diff --git a/website/content/guide/request.md b/website/content/guide/request.md index 92d4849f..76251094 100644 --- a/website/content/guide/request.md +++ b/website/content/guide/request.md @@ -3,7 +3,7 @@ title: Request menu: main: parent: guide - weight: 50 + weight: 5 --- ### Path parameter diff --git a/website/content/guide/response.md b/website/content/guide/response.md index 7f0870f1..3a62f57e 100644 --- a/website/content/guide/response.md +++ b/website/content/guide/response.md @@ -3,7 +3,7 @@ title: Response menu: main: parent: guide - weight: 60 + weight: 6 --- ### Template diff --git a/website/content/guide/routing.md b/website/content/guide/routing.md index ca7a95c9..840b59e0 100644 --- a/website/content/guide/routing.md +++ b/website/content/guide/routing.md @@ -3,7 +3,7 @@ title: Routing menu: main: parent: guide - weight: 30 + weight: 3 --- Echo's router is [fast, optimized]({{< relref "index.md#performance">}}) and diff --git a/website/layouts/_default/single.html b/website/layouts/_default/single.html index c169e9f1..407ba1cd 100644 --- a/website/layouts/_default/single.html +++ b/website/layouts/_default/single.html @@ -37,8 +37,8 @@ + {{ partial "footer.html" . }} - {{ partial "footer.html" . }} diff --git a/website/layouts/index.html b/website/layouts/index.html index c6bbc625..6feb84ab 100644 --- a/website/layouts/index.html +++ b/website/layouts/index.html @@ -16,8 +16,8 @@ + {{ partial "footer.html" . }} - {{ partial "footer.html" . }} diff --git a/website/layouts/partials/footer.html b/website/layouts/partials/footer.html index 955dc48d..b9065a5e 100644 --- a/website/layouts/partials/footer.html +++ b/website/layouts/partials/footer.html @@ -28,6 +28,7 @@ + diff --git a/website/rc.json b/website/rc.json new file mode 100644 index 00000000..c75e43a7 --- /dev/null +++ b/website/rc.json @@ -0,0 +1,29 @@ +{ + "apiVersion": "v1", + "kind": "ReplicationController", + "metadata": { + "name": "echo" + }, + "spec": { + "replicas": 2, + "selector": { + "name": "echo" + }, + "template": { + "metadata": { + "labels": { + "name": "echo" + } + }, + "spec": { + "containers": [{ + "image": "gcr.io/fluent-anagram-95603/echo", + "name": "echo", + "ports": [{ + "containerPort": 5091 + }] + }] + } + } + } +} diff --git a/website/service.json b/website/service.json new file mode 100644 index 00000000..970e8660 --- /dev/null +++ b/website/service.json @@ -0,0 +1,18 @@ +{ + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "name": "echo", + "labels": { + "name": "echo" + } + }, + "spec": { + "ports": [{ + "port": 5091 + }], + "selector": { + "name": "echo" + } + } +} diff --git a/website/static/scripts/echo.js b/website/static/scripts/echo.js new file mode 100644 index 00000000..d195dcb2 --- /dev/null +++ b/website/static/scripts/echo.js @@ -0,0 +1,10 @@ +(function() { + var menu = document.querySelectorAll('.menu a'); + + for (var i = 0; i < menu.length; i++) { + var m = menu[i]; + if (location.href === m.href) { + m.className += 'active'; + } + } +})(); diff --git a/website/static/styles/echo.css b/website/static/styles/echo.css index 2c43ba25..d1dacab3 100644 --- a/website/static/styles/echo.css +++ b/website/static/styles/echo.css @@ -1,5 +1,4 @@ footer { - padding: 40px 80px !important; background-color: inherit !important; border-top: 2px solid #E0E0E0; } @@ -16,11 +15,13 @@ footer { color: #333; } code { - font-size: .95em; padding: 2px 4px; - background: #eee; + background: #EEE; color: #424242; + font-size: .95em; font-family: Source Code Pro, Monaco, Menlo, Consolas, monospace; + border: 1px solid #BDBDBD; + border-radius: 4px; } a:link { text-decoration: none; @@ -36,5 +37,13 @@ a:link { .menu a { display: block; color: #757575; - padding: 2px 0 + padding: 5px; + border-left:2px #F06292 solid; +} +.menu a:hover { + background-color: #E0E0E0; +} +.menu .active { + color: #FFF; + background-color: #F06292; } From 5b019c507ee7f1e77374e2c87d90ebd1f48d0cec Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Tue, 6 Oct 2015 06:48:33 -0700 Subject: [PATCH 2/5] Handling 405 & pre-flight requests Signed-off-by: Vishal Rana --- context.go | 4 +- echo.go | 6 +- echo_test.go | 9 +- router.go | 228 +++++++++++++++------------------ router_test.go | 12 +- website/static/styles/echo.css | 7 +- 6 files changed, 121 insertions(+), 145 deletions(-) diff --git a/context.go b/context.go index 7b528546..fe1386ac 100644 --- a/context.go +++ b/context.go @@ -10,8 +10,8 @@ import ( "net/url" - "golang.org/x/net/websocket" "bytes" + "golang.org/x/net/websocket" ) type ( @@ -115,7 +115,7 @@ func (c *Context) Render(code int, name string, data interface{}) (err error) { if c.echo.renderer == nil { return RendererNotRegistered } - buf := new (bytes.Buffer) + buf := new(bytes.Buffer) if err = c.echo.renderer.Render(buf, name, data); err != nil { return } diff --git a/echo.go b/echo.go index 7232d65e..7bb1c5f8 100644 --- a/echo.go +++ b/echo.go @@ -175,8 +175,8 @@ var ( return NewHTTPError(http.StatusNotFound) } - badRequestHandler = func(c *Context) error { - return NewHTTPError(http.StatusBadRequest) + methodNotAllowedHandler = func(c *Context) error { + return NewHTTPError(http.StatusMethodNotAllowed) } ) @@ -462,13 +462,11 @@ func (e *Echo) Routes() []Route { // ServeHTTP implements `http.Handler` interface, which serves HTTP requests. func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { - println(r.Method) c := e.pool.Get().(*Context) h, echo := e.router.Find(r.Method, r.URL.Path, c) if echo != nil { e = echo } - println(echo) c.reset(r, w, e) // Chain middleware with handler in the end diff --git a/echo_test.go b/echo_test.go index 8a469085..67e4dec9 100644 --- a/echo_test.go +++ b/echo_test.go @@ -382,12 +382,15 @@ func TestEchoNotFound(t *testing.T) { assert.Equal(t, http.StatusNotFound, w.Code) } -func TestEchoBadRequest(t *testing.T) { +func TestEchoMethodNotAllowed(t *testing.T) { e := New() - r, _ := http.NewRequest("INVALID", "/files", nil) + e.Get("/", func(c *Context) error { + return c.String(http.StatusOK, "Echo!") + }) + r, _ := http.NewRequest(POST, "/", nil) w := httptest.NewRecorder() e.ServeHTTP(w, r) - assert.Equal(t, http.StatusBadRequest, w.Code) + assert.Equal(t, http.StatusMethodNotAllowed, w.Code) } func TestEchoHTTPError(t *testing.T) { diff --git a/router.go b/router.go index 8214a485..aaf388cd 100644 --- a/router.go +++ b/router.go @@ -4,30 +4,33 @@ import "net/http" type ( Router struct { - connectTree *node - deleteTree *node - getTree *node - headTree *node - optionsTree *node - patchTree *node - postTree *node - putTree *node - traceTree *node - routes []Route - echo *Echo + tree *node + routes []Route + echo *Echo } node struct { - typ ntype - label byte - prefix string - parent *node - children children - handler HandlerFunc - pnames []string - echo *Echo + typ ntype + label byte + prefix string + parent *node + children children + methodHandler *methodHandler + pnames []string + echo *Echo + } + ntype uint8 + children []*node + methodHandler struct { + connect HandlerFunc + delete HandlerFunc + get HandlerFunc + head HandlerFunc + options HandlerFunc + patch HandlerFunc + post HandlerFunc + put HandlerFunc + trace HandlerFunc } - ntype uint8 - children []*node ) const ( @@ -38,17 +41,11 @@ const ( func NewRouter(e *Echo) *Router { return &Router{ - connectTree: new(node), - deleteTree: new(node), - getTree: new(node), - headTree: new(node), - optionsTree: new(node), - patchTree: new(node), - postTree: new(node), - putTree: new(node), - traceTree: new(node), - routes: []Route{}, - echo: e, + tree: &node{ + methodHandler: new(methodHandler), + }, + routes: []Route{}, + echo: e, } } @@ -90,7 +87,7 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st *e.maxParam = l } - cn := r.findTree(method) // Current node as root + cn := r.tree // Current node as root if cn == nil { panic("echo => invalid method") } @@ -115,20 +112,20 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st cn.prefix = search if h != nil { cn.typ = t - cn.handler = h + cn.addHandler(method, h) cn.pnames = pnames cn.echo = e } } else if l < pl { // Split node - n := newNode(cn.typ, cn.prefix[l:], cn, cn.children, cn.handler, cn.pnames, cn.echo) + n := newNode(cn.typ, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.pnames, cn.echo) // Reset parent node cn.typ = stype cn.label = cn.prefix[0] cn.prefix = cn.prefix[:l] cn.children = nil - cn.handler = nil + cn.methodHandler = new(methodHandler) cn.pnames = nil cn.echo = nil @@ -137,12 +134,13 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st if l == sl { // At parent node cn.typ = t - cn.handler = h + cn.addHandler(method, h) cn.pnames = pnames cn.echo = e } else { // Create child node - n = newNode(t, search[l:], cn, nil, h, pnames, e) + n = newNode(t, search[l:], cn, nil, new(methodHandler), pnames, e) + n.addHandler(method, h) cn.addChild(n) } } else if l < sl { @@ -154,12 +152,13 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st continue } // Create child node - n := newNode(t, search, cn, nil, h, pnames, e) + n := newNode(t, search, cn, nil, new(methodHandler), pnames, e) + n.addHandler(method, h) cn.addChild(n) } else { // Node already exists if h != nil { - cn.handler = h + cn.addHandler(method, h) cn.pnames = pnames cn.echo = e } @@ -168,16 +167,16 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st } } -func newNode(t ntype, pre string, p *node, c children, h HandlerFunc, pnames []string, e *Echo) *node { +func newNode(t ntype, pre string, p *node, c children, mh *methodHandler, pnames []string, e *Echo) *node { return &node{ - typ: t, - label: pre[0], - prefix: pre, - parent: p, - children: c, - handler: h, - pnames: pnames, - echo: e, + typ: t, + label: pre[0], + prefix: pre, + parent: p, + children: c, + methodHandler: mh, + pnames: pnames, + echo: e, } } @@ -212,76 +211,57 @@ func (n *node) findChildWithType(t ntype) *node { return nil } -func (r *Router) findTree(method string) (n *node) { - switch method[0] { - case 'G': // GET - m := uint32(method[2])<<8 | uint32(method[1])<<16 | uint32(method[0])<<24 - if m == 0x47455400 { - n = r.getTree - } - case 'P': // POST, PUT or PATCH - switch method[1] { - case 'O': // POST - m := uint32(method[3]) | uint32(method[2])<<8 | uint32(method[1])<<16 | - uint32(method[0])<<24 - if m == 0x504f5354 { - n = r.postTree - } - case 'U': // PUT - m := uint32(method[2])<<8 | uint32(method[1])<<16 | uint32(method[0])<<24 - if m == 0x50555400 { - n = r.putTree - } - case 'A': // PATCH - m := uint64(method[4])<<24 | uint64(method[3])<<32 | uint64(method[2])<<40 | - uint64(method[1])<<48 | uint64(method[0])<<56 - if m == 0x5041544348000000 { - n = r.patchTree - } - } - case 'D': // DELETE - m := uint64(method[5])<<16 | uint64(method[4])<<24 | uint64(method[3])<<32 | - uint64(method[2])<<40 | uint64(method[1])<<48 | uint64(method[0])<<56 - if m == 0x44454c4554450000 { - n = r.deleteTree - } - case 'C': // CONNECT - m := uint64(method[6])<<8 | uint64(method[5])<<16 | uint64(method[4])<<24 | - uint64(method[3])<<32 | uint64(method[2])<<40 | uint64(method[1])<<48 | - uint64(method[0])<<56 - if m == 0x434f4e4e45435400 { - n = r.connectTree - } - case 'H': // HEAD - m := uint32(method[3]) | uint32(method[2])<<8 | uint32(method[1])<<16 | - uint32(method[0])<<24 - if m == 0x48454144 { - n = r.headTree - } - case 'O': // OPTIONS - m := uint64(method[6])<<8 | uint64(method[5])<<16 | uint64(method[4])<<24 | - uint64(method[3])<<32 | uint64(method[2])<<40 | uint64(method[1])<<48 | - uint64(method[0])<<56 - if m == 0x4f5054494f4e5300 { - n = r.optionsTree - } - case 'T': // TRACE - m := uint64(method[4])<<24 | uint64(method[3])<<32 | uint64(method[2])<<40 | - uint64(method[1])<<48 | uint64(method[0])<<56 - if m == 0x5452414345000000 { - n = r.traceTree - } +func (n *node) addHandler(method string, h HandlerFunc) { + switch method { + case GET: + n.methodHandler.get = h + case POST: + n.methodHandler.post = h + case PUT: + n.methodHandler.put = h + case DELETE: + n.methodHandler.delete = h + case PATCH: + n.methodHandler.patch = h + case OPTIONS: + n.methodHandler.delete = h + case HEAD: + n.methodHandler.head = h + case CONNECT: + n.methodHandler.connect = h + case TRACE: + n.methodHandler.trace = h + } +} + +func (n *node) findHandler(method string) HandlerFunc { + switch method { + case GET: + return n.methodHandler.get + case POST: + return n.methodHandler.post + case PUT: + return n.methodHandler.put + case DELETE: + return n.methodHandler.delete + case PATCH: + return n.methodHandler.patch + case OPTIONS: + return n.methodHandler.delete + case HEAD: + return n.methodHandler.head + case CONNECT: + return n.methodHandler.connect + case TRACE: + return n.methodHandler.trace + default: + return nil } - return } func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo) { h = notFoundHandler - cn := r.findTree(method) // Current node as root - if cn == nil { - h = badRequestHandler - return - } + cn := r.tree // Current node as root // Strip trailing slash if r.echo.stripTrailingSlash { @@ -339,14 +319,6 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo } if search == "" { - if cn.handler == nil { - // Look up for match-any, might have an empty value for *, e.g. - // serving a directory. Issue #207 - if cn = cn.findChildWithType(mtype); cn == nil { - return - } - ctx.pvalues[len(cn.pnames)-1] = "" - } goto Found } @@ -396,7 +368,17 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo Found: ctx.pnames = cn.pnames - h = cn.handler + h = cn.findHandler(method) + if h == nil { + h = methodNotAllowedHandler + // Look up for match-any, might have an empty value for *, e.g. + // serving a directory. Issue #207 + if cn = cn.findChildWithType(mtype); cn == nil { + return + } + h = cn.findHandler(method) + ctx.pvalues[len(cn.pnames)-1] = "" + } e = cn.echo return } diff --git a/router_test.go b/router_test.go index 40a1e62b..6c076ef9 100644 --- a/router_test.go +++ b/router_test.go @@ -567,16 +567,6 @@ func TestRouterAPI(t *testing.T) { } } -func TestRouterAddInvalidMethod(t *testing.T) { - e := New() - r := e.router - assert.Panics(t, func() { - r.Add("INVALID", "/", func(*Context) error { - return nil - }, e) - }) -} - func TestRouterServeHTTP(t *testing.T) { e := New() r := e.router @@ -600,7 +590,7 @@ func TestRouterServeHTTP(t *testing.T) { func (n *node) printTree(pfx string, tail bool) { p := prefix(tail, pfx, "└── ", "├── ") - fmt.Printf("%s%s, %p: type=%d, parent=%p, handler=%v\n", p, n.prefix, n, n.typ, n.parent, n.handler) + fmt.Printf("%s%s, %p: type=%d, parent=%p, handler=%v\n", p, n.prefix, n, n.typ, n.parent, n.methodHandler) children := n.children l := len(children) diff --git a/website/static/styles/echo.css b/website/static/styles/echo.css index d1dacab3..5c21af2b 100644 --- a/website/static/styles/echo.css +++ b/website/static/styles/echo.css @@ -34,13 +34,16 @@ a:link { .page-content header { padding-bottom: 16px; } +.menu { + margin-right: 40px; +} .menu a { display: block; color: #757575; padding: 5px; - border-left:2px #F06292 solid; + border-left:4px #F06292 solid; } -.menu a:hover { +.menu a:hover:not(.active) { background-color: #E0E0E0; } .menu .active { From f839210454cd70807bd163b1c6880eb7c76ae6c3 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Tue, 6 Oct 2015 11:04:36 -0700 Subject: [PATCH 3/5] Getting echo reference from the node Signed-off-by: Vishal Rana --- echo.go | 5 +---- router.go | 11 +++++++++-- website/static/styles/echo.css | 4 ++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/echo.go b/echo.go index 7bb1c5f8..b7c71736 100644 --- a/echo.go +++ b/echo.go @@ -463,10 +463,7 @@ func (e *Echo) Routes() []Route { // ServeHTTP implements `http.Handler` interface, which serves HTTP requests. 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) - if echo != nil { - e = echo - } + h, e := e.router.Find(r.Method, r.URL.Path, c) c.reset(r, w, e) // Chain middleware with handler in the end diff --git a/router.go b/router.go index aaf388cd..c0b2f65b 100644 --- a/router.go +++ b/router.go @@ -261,6 +261,7 @@ func (n *node) findHandler(method string) HandlerFunc { func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo) { h = notFoundHandler + e = r.echo cn := r.tree // Current node as root // Strip trailing slash @@ -369,17 +370,23 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo Found: ctx.pnames = cn.pnames h = cn.findHandler(method) + if cn.echo != nil { + e = cn.echo + } if h == nil { h = methodNotAllowedHandler - // Look up for match-any, might have an empty value for *, e.g. + // Dig further for match-any, might have an empty value for *, e.g. // serving a directory. Issue #207 if cn = cn.findChildWithType(mtype); cn == nil { return } +// println("here...") +// if cn.echo != nil { +// e = cn.echo +// } h = cn.findHandler(method) ctx.pvalues[len(cn.pnames)-1] = "" } - e = cn.echo return } diff --git a/website/static/styles/echo.css b/website/static/styles/echo.css index 5c21af2b..44fd0a41 100644 --- a/website/static/styles/echo.css +++ b/website/static/styles/echo.css @@ -20,8 +20,8 @@ code { color: #424242; font-size: .95em; font-family: Source Code Pro, Monaco, Menlo, Consolas, monospace; - border: 1px solid #BDBDBD; - border-radius: 4px; + border: 1px solid #E0E0E0; + border-radius: 2px; } a:link { text-decoration: none; From 0f82a6439baa4b041fefe30b26a7a3ed34b8ff0a Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Tue, 6 Oct 2015 13:56:01 -0700 Subject: [PATCH 4/5] Removed 405 handling for now Signed-off-by: Vishal Rana --- echo_test.go | 16 ++++++++-------- router.go | 16 ++++++---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/echo_test.go b/echo_test.go index 67e4dec9..2626645e 100644 --- a/echo_test.go +++ b/echo_test.go @@ -383,14 +383,14 @@ func TestEchoNotFound(t *testing.T) { } func TestEchoMethodNotAllowed(t *testing.T) { - e := New() - e.Get("/", func(c *Context) error { - return c.String(http.StatusOK, "Echo!") - }) - r, _ := http.NewRequest(POST, "/", nil) - w := httptest.NewRecorder() - e.ServeHTTP(w, r) - assert.Equal(t, http.StatusMethodNotAllowed, w.Code) +// e := New() +// e.Get("/", func(c *Context) error { +// return c.String(http.StatusOK, "Echo!") +// }) +// r, _ := http.NewRequest(POST, "/", nil) +// w := httptest.NewRecorder() +// e.ServeHTTP(w, r) +// assert.Equal(t, http.StatusMethodNotAllowed, w.Code) } func TestEchoHTTPError(t *testing.T) { diff --git a/router.go b/router.go index c0b2f65b..3d9f75e9 100644 --- a/router.go +++ b/router.go @@ -284,7 +284,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo // Search order static > param > match-any for { if search == "" { - goto Found + goto End } pl := 0 // Prefix length @@ -320,7 +320,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo } if search == "" { - goto Found + goto End } // Static node @@ -364,26 +364,22 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo return } ctx.pvalues[len(cn.pnames)-1] = search - goto Found + goto End } -Found: +End: ctx.pnames = cn.pnames h = cn.findHandler(method) if cn.echo != nil { e = cn.echo } if h == nil { - h = methodNotAllowedHandler // Dig further for match-any, might have an empty value for *, e.g. - // serving a directory. Issue #207 + // serving a directory. Issue #207. if cn = cn.findChildWithType(mtype); cn == nil { + h = notFoundHandler return } -// println("here...") -// if cn.echo != nil { -// e = cn.echo -// } h = cn.findHandler(method) ctx.pvalues[len(cn.pnames)-1] = "" } From 51f118b0ee77bc7573102f570709cd117a990f59 Mon Sep 17 00:00:00 2001 From: Vishal Rana Date: Wed, 7 Oct 2015 15:10:40 -0700 Subject: [PATCH 5/5] Refactored variable type to kind Signed-off-by: Vishal Rana --- echo_test.go | 16 ++++++------- router.go | 62 +++++++++++++++++++++++++------------------------- router_test.go | 2 +- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/echo_test.go b/echo_test.go index 2626645e..2a38c104 100644 --- a/echo_test.go +++ b/echo_test.go @@ -383,14 +383,14 @@ func TestEchoNotFound(t *testing.T) { } func TestEchoMethodNotAllowed(t *testing.T) { -// e := New() -// e.Get("/", func(c *Context) error { -// return c.String(http.StatusOK, "Echo!") -// }) -// r, _ := http.NewRequest(POST, "/", nil) -// w := httptest.NewRecorder() -// e.ServeHTTP(w, r) -// assert.Equal(t, http.StatusMethodNotAllowed, w.Code) + // e := New() + // e.Get("/", func(c *Context) error { + // return c.String(http.StatusOK, "Echo!") + // }) + // r, _ := http.NewRequest(POST, "/", nil) + // w := httptest.NewRecorder() + // e.ServeHTTP(w, r) + // assert.Equal(t, http.StatusMethodNotAllowed, w.Code) } func TestEchoHTTPError(t *testing.T) { diff --git a/router.go b/router.go index 3d9f75e9..111d6224 100644 --- a/router.go +++ b/router.go @@ -9,7 +9,7 @@ type ( echo *Echo } node struct { - typ ntype + kind kind label byte prefix string parent *node @@ -18,7 +18,7 @@ type ( pnames []string echo *Echo } - ntype uint8 + kind uint8 children []*node methodHandler struct { connect HandlerFunc @@ -34,9 +34,9 @@ type ( ) const ( - stype ntype = iota - ptype - mtype + skind kind = iota + pkind + mkind ) func NewRouter(e *Echo) *Router { @@ -56,7 +56,7 @@ func (r *Router) Add(method, path string, h HandlerFunc, e *Echo) { if path[i] == ':' { j := i + 1 - r.insert(method, path[:i], nil, stype, nil, e) + r.insert(method, path[:i], nil, skind, nil, e) for ; i < l && path[i] != '/'; i++ { } @@ -65,22 +65,22 @@ func (r *Router) Add(method, path string, h HandlerFunc, e *Echo) { i, l = j, len(path) if i == l { - r.insert(method, path[:i], h, ptype, pnames, e) + r.insert(method, path[:i], h, pkind, pnames, e) return } - r.insert(method, path[:i], nil, ptype, pnames, e) + r.insert(method, path[:i], nil, pkind, pnames, e) } else if path[i] == '*' { - r.insert(method, path[:i], nil, stype, nil, e) + r.insert(method, path[:i], nil, skind, nil, e) pnames = append(pnames, "_*") - r.insert(method, path[:i+1], h, mtype, pnames, e) + r.insert(method, path[:i+1], h, mkind, pnames, e) return } } - r.insert(method, path, h, stype, pnames, e) + r.insert(method, path, h, skind, pnames, e) } -func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []string, e *Echo) { +func (r *Router) insert(method, path string, h HandlerFunc, t kind, pnames []string, e *Echo) { // Adjust max param l := len(pnames) if *e.maxParam < l { @@ -111,17 +111,17 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st cn.label = search[0] cn.prefix = search if h != nil { - cn.typ = t + cn.kind = t cn.addHandler(method, h) cn.pnames = pnames cn.echo = e } } else if l < pl { // Split node - n := newNode(cn.typ, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.pnames, cn.echo) + n := newNode(cn.kind, cn.prefix[l:], cn, cn.children, cn.methodHandler, cn.pnames, cn.echo) // Reset parent node - cn.typ = stype + cn.kind = skind cn.label = cn.prefix[0] cn.prefix = cn.prefix[:l] cn.children = nil @@ -133,7 +133,7 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st if l == sl { // At parent node - cn.typ = t + cn.kind = t cn.addHandler(method, h) cn.pnames = pnames cn.echo = e @@ -167,9 +167,9 @@ func (r *Router) insert(method, path string, h HandlerFunc, t ntype, pnames []st } } -func newNode(t ntype, pre string, p *node, c children, mh *methodHandler, pnames []string, e *Echo) *node { +func newNode(t kind, pre string, p *node, c children, mh *methodHandler, pnames []string, e *Echo) *node { return &node{ - typ: t, + kind: t, label: pre[0], prefix: pre, parent: p, @@ -184,9 +184,9 @@ func (n *node) addChild(c *node) { n.children = append(n.children, c) } -func (n *node) findChild(l byte, t ntype) *node { +func (n *node) findChild(l byte, t kind) *node { for _, c := range n.children { - if c.label == l && c.typ == t { + if c.label == l && c.kind == t { return c } } @@ -202,9 +202,9 @@ func (n *node) findChildWithLabel(l byte) *node { return nil } -func (n *node) findChildWithType(t ntype) *node { +func (n *node) findChildByKind(t kind) *node { for _, c := range n.children { - if c.typ == t { + if c.kind == t { return c } } @@ -276,7 +276,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo search = path c *node // Child node n int // Param counter - nt ntype // Next type + nk kind // Next kind nn *node // Next node ns string // Next search ) @@ -309,9 +309,9 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo } else { cn = nn search = ns - if nt == ptype { + if nk == pkind { goto Param - } else if nt == mtype { + } else if nk == mkind { goto MatchAny } else { // Not found @@ -324,11 +324,11 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo } // Static node - c = cn.findChild(search[0], stype) + c = cn.findChild(search[0], skind) if c != nil { // Save next if cn.label == '/' { - nt = ptype + nk = pkind nn = cn ns = search } @@ -338,11 +338,11 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo // Param node Param: - c = cn.findChildWithType(ptype) + c = cn.findChildByKind(pkind) if c != nil { // Save next if cn.label == '/' { - nt = mtype + nk = mkind nn = cn ns = search } @@ -359,7 +359,7 @@ func (r *Router) Find(method, path string, ctx *Context) (h HandlerFunc, e *Echo // Match-any node MatchAny: // c = cn.getChild() - if cn = cn.findChildWithType(mtype); cn == nil { + if cn = cn.findChildByKind(mkind); cn == nil { // Not found return } @@ -376,7 +376,7 @@ End: if h == nil { // Dig further for match-any, might have an empty value for *, e.g. // serving a directory. Issue #207. - if cn = cn.findChildWithType(mtype); cn == nil { + if cn = cn.findChildByKind(mkind); cn == nil { h = notFoundHandler return } diff --git a/router_test.go b/router_test.go index 6c076ef9..c3357223 100644 --- a/router_test.go +++ b/router_test.go @@ -590,7 +590,7 @@ func TestRouterServeHTTP(t *testing.T) { func (n *node) printTree(pfx string, tail bool) { p := prefix(tail, pfx, "└── ", "├── ") - fmt.Printf("%s%s, %p: type=%d, parent=%p, handler=%v\n", p, n.prefix, n, n.typ, n.parent, n.methodHandler) + fmt.Printf("%s%s, %p: type=%d, parent=%p, handler=%v\n", p, n.prefix, n, n.kind, n.parent, n.methodHandler) children := n.children l := len(children)