diff --git a/echo.go b/echo.go index c10cdc73..79b0d336 100644 --- a/echo.go +++ b/echo.go @@ -22,7 +22,6 @@ import ( type ( Echo struct { - router *Router prefix string middleware []MiddlewareFunc http2 bool @@ -32,9 +31,15 @@ type ( httpErrorHandler HTTPErrorHandler binder BindFunc renderer Renderer - uris map[Handler]string pool sync.Pool debug bool + router *Router + } + + Route struct { + Method string + Path string + Handler Handler } HTTPError struct { @@ -136,9 +141,7 @@ var ( // New creates an Echo instance. func New() (e *Echo) { - e = &Echo{ - uris: make(map[Handler]string), - } + e = &Echo{} e.router = NewRouter(e) e.pool.New = func() interface{} { return NewContext(nil, new(Response), e) @@ -295,8 +298,12 @@ func (e *Echo) WebSocket(path string, h HandlerFunc) { func (e *Echo) add(method, path string, h Handler) { path = e.prefix + path e.router.Add(method, path, wrapHandler(h), e) - key := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name() - e.uris[key] = path + r := Route{ + Method: method, + Path: path, + Handler: runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name(), + } + e.router.routes = append(e.router.routes, r) } // Index serves index file. @@ -345,33 +352,6 @@ func serveFile(dir, file string, c *Context) error { return nil } -// URI generates a URI from handler. -func (e *Echo) URI(h Handler, params ...interface{}) string { - uri := new(bytes.Buffer) - lp := len(params) - n := 0 - key := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name() - if path, ok := e.uris[key]; ok { - for i, l := 0, len(path); i < l; i++ { - if path[i] == ':' && n < lp { - for ; i < l && path[i] != '/'; i++ { - } - uri.WriteString(fmt.Sprintf("%v", params[n])) - n++ - } - if i < l { - uri.WriteByte(path[i]) - } - } - } - return uri.String() -} - -// URL is an alias for URI -func (e *Echo) URL(h Handler, params ...interface{}) string { - return e.URI(h, params...) -} - // Group creates a new sub router with prefix. It inherits all properties from // the parent. Passing middleware overrides parent middleware. func (e *Echo) Group(prefix string, m ...Middleware) *Group { @@ -384,6 +364,41 @@ func (e *Echo) Group(prefix string, m ...Middleware) *Group { return g } +// URI generates a URI from handler. +func (e *Echo) URI(h Handler, params ...interface{}) string { + uri := new(bytes.Buffer) + pl := len(params) + n := 0 + hn := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name() + for _, r := range e.router.routes { + if r.Handler == hn { + for i, l := 0, len(r.Path); i < l; i++ { + if r.Path[i] == ':' && n < pl { + for ; i < l && r.Path[i] != '/'; i++ { + } + uri.WriteString(fmt.Sprintf("%v", params[n])) + n++ + } + if i < l { + uri.WriteByte(r.Path[i]) + } + } + break + } + } + return uri.String() +} + +// URL is an alias for URI +func (e *Echo) URL(h Handler, params ...interface{}) string { + return e.URI(h, params...) +} + +// Routes returns the registered routes. +func (e *Echo) Routes() []Route { + return e.router.routes +} + 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) @@ -401,8 +416,8 @@ func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // Execute chain - if he := h(c); he != nil { - e.httpErrorHandler(he, c) + if err := h(c); err != nil { + e.httpErrorHandler(err, c) } e.pool.Put(c) diff --git a/echo_test.go b/echo_test.go index 1a0b90e6..be8c779a 100644 --- a/echo_test.go +++ b/echo_test.go @@ -197,59 +197,6 @@ func TestEchoHandler(t *testing.T) { }) } -func TestEchoGroup(t *testing.T) { - e := New() - buf := new(bytes.Buffer) - e.Use(func(*Context) error { - buf.WriteString("0") - return nil - }) - h := func(*Context) error { return nil } - - //-------- - // Routes - //-------- - - e.Get("/users", h) - - // Group - g1 := e.Group("/group1") - g1.Use(func(*Context) error { - buf.WriteString("1") - return nil - }) - g1.Get("/", h) - - // Group with no parent middleware - g2 := e.Group("/group2", func(*Context) error { - buf.WriteString("2") - return nil - }) - g2.Get("/", h) - - // Nested groups - g3 := e.Group("/group3") - g4 := g3.Group("/group4") - g4.Get("/", func(c *Context) error { - return c.NoContent(http.StatusOK) - }) - - request(GET, "/users", e) - assert.Equal(t, "0", buf.String()) - - buf.Reset() - request(GET, "/group1/", e) - assert.Equal(t, "01", buf.String()) - - buf.Reset() - request(GET, "/group2/", e) - assert.Equal(t, "2", buf.String()) - - buf.Reset() - c, _ := request(GET, "/group3/group4/", e) - assert.Equal(t, http.StatusOK, c) -} - func TestEchoConnect(t *testing.T) { e := New() testMethod(t, CONNECT, "/", e) @@ -335,6 +282,80 @@ func TestEchoURL(t *testing.T) { assert.Equal(t, "/group/users/1/files/1", e.URL(getFile, "1", "1")) } +func TestEchoRoutes(t *testing.T) { + e := New() + h := func(*Context) error { return nil } + routes := []Route{ + {GET, "/users/:user/events", h}, + {GET, "/users/:user/events/public", h}, + {POST, "/repos/:owner/:repo/git/refs", h}, + {POST, "/repos/:owner/:repo/git/tags", h}, + } + for _, r := range routes { + e.add(r.Method, r.Path, h) + } + + for i, r := range e.Routes() { + assert.Equal(t, routes[i].Method, r.Method) + assert.Equal(t, routes[i].Path, r.Path) + } +} + +func TestEchoGroup(t *testing.T) { + e := New() + buf := new(bytes.Buffer) + e.Use(func(*Context) error { + buf.WriteString("0") + return nil + }) + h := func(*Context) error { return nil } + + //-------- + // Routes + //-------- + + e.Get("/users", h) + + // Group + g1 := e.Group("/group1") + g1.Use(func(*Context) error { + buf.WriteString("1") + return nil + }) + g1.Get("/", h) + + // Group with no parent middleware + g2 := e.Group("/group2", func(*Context) error { + buf.WriteString("2") + return nil + }) + g2.Get("/", h) + + // Nested groups + g3 := e.Group("/group3") + g4 := g3.Group("/group4") + g4.Get("/", func(c *Context) error { + return c.NoContent(http.StatusOK) + }) + + request(GET, "/users", e) + // println(len(e.middleware)) + assert.Equal(t, "0", buf.String()) + + buf.Reset() + request(GET, "/group1/", e) + // println(len(g1.echo.middleware)) + assert.Equal(t, "01", buf.String()) + + buf.Reset() + request(GET, "/group2/", e) + assert.Equal(t, "2", buf.String()) + + buf.Reset() + c, _ := request(GET, "/group3/group4/", e) + assert.Equal(t, http.StatusOK, c) +} + func TestEchoNotFound(t *testing.T) { e := New() r, _ := http.NewRequest(GET, "/files", nil) diff --git a/router.go b/router.go index 5587f665..a08bde71 100644 --- a/router.go +++ b/router.go @@ -4,8 +4,9 @@ import "net/http" type ( Router struct { - trees map[string]*node - echo *Echo + trees map[string]*node + routes []Route + echo *Echo } node struct { typ ntype @@ -29,8 +30,9 @@ const ( func NewRouter(e *Echo) (r *Router) { r = &Router{ - trees: make(map[string]*node), - echo: e, + trees: make(map[string]*node), + routes: []Route{}, + echo: e, } for _, m := range methods { r.trees[m] = &node{ diff --git a/router_test.go b/router_test.go index 69bdd2bd..c3a0dc45 100644 --- a/router_test.go +++ b/router_test.go @@ -9,274 +9,269 @@ import ( "github.com/stretchr/testify/assert" ) -type route struct { - method string - path string -} - var ( context = NewContext(nil, nil, New()) - api = []route{ + api = []Route{ // OAuth Authorizations - {"GET", "/authorizations"}, - {"GET", "/authorizations/:id"}, - {"POST", "/authorizations"}, - //{"PUT", "/authorizations/clients/:client_id"}, - //{"PATCH", "/authorizations/:id"}, - {"DELETE", "/authorizations/:id"}, - {"GET", "/applications/:client_id/tokens/:access_token"}, - {"DELETE", "/applications/:client_id/tokens"}, - {"DELETE", "/applications/:client_id/tokens/:access_token"}, + {"GET", "/authorizations", nil}, + {"GET", "/authorizations/:id", nil}, + {"POST", "/authorizations", nil}, + //{"PUT", "/authorizations/clients/:client_id", nil}, + //{"PATCH", "/authorizations/:id", nil}, + {"DELETE", "/authorizations/:id", nil}, + {"GET", "/applications/:client_id/tokens/:access_token", nil}, + {"DELETE", "/applications/:client_id/tokens", nil}, + {"DELETE", "/applications/:client_id/tokens/:access_token", nil}, // Activity - {"GET", "/events"}, - {"GET", "/repos/:owner/:repo/events"}, - {"GET", "/networks/:owner/:repo/events"}, - {"GET", "/orgs/:org/events"}, - {"GET", "/users/:user/received_events"}, - {"GET", "/users/:user/received_events/public"}, - {"GET", "/users/:user/events"}, - {"GET", "/users/:user/events/public"}, - {"GET", "/users/:user/events/orgs/:org"}, - {"GET", "/feeds"}, - {"GET", "/notifications"}, - {"GET", "/repos/:owner/:repo/notifications"}, - {"PUT", "/notifications"}, - {"PUT", "/repos/:owner/:repo/notifications"}, - {"GET", "/notifications/threads/:id"}, - //{"PATCH", "/notifications/threads/:id"}, - {"GET", "/notifications/threads/:id/subscription"}, - {"PUT", "/notifications/threads/:id/subscription"}, - {"DELETE", "/notifications/threads/:id/subscription"}, - {"GET", "/repos/:owner/:repo/stargazers"}, - {"GET", "/users/:user/starred"}, - {"GET", "/user/starred"}, - {"GET", "/user/starred/:owner/:repo"}, - {"PUT", "/user/starred/:owner/:repo"}, - {"DELETE", "/user/starred/:owner/:repo"}, - {"GET", "/repos/:owner/:repo/subscribers"}, - {"GET", "/users/:user/subscriptions"}, - {"GET", "/user/subscriptions"}, - {"GET", "/repos/:owner/:repo/subscription"}, - {"PUT", "/repos/:owner/:repo/subscription"}, - {"DELETE", "/repos/:owner/:repo/subscription"}, - {"GET", "/user/subscriptions/:owner/:repo"}, - {"PUT", "/user/subscriptions/:owner/:repo"}, - {"DELETE", "/user/subscriptions/:owner/:repo"}, + {"GET", "/events", nil}, + {"GET", "/repos/:owner/:repo/events", nil}, + {"GET", "/networks/:owner/:repo/events", nil}, + {"GET", "/orgs/:org/events", nil}, + {"GET", "/users/:user/received_events", nil}, + {"GET", "/users/:user/received_events/public", nil}, + {"GET", "/users/:user/events", nil}, + {"GET", "/users/:user/events/public", nil}, + {"GET", "/users/:user/events/orgs/:org", nil}, + {"GET", "/feeds", nil}, + {"GET", "/notifications", nil}, + {"GET", "/repos/:owner/:repo/notifications", nil}, + {"PUT", "/notifications", nil}, + {"PUT", "/repos/:owner/:repo/notifications", nil}, + {"GET", "/notifications/threads/:id", nil}, + //{"PATCH", "/notifications/threads/:id", nil}, + {"GET", "/notifications/threads/:id/subscription", nil}, + {"PUT", "/notifications/threads/:id/subscription", nil}, + {"DELETE", "/notifications/threads/:id/subscription", nil}, + {"GET", "/repos/:owner/:repo/stargazers", nil}, + {"GET", "/users/:user/starred", nil}, + {"GET", "/user/starred", nil}, + {"GET", "/user/starred/:owner/:repo", nil}, + {"PUT", "/user/starred/:owner/:repo", nil}, + {"DELETE", "/user/starred/:owner/:repo", nil}, + {"GET", "/repos/:owner/:repo/subscribers", nil}, + {"GET", "/users/:user/subscriptions", nil}, + {"GET", "/user/subscriptions", nil}, + {"GET", "/repos/:owner/:repo/subscription", nil}, + {"PUT", "/repos/:owner/:repo/subscription", nil}, + {"DELETE", "/repos/:owner/:repo/subscription", nil}, + {"GET", "/user/subscriptions/:owner/:repo", nil}, + {"PUT", "/user/subscriptions/:owner/:repo", nil}, + {"DELETE", "/user/subscriptions/:owner/:repo", nil}, // Gists - {"GET", "/users/:user/gists"}, - {"GET", "/gists"}, - //{"GET", "/gists/public"}, - //{"GET", "/gists/starred"}, - {"GET", "/gists/:id"}, - {"POST", "/gists"}, - //{"PATCH", "/gists/:id"}, - {"PUT", "/gists/:id/star"}, - {"DELETE", "/gists/:id/star"}, - {"GET", "/gists/:id/star"}, - {"POST", "/gists/:id/forks"}, - {"DELETE", "/gists/:id"}, + {"GET", "/users/:user/gists", nil}, + {"GET", "/gists", nil}, + //{"GET", "/gists/public", nil}, + //{"GET", "/gists/starred", nil}, + {"GET", "/gists/:id", nil}, + {"POST", "/gists", nil}, + //{"PATCH", "/gists/:id", nil}, + {"PUT", "/gists/:id/star", nil}, + {"DELETE", "/gists/:id/star", nil}, + {"GET", "/gists/:id/star", nil}, + {"POST", "/gists/:id/forks", nil}, + {"DELETE", "/gists/:id", nil}, // Git Data - {"GET", "/repos/:owner/:repo/git/blobs/:sha"}, - {"POST", "/repos/:owner/:repo/git/blobs"}, - {"GET", "/repos/:owner/:repo/git/commits/:sha"}, - {"POST", "/repos/:owner/:repo/git/commits"}, - //{"GET", "/repos/:owner/:repo/git/refs/*ref"}, - {"GET", "/repos/:owner/:repo/git/refs"}, - {"POST", "/repos/:owner/:repo/git/refs"}, - //{"PATCH", "/repos/:owner/:repo/git/refs/*ref"}, - //{"DELETE", "/repos/:owner/:repo/git/refs/*ref"}, - {"GET", "/repos/:owner/:repo/git/tags/:sha"}, - {"POST", "/repos/:owner/:repo/git/tags"}, - {"GET", "/repos/:owner/:repo/git/trees/:sha"}, - {"POST", "/repos/:owner/:repo/git/trees"}, + {"GET", "/repos/:owner/:repo/git/blobs/:sha", nil}, + {"POST", "/repos/:owner/:repo/git/blobs", nil}, + {"GET", "/repos/:owner/:repo/git/commits/:sha", nil}, + {"POST", "/repos/:owner/:repo/git/commits", nil}, + //{"GET", "/repos/:owner/:repo/git/refs/*ref", nil}, + {"GET", "/repos/:owner/:repo/git/refs", nil}, + {"POST", "/repos/:owner/:repo/git/refs", nil}, + //{"PATCH", "/repos/:owner/:repo/git/refs/*ref", nil}, + //{"DELETE", "/repos/:owner/:repo/git/refs/*ref", nil}, + {"GET", "/repos/:owner/:repo/git/tags/:sha", nil}, + {"POST", "/repos/:owner/:repo/git/tags", nil}, + {"GET", "/repos/:owner/:repo/git/trees/:sha", nil}, + {"POST", "/repos/:owner/:repo/git/trees", nil}, // Issues - {"GET", "/issues"}, - {"GET", "/user/issues"}, - {"GET", "/orgs/:org/issues"}, - {"GET", "/repos/:owner/:repo/issues"}, - {"GET", "/repos/:owner/:repo/issues/:number"}, - {"POST", "/repos/:owner/:repo/issues"}, - //{"PATCH", "/repos/:owner/:repo/issues/:number"}, - {"GET", "/repos/:owner/:repo/assignees"}, - {"GET", "/repos/:owner/:repo/assignees/:assignee"}, - {"GET", "/repos/:owner/:repo/issues/:number/comments"}, - //{"GET", "/repos/:owner/:repo/issues/comments"}, - //{"GET", "/repos/:owner/:repo/issues/comments/:id"}, - {"POST", "/repos/:owner/:repo/issues/:number/comments"}, - //{"PATCH", "/repos/:owner/:repo/issues/comments/:id"}, - //{"DELETE", "/repos/:owner/:repo/issues/comments/:id"}, - {"GET", "/repos/:owner/:repo/issues/:number/events"}, - //{"GET", "/repos/:owner/:repo/issues/events"}, - //{"GET", "/repos/:owner/:repo/issues/events/:id"}, - {"GET", "/repos/:owner/:repo/labels"}, - {"GET", "/repos/:owner/:repo/labels/:name"}, - {"POST", "/repos/:owner/:repo/labels"}, - //{"PATCH", "/repos/:owner/:repo/labels/:name"}, - {"DELETE", "/repos/:owner/:repo/labels/:name"}, - {"GET", "/repos/:owner/:repo/issues/:number/labels"}, - {"POST", "/repos/:owner/:repo/issues/:number/labels"}, - {"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name"}, - {"PUT", "/repos/:owner/:repo/issues/:number/labels"}, - {"DELETE", "/repos/:owner/:repo/issues/:number/labels"}, - {"GET", "/repos/:owner/:repo/milestones/:number/labels"}, - {"GET", "/repos/:owner/:repo/milestones"}, - {"GET", "/repos/:owner/:repo/milestones/:number"}, - {"POST", "/repos/:owner/:repo/milestones"}, - //{"PATCH", "/repos/:owner/:repo/milestones/:number"}, - {"DELETE", "/repos/:owner/:repo/milestones/:number"}, + {"GET", "/issues", nil}, + {"GET", "/user/issues", nil}, + {"GET", "/orgs/:org/issues", nil}, + {"GET", "/repos/:owner/:repo/issues", nil}, + {"GET", "/repos/:owner/:repo/issues/:number", nil}, + {"POST", "/repos/:owner/:repo/issues", nil}, + //{"PATCH", "/repos/:owner/:repo/issues/:number", nil}, + {"GET", "/repos/:owner/:repo/assignees", nil}, + {"GET", "/repos/:owner/:repo/assignees/:assignee", nil}, + {"GET", "/repos/:owner/:repo/issues/:number/comments", nil}, + //{"GET", "/repos/:owner/:repo/issues/comments", nil}, + //{"GET", "/repos/:owner/:repo/issues/comments/:id", nil}, + {"POST", "/repos/:owner/:repo/issues/:number/comments", nil}, + //{"PATCH", "/repos/:owner/:repo/issues/comments/:id", nil}, + //{"DELETE", "/repos/:owner/:repo/issues/comments/:id", nil}, + {"GET", "/repos/:owner/:repo/issues/:number/events", nil}, + //{"GET", "/repos/:owner/:repo/issues/events", nil}, + //{"GET", "/repos/:owner/:repo/issues/events/:id", nil}, + {"GET", "/repos/:owner/:repo/labels", nil}, + {"GET", "/repos/:owner/:repo/labels/:name", nil}, + {"POST", "/repos/:owner/:repo/labels", nil}, + //{"PATCH", "/repos/:owner/:repo/labels/:name", nil}, + {"DELETE", "/repos/:owner/:repo/labels/:name", nil}, + {"GET", "/repos/:owner/:repo/issues/:number/labels", nil}, + {"POST", "/repos/:owner/:repo/issues/:number/labels", nil}, + {"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name", nil}, + {"PUT", "/repos/:owner/:repo/issues/:number/labels", nil}, + {"DELETE", "/repos/:owner/:repo/issues/:number/labels", nil}, + {"GET", "/repos/:owner/:repo/milestones/:number/labels", nil}, + {"GET", "/repos/:owner/:repo/milestones", nil}, + {"GET", "/repos/:owner/:repo/milestones/:number", nil}, + {"POST", "/repos/:owner/:repo/milestones", nil}, + //{"PATCH", "/repos/:owner/:repo/milestones/:number", nil}, + {"DELETE", "/repos/:owner/:repo/milestones/:number", nil}, // Miscellaneous - {"GET", "/emojis"}, - {"GET", "/gitignore/templates"}, - {"GET", "/gitignore/templates/:name"}, - {"POST", "/markdown"}, - {"POST", "/markdown/raw"}, - {"GET", "/meta"}, - {"GET", "/rate_limit"}, + {"GET", "/emojis", nil}, + {"GET", "/gitignore/templates", nil}, + {"GET", "/gitignore/templates/:name", nil}, + {"POST", "/markdown", nil}, + {"POST", "/markdown/raw", nil}, + {"GET", "/meta", nil}, + {"GET", "/rate_limit", nil}, // Organizations - {"GET", "/users/:user/orgs"}, - {"GET", "/user/orgs"}, - {"GET", "/orgs/:org"}, - //{"PATCH", "/orgs/:org"}, - {"GET", "/orgs/:org/members"}, - {"GET", "/orgs/:org/members/:user"}, - {"DELETE", "/orgs/:org/members/:user"}, - {"GET", "/orgs/:org/public_members"}, - {"GET", "/orgs/:org/public_members/:user"}, - {"PUT", "/orgs/:org/public_members/:user"}, - {"DELETE", "/orgs/:org/public_members/:user"}, - {"GET", "/orgs/:org/teams"}, - {"GET", "/teams/:id"}, - {"POST", "/orgs/:org/teams"}, - //{"PATCH", "/teams/:id"}, - {"DELETE", "/teams/:id"}, - {"GET", "/teams/:id/members"}, - {"GET", "/teams/:id/members/:user"}, - {"PUT", "/teams/:id/members/:user"}, - {"DELETE", "/teams/:id/members/:user"}, - {"GET", "/teams/:id/repos"}, - {"GET", "/teams/:id/repos/:owner/:repo"}, - {"PUT", "/teams/:id/repos/:owner/:repo"}, - {"DELETE", "/teams/:id/repos/:owner/:repo"}, - {"GET", "/user/teams"}, + {"GET", "/users/:user/orgs", nil}, + {"GET", "/user/orgs", nil}, + {"GET", "/orgs/:org", nil}, + //{"PATCH", "/orgs/:org", nil}, + {"GET", "/orgs/:org/members", nil}, + {"GET", "/orgs/:org/members/:user", nil}, + {"DELETE", "/orgs/:org/members/:user", nil}, + {"GET", "/orgs/:org/public_members", nil}, + {"GET", "/orgs/:org/public_members/:user", nil}, + {"PUT", "/orgs/:org/public_members/:user", nil}, + {"DELETE", "/orgs/:org/public_members/:user", nil}, + {"GET", "/orgs/:org/teams", nil}, + {"GET", "/teams/:id", nil}, + {"POST", "/orgs/:org/teams", nil}, + //{"PATCH", "/teams/:id", nil}, + {"DELETE", "/teams/:id", nil}, + {"GET", "/teams/:id/members", nil}, + {"GET", "/teams/:id/members/:user", nil}, + {"PUT", "/teams/:id/members/:user", nil}, + {"DELETE", "/teams/:id/members/:user", nil}, + {"GET", "/teams/:id/repos", nil}, + {"GET", "/teams/:id/repos/:owner/:repo", nil}, + {"PUT", "/teams/:id/repos/:owner/:repo", nil}, + {"DELETE", "/teams/:id/repos/:owner/:repo", nil}, + {"GET", "/user/teams", nil}, // Pull Requests - {"GET", "/repos/:owner/:repo/pulls"}, - {"GET", "/repos/:owner/:repo/pulls/:number"}, - {"POST", "/repos/:owner/:repo/pulls"}, - //{"PATCH", "/repos/:owner/:repo/pulls/:number"}, - {"GET", "/repos/:owner/:repo/pulls/:number/commits"}, - {"GET", "/repos/:owner/:repo/pulls/:number/files"}, - {"GET", "/repos/:owner/:repo/pulls/:number/merge"}, - {"PUT", "/repos/:owner/:repo/pulls/:number/merge"}, - {"GET", "/repos/:owner/:repo/pulls/:number/comments"}, - //{"GET", "/repos/:owner/:repo/pulls/comments"}, - //{"GET", "/repos/:owner/:repo/pulls/comments/:number"}, - {"PUT", "/repos/:owner/:repo/pulls/:number/comments"}, - //{"PATCH", "/repos/:owner/:repo/pulls/comments/:number"}, - //{"DELETE", "/repos/:owner/:repo/pulls/comments/:number"}, + {"GET", "/repos/:owner/:repo/pulls", nil}, + {"GET", "/repos/:owner/:repo/pulls/:number", nil}, + {"POST", "/repos/:owner/:repo/pulls", nil}, + //{"PATCH", "/repos/:owner/:repo/pulls/:number", nil}, + {"GET", "/repos/:owner/:repo/pulls/:number/commits", nil}, + {"GET", "/repos/:owner/:repo/pulls/:number/files", nil}, + {"GET", "/repos/:owner/:repo/pulls/:number/merge", nil}, + {"PUT", "/repos/:owner/:repo/pulls/:number/merge", nil}, + {"GET", "/repos/:owner/:repo/pulls/:number/comments", nil}, + //{"GET", "/repos/:owner/:repo/pulls/comments", nil}, + //{"GET", "/repos/:owner/:repo/pulls/comments/:number", nil}, + {"PUT", "/repos/:owner/:repo/pulls/:number/comments", nil}, + //{"PATCH", "/repos/:owner/:repo/pulls/comments/:number", nil}, + //{"DELETE", "/repos/:owner/:repo/pulls/comments/:number", nil}, // Repositories - {"GET", "/user/repos"}, - {"GET", "/users/:user/repos"}, - {"GET", "/orgs/:org/repos"}, - {"GET", "/repositories"}, - {"POST", "/user/repos"}, - {"POST", "/orgs/:org/repos"}, - {"GET", "/repos/:owner/:repo"}, - //{"PATCH", "/repos/:owner/:repo"}, - {"GET", "/repos/:owner/:repo/contributors"}, - {"GET", "/repos/:owner/:repo/languages"}, - {"GET", "/repos/:owner/:repo/teams"}, - {"GET", "/repos/:owner/:repo/tags"}, - {"GET", "/repos/:owner/:repo/branches"}, - {"GET", "/repos/:owner/:repo/branches/:branch"}, - {"DELETE", "/repos/:owner/:repo"}, - {"GET", "/repos/:owner/:repo/collaborators"}, - {"GET", "/repos/:owner/:repo/collaborators/:user"}, - {"PUT", "/repos/:owner/:repo/collaborators/:user"}, - {"DELETE", "/repos/:owner/:repo/collaborators/:user"}, - {"GET", "/repos/:owner/:repo/comments"}, - {"GET", "/repos/:owner/:repo/commits/:sha/comments"}, - {"POST", "/repos/:owner/:repo/commits/:sha/comments"}, - {"GET", "/repos/:owner/:repo/comments/:id"}, - //{"PATCH", "/repos/:owner/:repo/comments/:id"}, - {"DELETE", "/repos/:owner/:repo/comments/:id"}, - {"GET", "/repos/:owner/:repo/commits"}, - {"GET", "/repos/:owner/:repo/commits/:sha"}, - {"GET", "/repos/:owner/:repo/readme"}, - //{"GET", "/repos/:owner/:repo/contents/*path"}, - //{"PUT", "/repos/:owner/:repo/contents/*path"}, - //{"DELETE", "/repos/:owner/:repo/contents/*path"}, - //{"GET", "/repos/:owner/:repo/:archive_format/:ref"}, - {"GET", "/repos/:owner/:repo/keys"}, - {"GET", "/repos/:owner/:repo/keys/:id"}, - {"POST", "/repos/:owner/:repo/keys"}, - //{"PATCH", "/repos/:owner/:repo/keys/:id"}, - {"DELETE", "/repos/:owner/:repo/keys/:id"}, - {"GET", "/repos/:owner/:repo/downloads"}, - {"GET", "/repos/:owner/:repo/downloads/:id"}, - {"DELETE", "/repos/:owner/:repo/downloads/:id"}, - {"GET", "/repos/:owner/:repo/forks"}, - {"POST", "/repos/:owner/:repo/forks"}, - {"GET", "/repos/:owner/:repo/hooks"}, - {"GET", "/repos/:owner/:repo/hooks/:id"}, - {"POST", "/repos/:owner/:repo/hooks"}, - //{"PATCH", "/repos/:owner/:repo/hooks/:id"}, - {"POST", "/repos/:owner/:repo/hooks/:id/tests"}, - {"DELETE", "/repos/:owner/:repo/hooks/:id"}, - {"POST", "/repos/:owner/:repo/merges"}, - {"GET", "/repos/:owner/:repo/releases"}, - {"GET", "/repos/:owner/:repo/releases/:id"}, - {"POST", "/repos/:owner/:repo/releases"}, - //{"PATCH", "/repos/:owner/:repo/releases/:id"}, - {"DELETE", "/repos/:owner/:repo/releases/:id"}, - {"GET", "/repos/:owner/:repo/releases/:id/assets"}, - {"GET", "/repos/:owner/:repo/stats/contributors"}, - {"GET", "/repos/:owner/:repo/stats/commit_activity"}, - {"GET", "/repos/:owner/:repo/stats/code_frequency"}, - {"GET", "/repos/:owner/:repo/stats/participation"}, - {"GET", "/repos/:owner/:repo/stats/punch_card"}, - {"GET", "/repos/:owner/:repo/statuses/:ref"}, - {"POST", "/repos/:owner/:repo/statuses/:ref"}, + {"GET", "/user/repos", nil}, + {"GET", "/users/:user/repos", nil}, + {"GET", "/orgs/:org/repos", nil}, + {"GET", "/repositories", nil}, + {"POST", "/user/repos", nil}, + {"POST", "/orgs/:org/repos", nil}, + {"GET", "/repos/:owner/:repo", nil}, + //{"PATCH", "/repos/:owner/:repo", nil}, + {"GET", "/repos/:owner/:repo/contributors", nil}, + {"GET", "/repos/:owner/:repo/languages", nil}, + {"GET", "/repos/:owner/:repo/teams", nil}, + {"GET", "/repos/:owner/:repo/tags", nil}, + {"GET", "/repos/:owner/:repo/branches", nil}, + {"GET", "/repos/:owner/:repo/branches/:branch", nil}, + {"DELETE", "/repos/:owner/:repo", nil}, + {"GET", "/repos/:owner/:repo/collaborators", nil}, + {"GET", "/repos/:owner/:repo/collaborators/:user", nil}, + {"PUT", "/repos/:owner/:repo/collaborators/:user", nil}, + {"DELETE", "/repos/:owner/:repo/collaborators/:user", nil}, + {"GET", "/repos/:owner/:repo/comments", nil}, + {"GET", "/repos/:owner/:repo/commits/:sha/comments", nil}, + {"POST", "/repos/:owner/:repo/commits/:sha/comments", nil}, + {"GET", "/repos/:owner/:repo/comments/:id", nil}, + //{"PATCH", "/repos/:owner/:repo/comments/:id", nil}, + {"DELETE", "/repos/:owner/:repo/comments/:id", nil}, + {"GET", "/repos/:owner/:repo/commits", nil}, + {"GET", "/repos/:owner/:repo/commits/:sha", nil}, + {"GET", "/repos/:owner/:repo/readme", nil}, + //{"GET", "/repos/:owner/:repo/contents/*path", nil}, + //{"PUT", "/repos/:owner/:repo/contents/*path", nil}, + //{"DELETE", "/repos/:owner/:repo/contents/*path", nil}, + //{"GET", "/repos/:owner/:repo/:archive_format/:ref", nil}, + {"GET", "/repos/:owner/:repo/keys", nil}, + {"GET", "/repos/:owner/:repo/keys/:id", nil}, + {"POST", "/repos/:owner/:repo/keys", nil}, + //{"PATCH", "/repos/:owner/:repo/keys/:id", nil}, + {"DELETE", "/repos/:owner/:repo/keys/:id", nil}, + {"GET", "/repos/:owner/:repo/downloads", nil}, + {"GET", "/repos/:owner/:repo/downloads/:id", nil}, + {"DELETE", "/repos/:owner/:repo/downloads/:id", nil}, + {"GET", "/repos/:owner/:repo/forks", nil}, + {"POST", "/repos/:owner/:repo/forks", nil}, + {"GET", "/repos/:owner/:repo/hooks", nil}, + {"GET", "/repos/:owner/:repo/hooks/:id", nil}, + {"POST", "/repos/:owner/:repo/hooks", nil}, + //{"PATCH", "/repos/:owner/:repo/hooks/:id", nil}, + {"POST", "/repos/:owner/:repo/hooks/:id/tests", nil}, + {"DELETE", "/repos/:owner/:repo/hooks/:id", nil}, + {"POST", "/repos/:owner/:repo/merges", nil}, + {"GET", "/repos/:owner/:repo/releases", nil}, + {"GET", "/repos/:owner/:repo/releases/:id", nil}, + {"POST", "/repos/:owner/:repo/releases", nil}, + //{"PATCH", "/repos/:owner/:repo/releases/:id", nil}, + {"DELETE", "/repos/:owner/:repo/releases/:id", nil}, + {"GET", "/repos/:owner/:repo/releases/:id/assets", nil}, + {"GET", "/repos/:owner/:repo/stats/contributors", nil}, + {"GET", "/repos/:owner/:repo/stats/commit_activity", nil}, + {"GET", "/repos/:owner/:repo/stats/code_frequency", nil}, + {"GET", "/repos/:owner/:repo/stats/participation", nil}, + {"GET", "/repos/:owner/:repo/stats/punch_card", nil}, + {"GET", "/repos/:owner/:repo/statuses/:ref", nil}, + {"POST", "/repos/:owner/:repo/statuses/:ref", nil}, // Search - {"GET", "/search/repositories"}, - {"GET", "/search/code"}, - {"GET", "/search/issues"}, - {"GET", "/search/users"}, - {"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword"}, - {"GET", "/legacy/repos/search/:keyword"}, - {"GET", "/legacy/user/search/:keyword"}, - {"GET", "/legacy/user/email/:email"}, + {"GET", "/search/repositories", nil}, + {"GET", "/search/code", nil}, + {"GET", "/search/issues", nil}, + {"GET", "/search/users", nil}, + {"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword", nil}, + {"GET", "/legacy/repos/search/:keyword", nil}, + {"GET", "/legacy/user/search/:keyword", nil}, + {"GET", "/legacy/user/email/:email", nil}, // Users - {"GET", "/users/:user"}, - {"GET", "/user"}, - //{"PATCH", "/user"}, - {"GET", "/users"}, - {"GET", "/user/emails"}, - {"POST", "/user/emails"}, - {"DELETE", "/user/emails"}, - {"GET", "/users/:user/followers"}, - {"GET", "/user/followers"}, - {"GET", "/users/:user/following"}, - {"GET", "/user/following"}, - {"GET", "/user/following/:user"}, - {"GET", "/users/:user/following/:target_user"}, - {"PUT", "/user/following/:user"}, - {"DELETE", "/user/following/:user"}, - {"GET", "/users/:user/keys"}, - {"GET", "/user/keys"}, - {"GET", "/user/keys/:id"}, - {"POST", "/user/keys"}, - //{"PATCH", "/user/keys/:id"}, - {"DELETE", "/user/keys/:id"}, + {"GET", "/users/:user", nil}, + {"GET", "/user", nil}, + //{"PATCH", "/user", nil}, + {"GET", "/users", nil}, + {"GET", "/user/emails", nil}, + {"POST", "/user/emails", nil}, + {"DELETE", "/user/emails", nil}, + {"GET", "/users/:user/followers", nil}, + {"GET", "/user/followers", nil}, + {"GET", "/users/:user/following", nil}, + {"GET", "/user/following", nil}, + {"GET", "/user/following/:user", nil}, + {"GET", "/users/:user/following/:target_user", nil}, + {"PUT", "/user/following/:user", nil}, + {"DELETE", "/user/following/:user", nil}, + {"GET", "/users/:user/keys", nil}, + {"GET", "/user/keys", nil}, + {"GET", "/user/keys/:id", nil}, + {"POST", "/user/keys", nil}, + //{"PATCH", "/user/keys/:id", nil}, + {"DELETE", "/user/keys/:id", nil}, } ) @@ -506,7 +501,7 @@ func TestRouterParamNames(t *testing.T) { func TestRouterAPI(t *testing.T) { r := New().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 { for i, n := range c.pnames { if assert.NotEmpty(t, n) { assert.Equal(t, ":"+n, c.P(uint8(i))) @@ -514,7 +509,7 @@ func TestRouterAPI(t *testing.T) { } return nil }, nil) - h, _ := r.Find(route.method, route.path, context) + h, _ := r.Find(route.Method, route.Path, context) if assert.NotNil(t, h) { h(context) }