mirror of
https://github.com/labstack/echo.git
synced 2025-11-27 22:38:25 +02:00
87
echo.go
87
echo.go
@@ -22,7 +22,6 @@ import (
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
Echo struct {
|
Echo struct {
|
||||||
router *Router
|
|
||||||
prefix string
|
prefix string
|
||||||
middleware []MiddlewareFunc
|
middleware []MiddlewareFunc
|
||||||
http2 bool
|
http2 bool
|
||||||
@@ -32,9 +31,15 @@ type (
|
|||||||
httpErrorHandler HTTPErrorHandler
|
httpErrorHandler HTTPErrorHandler
|
||||||
binder BindFunc
|
binder BindFunc
|
||||||
renderer Renderer
|
renderer Renderer
|
||||||
uris map[Handler]string
|
|
||||||
pool sync.Pool
|
pool sync.Pool
|
||||||
debug bool
|
debug bool
|
||||||
|
router *Router
|
||||||
|
}
|
||||||
|
|
||||||
|
Route struct {
|
||||||
|
Method string
|
||||||
|
Path string
|
||||||
|
Handler Handler
|
||||||
}
|
}
|
||||||
|
|
||||||
HTTPError struct {
|
HTTPError struct {
|
||||||
@@ -136,9 +141,7 @@ var (
|
|||||||
|
|
||||||
// New creates an Echo instance.
|
// New creates an Echo instance.
|
||||||
func New() (e *Echo) {
|
func New() (e *Echo) {
|
||||||
e = &Echo{
|
e = &Echo{}
|
||||||
uris: make(map[Handler]string),
|
|
||||||
}
|
|
||||||
e.router = NewRouter(e)
|
e.router = NewRouter(e)
|
||||||
e.pool.New = func() interface{} {
|
e.pool.New = func() interface{} {
|
||||||
return NewContext(nil, new(Response), e)
|
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) {
|
func (e *Echo) add(method, path string, h Handler) {
|
||||||
path = e.prefix + path
|
path = e.prefix + path
|
||||||
e.router.Add(method, path, wrapHandler(h), e)
|
e.router.Add(method, path, wrapHandler(h), e)
|
||||||
key := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()
|
r := Route{
|
||||||
e.uris[key] = path
|
Method: method,
|
||||||
|
Path: path,
|
||||||
|
Handler: runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name(),
|
||||||
|
}
|
||||||
|
e.router.routes = append(e.router.routes, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index serves index file.
|
// Index serves index file.
|
||||||
@@ -345,33 +352,6 @@ func serveFile(dir, file string, c *Context) error {
|
|||||||
return nil
|
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
|
// Group creates a new sub router with prefix. It inherits all properties from
|
||||||
// the parent. Passing middleware overrides parent middleware.
|
// the parent. Passing middleware overrides parent middleware.
|
||||||
func (e *Echo) Group(prefix string, m ...Middleware) *Group {
|
func (e *Echo) Group(prefix string, m ...Middleware) *Group {
|
||||||
@@ -384,6 +364,41 @@ func (e *Echo) Group(prefix string, m ...Middleware) *Group {
|
|||||||
return g
|
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) {
|
func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
c := e.pool.Get().(*Context)
|
c := e.pool.Get().(*Context)
|
||||||
h, echo := e.router.Find(r.Method, r.URL.Path, c)
|
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
|
// Execute chain
|
||||||
if he := h(c); he != nil {
|
if err := h(c); err != nil {
|
||||||
e.httpErrorHandler(he, c)
|
e.httpErrorHandler(err, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
e.pool.Put(c)
|
e.pool.Put(c)
|
||||||
|
|||||||
127
echo_test.go
127
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) {
|
func TestEchoConnect(t *testing.T) {
|
||||||
e := New()
|
e := New()
|
||||||
testMethod(t, CONNECT, "/", e)
|
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"))
|
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) {
|
func TestEchoNotFound(t *testing.T) {
|
||||||
e := New()
|
e := New()
|
||||||
r, _ := http.NewRequest(GET, "/files", nil)
|
r, _ := http.NewRequest(GET, "/files", nil)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import "net/http"
|
|||||||
type (
|
type (
|
||||||
Router struct {
|
Router struct {
|
||||||
trees map[string]*node
|
trees map[string]*node
|
||||||
|
routes []Route
|
||||||
echo *Echo
|
echo *Echo
|
||||||
}
|
}
|
||||||
node struct {
|
node struct {
|
||||||
@@ -30,6 +31,7 @@ const (
|
|||||||
func NewRouter(e *Echo) (r *Router) {
|
func NewRouter(e *Echo) (r *Router) {
|
||||||
r = &Router{
|
r = &Router{
|
||||||
trees: make(map[string]*node),
|
trees: make(map[string]*node),
|
||||||
|
routes: []Route{},
|
||||||
echo: e,
|
echo: e,
|
||||||
}
|
}
|
||||||
for _, m := range methods {
|
for _, m := range methods {
|
||||||
|
|||||||
489
router_test.go
489
router_test.go
@@ -9,274 +9,269 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
type route struct {
|
|
||||||
method string
|
|
||||||
path string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
context = NewContext(nil, nil, New())
|
context = NewContext(nil, nil, New())
|
||||||
api = []route{
|
api = []Route{
|
||||||
// OAuth Authorizations
|
// OAuth Authorizations
|
||||||
{"GET", "/authorizations"},
|
{"GET", "/authorizations", nil},
|
||||||
{"GET", "/authorizations/:id"},
|
{"GET", "/authorizations/:id", nil},
|
||||||
{"POST", "/authorizations"},
|
{"POST", "/authorizations", nil},
|
||||||
//{"PUT", "/authorizations/clients/:client_id"},
|
//{"PUT", "/authorizations/clients/:client_id", nil},
|
||||||
//{"PATCH", "/authorizations/:id"},
|
//{"PATCH", "/authorizations/:id", nil},
|
||||||
{"DELETE", "/authorizations/:id"},
|
{"DELETE", "/authorizations/:id", nil},
|
||||||
{"GET", "/applications/:client_id/tokens/:access_token"},
|
{"GET", "/applications/:client_id/tokens/:access_token", nil},
|
||||||
{"DELETE", "/applications/:client_id/tokens"},
|
{"DELETE", "/applications/:client_id/tokens", nil},
|
||||||
{"DELETE", "/applications/:client_id/tokens/:access_token"},
|
{"DELETE", "/applications/:client_id/tokens/:access_token", nil},
|
||||||
|
|
||||||
// Activity
|
// Activity
|
||||||
{"GET", "/events"},
|
{"GET", "/events", nil},
|
||||||
{"GET", "/repos/:owner/:repo/events"},
|
{"GET", "/repos/:owner/:repo/events", nil},
|
||||||
{"GET", "/networks/:owner/:repo/events"},
|
{"GET", "/networks/:owner/:repo/events", nil},
|
||||||
{"GET", "/orgs/:org/events"},
|
{"GET", "/orgs/:org/events", nil},
|
||||||
{"GET", "/users/:user/received_events"},
|
{"GET", "/users/:user/received_events", nil},
|
||||||
{"GET", "/users/:user/received_events/public"},
|
{"GET", "/users/:user/received_events/public", nil},
|
||||||
{"GET", "/users/:user/events"},
|
{"GET", "/users/:user/events", nil},
|
||||||
{"GET", "/users/:user/events/public"},
|
{"GET", "/users/:user/events/public", nil},
|
||||||
{"GET", "/users/:user/events/orgs/:org"},
|
{"GET", "/users/:user/events/orgs/:org", nil},
|
||||||
{"GET", "/feeds"},
|
{"GET", "/feeds", nil},
|
||||||
{"GET", "/notifications"},
|
{"GET", "/notifications", nil},
|
||||||
{"GET", "/repos/:owner/:repo/notifications"},
|
{"GET", "/repos/:owner/:repo/notifications", nil},
|
||||||
{"PUT", "/notifications"},
|
{"PUT", "/notifications", nil},
|
||||||
{"PUT", "/repos/:owner/:repo/notifications"},
|
{"PUT", "/repos/:owner/:repo/notifications", nil},
|
||||||
{"GET", "/notifications/threads/:id"},
|
{"GET", "/notifications/threads/:id", nil},
|
||||||
//{"PATCH", "/notifications/threads/:id"},
|
//{"PATCH", "/notifications/threads/:id", nil},
|
||||||
{"GET", "/notifications/threads/:id/subscription"},
|
{"GET", "/notifications/threads/:id/subscription", nil},
|
||||||
{"PUT", "/notifications/threads/:id/subscription"},
|
{"PUT", "/notifications/threads/:id/subscription", nil},
|
||||||
{"DELETE", "/notifications/threads/:id/subscription"},
|
{"DELETE", "/notifications/threads/:id/subscription", nil},
|
||||||
{"GET", "/repos/:owner/:repo/stargazers"},
|
{"GET", "/repos/:owner/:repo/stargazers", nil},
|
||||||
{"GET", "/users/:user/starred"},
|
{"GET", "/users/:user/starred", nil},
|
||||||
{"GET", "/user/starred"},
|
{"GET", "/user/starred", nil},
|
||||||
{"GET", "/user/starred/:owner/:repo"},
|
{"GET", "/user/starred/:owner/:repo", nil},
|
||||||
{"PUT", "/user/starred/:owner/:repo"},
|
{"PUT", "/user/starred/:owner/:repo", nil},
|
||||||
{"DELETE", "/user/starred/:owner/:repo"},
|
{"DELETE", "/user/starred/:owner/:repo", nil},
|
||||||
{"GET", "/repos/:owner/:repo/subscribers"},
|
{"GET", "/repos/:owner/:repo/subscribers", nil},
|
||||||
{"GET", "/users/:user/subscriptions"},
|
{"GET", "/users/:user/subscriptions", nil},
|
||||||
{"GET", "/user/subscriptions"},
|
{"GET", "/user/subscriptions", nil},
|
||||||
{"GET", "/repos/:owner/:repo/subscription"},
|
{"GET", "/repos/:owner/:repo/subscription", nil},
|
||||||
{"PUT", "/repos/:owner/:repo/subscription"},
|
{"PUT", "/repos/:owner/:repo/subscription", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/subscription"},
|
{"DELETE", "/repos/:owner/:repo/subscription", nil},
|
||||||
{"GET", "/user/subscriptions/:owner/:repo"},
|
{"GET", "/user/subscriptions/:owner/:repo", nil},
|
||||||
{"PUT", "/user/subscriptions/:owner/:repo"},
|
{"PUT", "/user/subscriptions/:owner/:repo", nil},
|
||||||
{"DELETE", "/user/subscriptions/:owner/:repo"},
|
{"DELETE", "/user/subscriptions/:owner/:repo", nil},
|
||||||
|
|
||||||
// Gists
|
// Gists
|
||||||
{"GET", "/users/:user/gists"},
|
{"GET", "/users/:user/gists", nil},
|
||||||
{"GET", "/gists"},
|
{"GET", "/gists", nil},
|
||||||
//{"GET", "/gists/public"},
|
//{"GET", "/gists/public", nil},
|
||||||
//{"GET", "/gists/starred"},
|
//{"GET", "/gists/starred", nil},
|
||||||
{"GET", "/gists/:id"},
|
{"GET", "/gists/:id", nil},
|
||||||
{"POST", "/gists"},
|
{"POST", "/gists", nil},
|
||||||
//{"PATCH", "/gists/:id"},
|
//{"PATCH", "/gists/:id", nil},
|
||||||
{"PUT", "/gists/:id/star"},
|
{"PUT", "/gists/:id/star", nil},
|
||||||
{"DELETE", "/gists/:id/star"},
|
{"DELETE", "/gists/:id/star", nil},
|
||||||
{"GET", "/gists/:id/star"},
|
{"GET", "/gists/:id/star", nil},
|
||||||
{"POST", "/gists/:id/forks"},
|
{"POST", "/gists/:id/forks", nil},
|
||||||
{"DELETE", "/gists/:id"},
|
{"DELETE", "/gists/:id", nil},
|
||||||
|
|
||||||
// Git Data
|
// Git Data
|
||||||
{"GET", "/repos/:owner/:repo/git/blobs/:sha"},
|
{"GET", "/repos/:owner/:repo/git/blobs/:sha", nil},
|
||||||
{"POST", "/repos/:owner/:repo/git/blobs"},
|
{"POST", "/repos/:owner/:repo/git/blobs", nil},
|
||||||
{"GET", "/repos/:owner/:repo/git/commits/:sha"},
|
{"GET", "/repos/:owner/:repo/git/commits/:sha", nil},
|
||||||
{"POST", "/repos/:owner/:repo/git/commits"},
|
{"POST", "/repos/:owner/:repo/git/commits", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/git/refs/*ref"},
|
//{"GET", "/repos/:owner/:repo/git/refs/*ref", nil},
|
||||||
{"GET", "/repos/:owner/:repo/git/refs"},
|
{"GET", "/repos/:owner/:repo/git/refs", nil},
|
||||||
{"POST", "/repos/:owner/:repo/git/refs"},
|
{"POST", "/repos/:owner/:repo/git/refs", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/git/refs/*ref"},
|
//{"PATCH", "/repos/:owner/:repo/git/refs/*ref", nil},
|
||||||
//{"DELETE", "/repos/:owner/:repo/git/refs/*ref"},
|
//{"DELETE", "/repos/:owner/:repo/git/refs/*ref", nil},
|
||||||
{"GET", "/repos/:owner/:repo/git/tags/:sha"},
|
{"GET", "/repos/:owner/:repo/git/tags/:sha", nil},
|
||||||
{"POST", "/repos/:owner/:repo/git/tags"},
|
{"POST", "/repos/:owner/:repo/git/tags", nil},
|
||||||
{"GET", "/repos/:owner/:repo/git/trees/:sha"},
|
{"GET", "/repos/:owner/:repo/git/trees/:sha", nil},
|
||||||
{"POST", "/repos/:owner/:repo/git/trees"},
|
{"POST", "/repos/:owner/:repo/git/trees", nil},
|
||||||
|
|
||||||
// Issues
|
// Issues
|
||||||
{"GET", "/issues"},
|
{"GET", "/issues", nil},
|
||||||
{"GET", "/user/issues"},
|
{"GET", "/user/issues", nil},
|
||||||
{"GET", "/orgs/:org/issues"},
|
{"GET", "/orgs/:org/issues", nil},
|
||||||
{"GET", "/repos/:owner/:repo/issues"},
|
{"GET", "/repos/:owner/:repo/issues", nil},
|
||||||
{"GET", "/repos/:owner/:repo/issues/:number"},
|
{"GET", "/repos/:owner/:repo/issues/:number", nil},
|
||||||
{"POST", "/repos/:owner/:repo/issues"},
|
{"POST", "/repos/:owner/:repo/issues", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/issues/:number"},
|
//{"PATCH", "/repos/:owner/:repo/issues/:number", nil},
|
||||||
{"GET", "/repos/:owner/:repo/assignees"},
|
{"GET", "/repos/:owner/:repo/assignees", nil},
|
||||||
{"GET", "/repos/:owner/:repo/assignees/:assignee"},
|
{"GET", "/repos/:owner/:repo/assignees/:assignee", nil},
|
||||||
{"GET", "/repos/:owner/:repo/issues/:number/comments"},
|
{"GET", "/repos/:owner/:repo/issues/:number/comments", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/issues/comments"},
|
//{"GET", "/repos/:owner/:repo/issues/comments", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/issues/comments/:id"},
|
//{"GET", "/repos/:owner/:repo/issues/comments/:id", nil},
|
||||||
{"POST", "/repos/:owner/:repo/issues/:number/comments"},
|
{"POST", "/repos/:owner/:repo/issues/:number/comments", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/issues/comments/:id"},
|
//{"PATCH", "/repos/:owner/:repo/issues/comments/:id", nil},
|
||||||
//{"DELETE", "/repos/:owner/:repo/issues/comments/:id"},
|
//{"DELETE", "/repos/:owner/:repo/issues/comments/:id", nil},
|
||||||
{"GET", "/repos/:owner/:repo/issues/:number/events"},
|
{"GET", "/repos/:owner/:repo/issues/:number/events", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/issues/events"},
|
//{"GET", "/repos/:owner/:repo/issues/events", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/issues/events/:id"},
|
//{"GET", "/repos/:owner/:repo/issues/events/:id", nil},
|
||||||
{"GET", "/repos/:owner/:repo/labels"},
|
{"GET", "/repos/:owner/:repo/labels", nil},
|
||||||
{"GET", "/repos/:owner/:repo/labels/:name"},
|
{"GET", "/repos/:owner/:repo/labels/:name", nil},
|
||||||
{"POST", "/repos/:owner/:repo/labels"},
|
{"POST", "/repos/:owner/:repo/labels", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/labels/:name"},
|
//{"PATCH", "/repos/:owner/:repo/labels/:name", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/labels/:name"},
|
{"DELETE", "/repos/:owner/:repo/labels/:name", nil},
|
||||||
{"GET", "/repos/:owner/:repo/issues/:number/labels"},
|
{"GET", "/repos/:owner/:repo/issues/:number/labels", nil},
|
||||||
{"POST", "/repos/:owner/:repo/issues/:number/labels"},
|
{"POST", "/repos/:owner/:repo/issues/:number/labels", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name"},
|
{"DELETE", "/repos/:owner/:repo/issues/:number/labels/:name", nil},
|
||||||
{"PUT", "/repos/:owner/:repo/issues/:number/labels"},
|
{"PUT", "/repos/:owner/:repo/issues/:number/labels", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/issues/:number/labels"},
|
{"DELETE", "/repos/:owner/:repo/issues/:number/labels", nil},
|
||||||
{"GET", "/repos/:owner/:repo/milestones/:number/labels"},
|
{"GET", "/repos/:owner/:repo/milestones/:number/labels", nil},
|
||||||
{"GET", "/repos/:owner/:repo/milestones"},
|
{"GET", "/repos/:owner/:repo/milestones", nil},
|
||||||
{"GET", "/repos/:owner/:repo/milestones/:number"},
|
{"GET", "/repos/:owner/:repo/milestones/:number", nil},
|
||||||
{"POST", "/repos/:owner/:repo/milestones"},
|
{"POST", "/repos/:owner/:repo/milestones", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/milestones/:number"},
|
//{"PATCH", "/repos/:owner/:repo/milestones/:number", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/milestones/:number"},
|
{"DELETE", "/repos/:owner/:repo/milestones/:number", nil},
|
||||||
|
|
||||||
// Miscellaneous
|
// Miscellaneous
|
||||||
{"GET", "/emojis"},
|
{"GET", "/emojis", nil},
|
||||||
{"GET", "/gitignore/templates"},
|
{"GET", "/gitignore/templates", nil},
|
||||||
{"GET", "/gitignore/templates/:name"},
|
{"GET", "/gitignore/templates/:name", nil},
|
||||||
{"POST", "/markdown"},
|
{"POST", "/markdown", nil},
|
||||||
{"POST", "/markdown/raw"},
|
{"POST", "/markdown/raw", nil},
|
||||||
{"GET", "/meta"},
|
{"GET", "/meta", nil},
|
||||||
{"GET", "/rate_limit"},
|
{"GET", "/rate_limit", nil},
|
||||||
|
|
||||||
// Organizations
|
// Organizations
|
||||||
{"GET", "/users/:user/orgs"},
|
{"GET", "/users/:user/orgs", nil},
|
||||||
{"GET", "/user/orgs"},
|
{"GET", "/user/orgs", nil},
|
||||||
{"GET", "/orgs/:org"},
|
{"GET", "/orgs/:org", nil},
|
||||||
//{"PATCH", "/orgs/:org"},
|
//{"PATCH", "/orgs/:org", nil},
|
||||||
{"GET", "/orgs/:org/members"},
|
{"GET", "/orgs/:org/members", nil},
|
||||||
{"GET", "/orgs/:org/members/:user"},
|
{"GET", "/orgs/:org/members/:user", nil},
|
||||||
{"DELETE", "/orgs/:org/members/:user"},
|
{"DELETE", "/orgs/:org/members/:user", nil},
|
||||||
{"GET", "/orgs/:org/public_members"},
|
{"GET", "/orgs/:org/public_members", nil},
|
||||||
{"GET", "/orgs/:org/public_members/:user"},
|
{"GET", "/orgs/:org/public_members/:user", nil},
|
||||||
{"PUT", "/orgs/:org/public_members/:user"},
|
{"PUT", "/orgs/:org/public_members/:user", nil},
|
||||||
{"DELETE", "/orgs/:org/public_members/:user"},
|
{"DELETE", "/orgs/:org/public_members/:user", nil},
|
||||||
{"GET", "/orgs/:org/teams"},
|
{"GET", "/orgs/:org/teams", nil},
|
||||||
{"GET", "/teams/:id"},
|
{"GET", "/teams/:id", nil},
|
||||||
{"POST", "/orgs/:org/teams"},
|
{"POST", "/orgs/:org/teams", nil},
|
||||||
//{"PATCH", "/teams/:id"},
|
//{"PATCH", "/teams/:id", nil},
|
||||||
{"DELETE", "/teams/:id"},
|
{"DELETE", "/teams/:id", nil},
|
||||||
{"GET", "/teams/:id/members"},
|
{"GET", "/teams/:id/members", nil},
|
||||||
{"GET", "/teams/:id/members/:user"},
|
{"GET", "/teams/:id/members/:user", nil},
|
||||||
{"PUT", "/teams/:id/members/:user"},
|
{"PUT", "/teams/:id/members/:user", nil},
|
||||||
{"DELETE", "/teams/:id/members/:user"},
|
{"DELETE", "/teams/:id/members/:user", nil},
|
||||||
{"GET", "/teams/:id/repos"},
|
{"GET", "/teams/:id/repos", nil},
|
||||||
{"GET", "/teams/:id/repos/:owner/:repo"},
|
{"GET", "/teams/:id/repos/:owner/:repo", nil},
|
||||||
{"PUT", "/teams/:id/repos/:owner/:repo"},
|
{"PUT", "/teams/:id/repos/:owner/:repo", nil},
|
||||||
{"DELETE", "/teams/:id/repos/:owner/:repo"},
|
{"DELETE", "/teams/:id/repos/:owner/:repo", nil},
|
||||||
{"GET", "/user/teams"},
|
{"GET", "/user/teams", nil},
|
||||||
|
|
||||||
// Pull Requests
|
// Pull Requests
|
||||||
{"GET", "/repos/:owner/:repo/pulls"},
|
{"GET", "/repos/:owner/:repo/pulls", nil},
|
||||||
{"GET", "/repos/:owner/:repo/pulls/:number"},
|
{"GET", "/repos/:owner/:repo/pulls/:number", nil},
|
||||||
{"POST", "/repos/:owner/:repo/pulls"},
|
{"POST", "/repos/:owner/:repo/pulls", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/pulls/:number"},
|
//{"PATCH", "/repos/:owner/:repo/pulls/:number", nil},
|
||||||
{"GET", "/repos/:owner/:repo/pulls/:number/commits"},
|
{"GET", "/repos/:owner/:repo/pulls/:number/commits", nil},
|
||||||
{"GET", "/repos/:owner/:repo/pulls/:number/files"},
|
{"GET", "/repos/:owner/:repo/pulls/:number/files", nil},
|
||||||
{"GET", "/repos/:owner/:repo/pulls/:number/merge"},
|
{"GET", "/repos/:owner/:repo/pulls/:number/merge", nil},
|
||||||
{"PUT", "/repos/:owner/:repo/pulls/:number/merge"},
|
{"PUT", "/repos/:owner/:repo/pulls/:number/merge", nil},
|
||||||
{"GET", "/repos/:owner/:repo/pulls/:number/comments"},
|
{"GET", "/repos/:owner/:repo/pulls/:number/comments", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/pulls/comments"},
|
//{"GET", "/repos/:owner/:repo/pulls/comments", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/pulls/comments/:number"},
|
//{"GET", "/repos/:owner/:repo/pulls/comments/:number", nil},
|
||||||
{"PUT", "/repos/:owner/:repo/pulls/:number/comments"},
|
{"PUT", "/repos/:owner/:repo/pulls/:number/comments", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/pulls/comments/:number"},
|
//{"PATCH", "/repos/:owner/:repo/pulls/comments/:number", nil},
|
||||||
//{"DELETE", "/repos/:owner/:repo/pulls/comments/:number"},
|
//{"DELETE", "/repos/:owner/:repo/pulls/comments/:number", nil},
|
||||||
|
|
||||||
// Repositories
|
// Repositories
|
||||||
{"GET", "/user/repos"},
|
{"GET", "/user/repos", nil},
|
||||||
{"GET", "/users/:user/repos"},
|
{"GET", "/users/:user/repos", nil},
|
||||||
{"GET", "/orgs/:org/repos"},
|
{"GET", "/orgs/:org/repos", nil},
|
||||||
{"GET", "/repositories"},
|
{"GET", "/repositories", nil},
|
||||||
{"POST", "/user/repos"},
|
{"POST", "/user/repos", nil},
|
||||||
{"POST", "/orgs/:org/repos"},
|
{"POST", "/orgs/:org/repos", nil},
|
||||||
{"GET", "/repos/:owner/:repo"},
|
{"GET", "/repos/:owner/:repo", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo"},
|
//{"PATCH", "/repos/:owner/:repo", nil},
|
||||||
{"GET", "/repos/:owner/:repo/contributors"},
|
{"GET", "/repos/:owner/:repo/contributors", nil},
|
||||||
{"GET", "/repos/:owner/:repo/languages"},
|
{"GET", "/repos/:owner/:repo/languages", nil},
|
||||||
{"GET", "/repos/:owner/:repo/teams"},
|
{"GET", "/repos/:owner/:repo/teams", nil},
|
||||||
{"GET", "/repos/:owner/:repo/tags"},
|
{"GET", "/repos/:owner/:repo/tags", nil},
|
||||||
{"GET", "/repos/:owner/:repo/branches"},
|
{"GET", "/repos/:owner/:repo/branches", nil},
|
||||||
{"GET", "/repos/:owner/:repo/branches/:branch"},
|
{"GET", "/repos/:owner/:repo/branches/:branch", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo"},
|
{"DELETE", "/repos/:owner/:repo", nil},
|
||||||
{"GET", "/repos/:owner/:repo/collaborators"},
|
{"GET", "/repos/:owner/:repo/collaborators", nil},
|
||||||
{"GET", "/repos/:owner/:repo/collaborators/:user"},
|
{"GET", "/repos/:owner/:repo/collaborators/:user", nil},
|
||||||
{"PUT", "/repos/:owner/:repo/collaborators/:user"},
|
{"PUT", "/repos/:owner/:repo/collaborators/:user", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/collaborators/:user"},
|
{"DELETE", "/repos/:owner/:repo/collaborators/:user", nil},
|
||||||
{"GET", "/repos/:owner/:repo/comments"},
|
{"GET", "/repos/:owner/:repo/comments", nil},
|
||||||
{"GET", "/repos/:owner/:repo/commits/:sha/comments"},
|
{"GET", "/repos/:owner/:repo/commits/:sha/comments", nil},
|
||||||
{"POST", "/repos/:owner/:repo/commits/:sha/comments"},
|
{"POST", "/repos/:owner/:repo/commits/:sha/comments", nil},
|
||||||
{"GET", "/repos/:owner/:repo/comments/:id"},
|
{"GET", "/repos/:owner/:repo/comments/:id", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/comments/:id"},
|
//{"PATCH", "/repos/:owner/:repo/comments/:id", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/comments/:id"},
|
{"DELETE", "/repos/:owner/:repo/comments/:id", nil},
|
||||||
{"GET", "/repos/:owner/:repo/commits"},
|
{"GET", "/repos/:owner/:repo/commits", nil},
|
||||||
{"GET", "/repos/:owner/:repo/commits/:sha"},
|
{"GET", "/repos/:owner/:repo/commits/:sha", nil},
|
||||||
{"GET", "/repos/:owner/:repo/readme"},
|
{"GET", "/repos/:owner/:repo/readme", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/contents/*path"},
|
//{"GET", "/repos/:owner/:repo/contents/*path", nil},
|
||||||
//{"PUT", "/repos/:owner/:repo/contents/*path"},
|
//{"PUT", "/repos/:owner/:repo/contents/*path", nil},
|
||||||
//{"DELETE", "/repos/:owner/:repo/contents/*path"},
|
//{"DELETE", "/repos/:owner/:repo/contents/*path", nil},
|
||||||
//{"GET", "/repos/:owner/:repo/:archive_format/:ref"},
|
//{"GET", "/repos/:owner/:repo/:archive_format/:ref", nil},
|
||||||
{"GET", "/repos/:owner/:repo/keys"},
|
{"GET", "/repos/:owner/:repo/keys", nil},
|
||||||
{"GET", "/repos/:owner/:repo/keys/:id"},
|
{"GET", "/repos/:owner/:repo/keys/:id", nil},
|
||||||
{"POST", "/repos/:owner/:repo/keys"},
|
{"POST", "/repos/:owner/:repo/keys", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/keys/:id"},
|
//{"PATCH", "/repos/:owner/:repo/keys/:id", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/keys/:id"},
|
{"DELETE", "/repos/:owner/:repo/keys/:id", nil},
|
||||||
{"GET", "/repos/:owner/:repo/downloads"},
|
{"GET", "/repos/:owner/:repo/downloads", nil},
|
||||||
{"GET", "/repos/:owner/:repo/downloads/:id"},
|
{"GET", "/repos/:owner/:repo/downloads/:id", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/downloads/:id"},
|
{"DELETE", "/repos/:owner/:repo/downloads/:id", nil},
|
||||||
{"GET", "/repos/:owner/:repo/forks"},
|
{"GET", "/repos/:owner/:repo/forks", nil},
|
||||||
{"POST", "/repos/:owner/:repo/forks"},
|
{"POST", "/repos/:owner/:repo/forks", nil},
|
||||||
{"GET", "/repos/:owner/:repo/hooks"},
|
{"GET", "/repos/:owner/:repo/hooks", nil},
|
||||||
{"GET", "/repos/:owner/:repo/hooks/:id"},
|
{"GET", "/repos/:owner/:repo/hooks/:id", nil},
|
||||||
{"POST", "/repos/:owner/:repo/hooks"},
|
{"POST", "/repos/:owner/:repo/hooks", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/hooks/:id"},
|
//{"PATCH", "/repos/:owner/:repo/hooks/:id", nil},
|
||||||
{"POST", "/repos/:owner/:repo/hooks/:id/tests"},
|
{"POST", "/repos/:owner/:repo/hooks/:id/tests", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/hooks/:id"},
|
{"DELETE", "/repos/:owner/:repo/hooks/:id", nil},
|
||||||
{"POST", "/repos/:owner/:repo/merges"},
|
{"POST", "/repos/:owner/:repo/merges", nil},
|
||||||
{"GET", "/repos/:owner/:repo/releases"},
|
{"GET", "/repos/:owner/:repo/releases", nil},
|
||||||
{"GET", "/repos/:owner/:repo/releases/:id"},
|
{"GET", "/repos/:owner/:repo/releases/:id", nil},
|
||||||
{"POST", "/repos/:owner/:repo/releases"},
|
{"POST", "/repos/:owner/:repo/releases", nil},
|
||||||
//{"PATCH", "/repos/:owner/:repo/releases/:id"},
|
//{"PATCH", "/repos/:owner/:repo/releases/:id", nil},
|
||||||
{"DELETE", "/repos/:owner/:repo/releases/:id"},
|
{"DELETE", "/repos/:owner/:repo/releases/:id", nil},
|
||||||
{"GET", "/repos/:owner/:repo/releases/:id/assets"},
|
{"GET", "/repos/:owner/:repo/releases/:id/assets", nil},
|
||||||
{"GET", "/repos/:owner/:repo/stats/contributors"},
|
{"GET", "/repos/:owner/:repo/stats/contributors", nil},
|
||||||
{"GET", "/repos/:owner/:repo/stats/commit_activity"},
|
{"GET", "/repos/:owner/:repo/stats/commit_activity", nil},
|
||||||
{"GET", "/repos/:owner/:repo/stats/code_frequency"},
|
{"GET", "/repos/:owner/:repo/stats/code_frequency", nil},
|
||||||
{"GET", "/repos/:owner/:repo/stats/participation"},
|
{"GET", "/repos/:owner/:repo/stats/participation", nil},
|
||||||
{"GET", "/repos/:owner/:repo/stats/punch_card"},
|
{"GET", "/repos/:owner/:repo/stats/punch_card", nil},
|
||||||
{"GET", "/repos/:owner/:repo/statuses/:ref"},
|
{"GET", "/repos/:owner/:repo/statuses/:ref", nil},
|
||||||
{"POST", "/repos/:owner/:repo/statuses/:ref"},
|
{"POST", "/repos/:owner/:repo/statuses/:ref", nil},
|
||||||
|
|
||||||
// Search
|
// Search
|
||||||
{"GET", "/search/repositories"},
|
{"GET", "/search/repositories", nil},
|
||||||
{"GET", "/search/code"},
|
{"GET", "/search/code", nil},
|
||||||
{"GET", "/search/issues"},
|
{"GET", "/search/issues", nil},
|
||||||
{"GET", "/search/users"},
|
{"GET", "/search/users", nil},
|
||||||
{"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword"},
|
{"GET", "/legacy/issues/search/:owner/:repository/:state/:keyword", nil},
|
||||||
{"GET", "/legacy/repos/search/:keyword"},
|
{"GET", "/legacy/repos/search/:keyword", nil},
|
||||||
{"GET", "/legacy/user/search/:keyword"},
|
{"GET", "/legacy/user/search/:keyword", nil},
|
||||||
{"GET", "/legacy/user/email/:email"},
|
{"GET", "/legacy/user/email/:email", nil},
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
{"GET", "/users/:user"},
|
{"GET", "/users/:user", nil},
|
||||||
{"GET", "/user"},
|
{"GET", "/user", nil},
|
||||||
//{"PATCH", "/user"},
|
//{"PATCH", "/user", nil},
|
||||||
{"GET", "/users"},
|
{"GET", "/users", nil},
|
||||||
{"GET", "/user/emails"},
|
{"GET", "/user/emails", nil},
|
||||||
{"POST", "/user/emails"},
|
{"POST", "/user/emails", nil},
|
||||||
{"DELETE", "/user/emails"},
|
{"DELETE", "/user/emails", nil},
|
||||||
{"GET", "/users/:user/followers"},
|
{"GET", "/users/:user/followers", nil},
|
||||||
{"GET", "/user/followers"},
|
{"GET", "/user/followers", nil},
|
||||||
{"GET", "/users/:user/following"},
|
{"GET", "/users/:user/following", nil},
|
||||||
{"GET", "/user/following"},
|
{"GET", "/user/following", nil},
|
||||||
{"GET", "/user/following/:user"},
|
{"GET", "/user/following/:user", nil},
|
||||||
{"GET", "/users/:user/following/:target_user"},
|
{"GET", "/users/:user/following/:target_user", nil},
|
||||||
{"PUT", "/user/following/:user"},
|
{"PUT", "/user/following/:user", nil},
|
||||||
{"DELETE", "/user/following/:user"},
|
{"DELETE", "/user/following/:user", nil},
|
||||||
{"GET", "/users/:user/keys"},
|
{"GET", "/users/:user/keys", nil},
|
||||||
{"GET", "/user/keys"},
|
{"GET", "/user/keys", nil},
|
||||||
{"GET", "/user/keys/:id"},
|
{"GET", "/user/keys/:id", nil},
|
||||||
{"POST", "/user/keys"},
|
{"POST", "/user/keys", nil},
|
||||||
//{"PATCH", "/user/keys/:id"},
|
//{"PATCH", "/user/keys/:id", nil},
|
||||||
{"DELETE", "/user/keys/:id"},
|
{"DELETE", "/user/keys/:id", nil},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -506,7 +501,7 @@ func TestRouterParamNames(t *testing.T) {
|
|||||||
func TestRouterAPI(t *testing.T) {
|
func TestRouterAPI(t *testing.T) {
|
||||||
r := New().router
|
r := New().router
|
||||||
for _, route := range api {
|
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 {
|
for i, n := range c.pnames {
|
||||||
if assert.NotEmpty(t, n) {
|
if assert.NotEmpty(t, n) {
|
||||||
assert.Equal(t, ":"+n, c.P(uint8(i)))
|
assert.Equal(t, ":"+n, c.P(uint8(i)))
|
||||||
@@ -514,7 +509,7 @@ func TestRouterAPI(t *testing.T) {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}, nil)
|
}, nil)
|
||||||
h, _ := r.Find(route.method, route.path, context)
|
h, _ := r.Find(route.Method, route.Path, context)
|
||||||
if assert.NotNil(t, h) {
|
if assert.NotNil(t, h) {
|
||||||
h(context)
|
h(context)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user