Skip to content

Commit

Permalink
Add new middleware signature (#3)
Browse files Browse the repository at this point in the history
closes #3
  • Loading branch information
anjmao authored Jul 18, 2019
1 parent 56e267a commit 6378588
Show file tree
Hide file tree
Showing 8 changed files with 200 additions and 178 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ type hello struct {
func main() {
mux := route.NewServeMux()

mux.GET("/", func (ctx route.Context) error {
return ctx.JSON(http.StatusOK, &hello{Title:"Hello, World!"})
mux.GET("/", func (c route.Context) error {
return c.JSON(http.StatusOK, &hello{Title:"Hello, World!"})
})

log.Fatal(http.ListenAndServe(":9000", mux))
Expand Down
21 changes: 21 additions & 0 deletions example/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

import (
"github.com/goroute/route"
"log"
"net/http"
)

type hello struct {
Title string
}

func main() {
mux := route.NewServeMux()

mux.GET("/", func(c route.Context) error {
return c.JSON(http.StatusOK, &hello{Title: "Hello, World!"})
})

log.Fatal(http.ListenAndServe(":9000", mux))
}
26 changes: 12 additions & 14 deletions group.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,22 @@ import (
"path"
)

type (
// Group is a set of sub-routes for a specified route. It can be used for inner
// routes that share a common middleware or functionality that should be separate
// from the parent mux instance while still inheriting from it.
Group struct {
prefix string
middleware []MiddlewareFunc
nio *Mux
}
)
// Group is a set of sub-routes for a specified route. It can be used for inner
// routes that share a common middleware or functionality that should be separate
// from the parent mux instance while still inheriting from it.
type Group struct {
prefix string
middleware []MiddlewareFunc
mux *Mux
}

// Use implements `Mux#Use()` for sub-routes within the Group.
func (g *Group) Use(middleware ...MiddlewareFunc) {
g.middleware = append(g.middleware, middleware...)
// Allow all requests to reach the group as they might get dropped if router
// doesn't find a match, making none of the group middleware process.
for _, p := range []string{"", "/*"} {
g.nio.Any(path.Clean(g.prefix+p), func(c Context) error {
g.mux.Any(path.Clean(g.prefix+p), func(c Context) error {
return NotFoundHandler(c)
}, g.middleware...)
}
Expand Down Expand Up @@ -96,7 +94,7 @@ func (g *Group) Group(prefix string, middleware ...MiddlewareFunc) *Group {
m := make([]MiddlewareFunc, 0, len(g.middleware)+len(middleware))
m = append(m, g.middleware...)
m = append(m, middleware...)
return g.nio.Group(g.prefix+prefix, m...)
return g.mux.Group(g.prefix+prefix, m...)
}

// Static implements `Mux#Static()` for sub-routes within the Group.
Expand All @@ -106,7 +104,7 @@ func (g *Group) Static(prefix, root string) {

// File implements `Mux#File()` for sub-routes within the Group.
func (g *Group) File(path, file string) {
g.nio.File(g.prefix+path, file)
g.mux.File(g.prefix+path, file)
}

// Add implements `Mux#Add()` for sub-routes within the Group.
Expand All @@ -117,5 +115,5 @@ func (g *Group) Add(method, path string, handler HandlerFunc, middleware ...Midd
m := make([]MiddlewareFunc, 0, len(g.middleware)+len(middleware))
m = append(m, g.middleware...)
m = append(m, middleware...)
return g.nio.Add(method, g.prefix+path, handler, m...)
return g.mux.Add(method, g.prefix+path, handler, m...)
}
30 changes: 10 additions & 20 deletions group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,20 @@ func TestGroupRouteMiddleware(t *testing.T) {
e := NewServeMux()
g := e.Group("/group")
h := func(Context) error { return nil }
m1 := func(next HandlerFunc) HandlerFunc {
return func(c Context) error {
return next(c)
}
m1 := func(c Context, next HandlerFunc) error {
return next(c)
}
m2 := func(next HandlerFunc) HandlerFunc {
return func(c Context) error {
return next(c)
}
m2 := func(c Context, next HandlerFunc) error {
return next(c)
}
m3 := func(next HandlerFunc) HandlerFunc {
return func(c Context) error {
return next(c)
}
m3 := func(c Context, next HandlerFunc) error {
return next(c)
}
m4 := func(next HandlerFunc) HandlerFunc {
return func(c Context) error {
return c.NoContent(404)
}
m4 := func(c Context, next HandlerFunc) error {
return c.NoContent(404)
}
m5 := func(next HandlerFunc) HandlerFunc {
return func(c Context) error {
return c.NoContent(405)
}
m5 := func(c Context, next HandlerFunc) error {
return c.NoContent(405)
}
g.Use(m1, m2, m3)
g.GET("/404", h, m4)
Expand Down
23 changes: 14 additions & 9 deletions middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "net/http"

type (
// MiddlewareFunc defines a function to process middleware.
MiddlewareFunc func(HandlerFunc) HandlerFunc
MiddlewareFunc func(c Context, next HandlerFunc) error

// Skipper defines a function to skip middleware. Returning true skips processing
// the middleware.
Expand All @@ -13,18 +13,23 @@ type (

// WrapMiddleware wraps `func(http.Handler) http.Handler` into `mux.MiddlewareFunc`
func WrapMiddleware(m func(http.Handler) http.Handler) MiddlewareFunc {
return func(next HandlerFunc) HandlerFunc {
return func(c Context) (err error) {
m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c.SetRequest(r)
err = next(c)
})).ServeHTTP(c.Response(), c.Request())
return
}
return func(c Context, next HandlerFunc) (err error) {
m(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c.SetRequest(r)
err = next(c)
})).ServeHTTP(c.Response(), c.Request())
return
}
}

// DefaultSkipper returns false which processes the middleware.
func DefaultSkipper(Context) bool {
return false
}

// compose chains given handler with next middleware.
func compose(h HandlerFunc, m MiddlewareFunc) HandlerFunc {
return func(c Context) error {
return m(c, h)
}
}
17 changes: 13 additions & 4 deletions middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert"
)

func TestNioWrapMiddleware(t *testing.T) {
func TestWrapMiddleware(t *testing.T) {
e := NewServeMux()
req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
Expand All @@ -21,12 +21,21 @@ func TestNioWrapMiddleware(t *testing.T) {
h.ServeHTTP(w, r)
})
})
h := mw(func(c Context) error {

h := func(c Context) error {
return c.String(http.StatusOK, "OK")
})
if assert.NoError(t, h(c)) {
}

err := mw(c, h)
if assert.NoError(t, err) {
assert.Equal(t, "mw", buf.String())
assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, "OK", rec.Body.String())
}
}

func TestDefaultSkipper(t *testing.T) {
skipper := DefaultSkipper(nil)

assert.Equal(t, false, skipper)
}
10 changes: 5 additions & 5 deletions mux.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ func (mux *Mux) Add(method, path string, handler HandlerFunc, middleware ...Midd
h := handler
// Chain middleware
for i := len(middleware) - 1; i >= 0; i-- {
h = middleware[i](h)
h = compose(h, middleware[i])
}
return h(c)
})
Expand All @@ -395,7 +395,7 @@ func (mux *Mux) Add(method, path string, handler HandlerFunc, middleware ...Midd

// Group creates a new router group with prefix and optional group-level middleware.
func (mux *Mux) Group(prefix string, m ...MiddlewareFunc) (g *Group) {
g = &Group{prefix: prefix, nio: mux}
g = &Group{prefix: prefix, mux: mux}
g.Use(m...)
return
}
Expand All @@ -421,19 +421,19 @@ func (mux *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
mux.router.find(r.Method, getPath(r), c)
h = c.Handler()
for i := len(mux.middleware) - 1; i >= 0; i-- {
h = mux.middleware[i](h)
h = compose(h, mux.middleware[i])
}
} else {
h = func(c Context) error {
mux.router.find(r.Method, getPath(r), c)
h := c.Handler()
for i := len(mux.middleware) - 1; i >= 0; i-- {
h = mux.middleware[i](h)
h = compose(h, mux.middleware[i])
}
return h(c)
}
for i := len(mux.premiddleware) - 1; i >= 0; i-- {
h = mux.premiddleware[i](h)
h = compose(h, mux.premiddleware[i])
}
}

Expand Down
Loading

0 comments on commit 6378588

Please sign in to comment.