Skip to content
This repository has been archived by the owner on Dec 23, 2023. It is now read-only.

Commit

Permalink
Merge a6990d5 into 6a2fc25
Browse files Browse the repository at this point in the history
  • Loading branch information
razonyang committed Apr 24, 2020
2 parents 6a2fc25 + a6990d5 commit 8d36dab
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,7 @@ under development
-----------------
- Add `Skipper`.
- Add `PathSkipper`.
- Add `IRouter.Any`: registers a new request handler function that matches any HTTP methods.

v1.11.0 April 15, 2020
----------------------
Expand Down
10 changes: 10 additions & 0 deletions route.go
Expand Up @@ -39,6 +39,10 @@ type IRouter interface {
// Delete registers a new DELETE request handler function with the given path and optional route options.
Delete(path string, handle Handle, opts ...RouteOption)

// Any registers a new request handler function that matches any HTTP methods with the given path and
// optional route options. GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH.
Any(path string, handle Handle, opts ...RouteOption)

// HandleFunc registers a new request handler function with the given path, method and optional route options.
//
// For Get, Head, Options, Post, Put, Patch and Delete requests the respective shortcut
Expand Down Expand Up @@ -144,6 +148,12 @@ func RouteName(name string) RouteOption {
}
}

func isRouteNameOption(opt RouteOption) bool {
r := &Route{}
opt(r)
return r.name != ""
}

// RouteMiddleware is a route option for chainging middlewares to a route.
func RouteMiddleware(middlewares ...MiddlewareFunc) RouteOption {
return func(r *Route) {
Expand Down
32 changes: 24 additions & 8 deletions routegroup.go
Expand Up @@ -60,19 +60,30 @@ func (r *RouteGroup) Group(path string, opts ...RouteGroupOption) IRouter {
return router
}

// Handle implements IRouter.Handle.
func (r *RouteGroup) Handle(method, path string, handle Handle, opts ...RouteOption) {
opts = append(opts, func(route *Route) {
func (r *RouteGroup) nameOption() RouteOption {
return func(route *Route) {
if route.name != "" {
route.name = r.name + "/" + route.name
}
})
if len(r.middlewares) > 0 {
opts = append(opts, func(route *Route) {
}
}

func (r RouteGroup) middlewareOption() RouteOption {
return func(route *Route) {
if len(r.middlewares) > 0 {
route.handle = Chain(route.handle, r.middlewares...)
})
}
}
r.parent.Handle(method, r.subPath(path), handle, opts...)
}

func (r *RouteGroup) combineOptions(opts []RouteOption) []RouteOption {
opts = append(opts, r.nameOption(), r.middlewareOption())
return opts
}

// Handle implements IRouter.Handle.
func (r *RouteGroup) Handle(method, path string, handle Handle, opts ...RouteOption) {
r.parent.Handle(method, r.subPath(path), handle, r.combineOptions(opts)...)
}

// Handler implements IRouter.Handler.
Expand Down Expand Up @@ -120,6 +131,11 @@ func (r *RouteGroup) Delete(path string, handle Handle, opts ...RouteOption) {
r.Handle(http.MethodDelete, path, handle, opts...)
}

// Any implements IRouter.Any.
func (r *RouteGroup) Any(path string, handle Handle, opts ...RouteOption) {
r.parent.Any(r.subPath(path), handle, r.combineOptions(opts)...)
}

func (r *RouteGroup) subPath(path string) string {
return r.path + path
}
26 changes: 26 additions & 0 deletions router.go
Expand Up @@ -21,6 +21,18 @@ var (
ErrDecoderNotRegister = errors.New("decoder not registered")
)

var requestMethods = []string{
http.MethodGet,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodOptions,
http.MethodDelete,
http.MethodHead,
http.MethodConnect,
http.MethodTrace,
}

// Handle is a function which handle incoming request and manage outgoing response.
type Handle func(ctx *Context) error

Expand Down Expand Up @@ -206,6 +218,20 @@ func (r *Router) Delete(path string, handle Handle, opts ...RouteOption) {
r.Handle(http.MethodDelete, path, handle, opts...)
}

// Any implements IRouter.Any.
func (r *Router) Any(path string, handle Handle, opts ...RouteOption) {
r.Handle(requestMethods[0], path, handle, opts...)
// Removes route name option before registering handler by the rest of methods.
for i, opt := range opts {
if isRouteNameOption(opt) {
opts = append(opts[:i], opts[i+1:]...)
}
}
for i := 1; i < len(requestMethods); i++ {
r.Handle(requestMethods[i], path, handle, opts...)
}
}

// Handle implements IRouter.Handle.
func (r *Router) Handle(method, path string, handle Handle, opts ...RouteOption) {
if method == "" {
Expand Down
25 changes: 25 additions & 0 deletions router_test.go
Expand Up @@ -11,6 +11,8 @@ import (
"net/http/httptest"
"reflect"
"testing"

"github.com/stretchr/testify/assert"
)

type mockResponseWriter struct{}
Expand Down Expand Up @@ -156,6 +158,29 @@ func TestRouterAPI(t *testing.T) {
}
}

func TestRouterAny(t *testing.T) {
router := NewRouter()
handle := func(ctx *Context) error {
ctx.WriteString(ctx.Request.Method)
return nil
}
nameOpt := RouteName("ping")
router.Any("/ping", handle, nameOpt)
group := router.Group("/foo")
group.Any("/ping", handle, nameOpt)
paths := []string{"/ping", "/foo/ping"}
for _, method := range requestMethods {
for _, path := range paths {
w := httptest.NewRecorder()
router.ServeHTTP(w, httptest.NewRequest(method, path, nil))
assert.Equal(t, method, w.Body.String())
}
}
url, err := router.URL("ping")
assert.Nil(t, err)
assert.Equal(t, "/ping", url.String())
}

func TestRouterInvalidInput(t *testing.T) {
router := NewRouter()

Expand Down

0 comments on commit 8d36dab

Please sign in to comment.