forked from Fuyu/router
Add middleware
This commit is contained in:
parent
5a44e82541
commit
69754a9946
18
default.go
Normal file
18
default.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package router
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func defaultNotFoundHandler(c *Context) error {
|
||||||
|
return c.String(404, `not found`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultMethodNotAllowedHandler(c *Context) error {
|
||||||
|
return c.String(504, `method not allowed`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultErrorHandler(c *Context, err interface{}) {
|
||||||
|
fmt.Println(err)
|
||||||
|
c.String(500, `internal server error`)
|
||||||
|
}
|
37
group.go
37
group.go
@ -6,48 +6,49 @@ func join(prefix, path string) string {
|
|||||||
return urlpath.Join(prefix, urlpath.Clean(path))
|
return urlpath.Join(prefix, urlpath.Clean(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Group is a router group with a shared prefix and set of middlewares
|
||||||
type Group struct {
|
type Group struct {
|
||||||
router *Router
|
router *Router
|
||||||
prefix string
|
prefix string
|
||||||
|
middleware []Middleware
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) Group(prefix string) *Group {
|
// Group creates a new router group with a shared prefix and set of middlewares
|
||||||
return &Group{prefix: join(g.prefix, prefix), router: g.router}
|
func (g *Group) Group(prefix string, middleware ...Middleware) *Group {
|
||||||
|
return &Group{prefix: join(g.prefix, prefix), router: g.router, middleware: append(g.middleware, middleware...)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET adds a GET route
|
// GET adds a GET route
|
||||||
func (g *Group) GET(path string, handle GetHandle) {
|
func (g *Group) GET(path string, handle Handle, middleware ...Middleware) {
|
||||||
g.router.GET(join(g.prefix, path), handle)
|
g.router.GET(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST adds a POST route
|
// POST adds a POST route
|
||||||
func (g *Group) POST(path string, handle interface{}) {
|
func (g *Group) POST(path string, handle interface{}, middleware ...Middleware) {
|
||||||
g.router.POST(join(g.prefix, path), handle)
|
g.router.POST(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE adds a DELETE route
|
// DELETE adds a DELETE route
|
||||||
func (g *Group) DELETE(path string, handle GetHandle) {
|
func (g *Group) DELETE(path string, handle Handle, middleware ...Middleware) {
|
||||||
g.router.DELETE(join(g.prefix, path), handle)
|
g.router.DELETE(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT adds a PUT route
|
// PUT adds a PUT route
|
||||||
func (g *Group) PUT(path string, handle interface{}) {
|
func (g *Group) PUT(path string, handle interface{}, middleware ...Middleware) {
|
||||||
checkInterfaceHandle(handle)
|
g.router.PUT(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
g.router.PUT(join(g.prefix, path), handle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PATCH adds a PATCH route
|
// PATCH adds a PATCH route
|
||||||
func (g *Group) PATCH(path string, handle interface{}) {
|
func (g *Group) PATCH(path string, handle interface{}, middleware ...Middleware) {
|
||||||
checkInterfaceHandle(handle)
|
g.router.PATCH(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
g.router.PATCH(join(g.prefix, path), handle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HEAD adds a HEAD route
|
// HEAD adds a HEAD route
|
||||||
func (g *Group) HEAD(path string, handle GetHandle) {
|
func (g *Group) HEAD(path string, handle Handle, middleware ...Middleware) {
|
||||||
g.router.HEAD(join(g.prefix, path), handle)
|
g.router.HEAD(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OPTIONS adds a OPTIONS route
|
// OPTIONS adds a OPTIONS route
|
||||||
func (g *Group) OPTIONS(path string, handle GetHandle) {
|
func (g *Group) OPTIONS(path string, handle Handle, middleware ...Middleware) {
|
||||||
g.router.OPTIONS(join(g.prefix, path), handle)
|
g.router.OPTIONS(join(g.prefix, path), handle, append(g.middleware, middleware...)...)
|
||||||
}
|
}
|
||||||
|
119
router.go
119
router.go
@ -2,7 +2,6 @@ package router
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
@ -13,62 +12,79 @@ type route struct {
|
|||||||
Method string
|
Method string
|
||||||
Path string
|
Path string
|
||||||
Handle interface{}
|
Handle interface{}
|
||||||
|
Middleware []Middleware
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetHandle handles a request that doesn't receive a body
|
// Handle handles a request
|
||||||
type GetHandle func(*Context) error
|
type Handle func(*Context) error
|
||||||
|
|
||||||
|
// ErrorHandle handles a request
|
||||||
|
type ErrorHandle func(*Context, interface{})
|
||||||
|
|
||||||
|
// Middleware TODO:
|
||||||
|
type Middleware func(Handle) Handle
|
||||||
|
|
||||||
// Router is the router itself
|
// Router is the router itself
|
||||||
type Router struct {
|
type Router struct {
|
||||||
routes []route
|
routes []route
|
||||||
Renderer Renderer
|
Renderer Renderer
|
||||||
|
middleware []Middleware
|
||||||
|
NotFoundHandler Handle
|
||||||
|
MethodNotAllowedHandler Handle
|
||||||
|
ErrorHandler ErrorHandle
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a new Router
|
// New returns a new Router
|
||||||
func New() *Router {
|
func New() *Router {
|
||||||
return &Router{}
|
return &Router{NotFoundHandler: defaultNotFoundHandler, MethodNotAllowedHandler: defaultMethodNotAllowedHandler, ErrorHandler: defaultErrorHandler}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Router) Group(prefix string) *Group {
|
// Use adds a global middleware
|
||||||
return &Group{prefix: prefix, router: r}
|
func (r *Router) Use(m ...Middleware) {
|
||||||
|
r.middleware = append(r.middleware, m...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group creates a new router group with a shared prefix and set of middlewares
|
||||||
|
func (r *Router) Group(prefix string, middleware ...Middleware) *Group {
|
||||||
|
return &Group{prefix: prefix, router: r, middleware: middleware}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET adds a GET route
|
// GET adds a GET route
|
||||||
func (r *Router) GET(path string, handle GetHandle) {
|
func (r *Router) GET(path string, handle Handle, middleware ...Middleware) {
|
||||||
r.routes = append(r.routes, route{`GET`, path, handle})
|
r.routes = append(r.routes, route{`GET`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST adds a POST route
|
// POST adds a POST route
|
||||||
func (r *Router) POST(path string, handle interface{}) {
|
func (r *Router) POST(path string, handle interface{}, middleware ...Middleware) {
|
||||||
checkInterfaceHandle(handle)
|
checkInterfaceHandle(handle)
|
||||||
r.routes = append(r.routes, route{`POST`, path, handle})
|
r.routes = append(r.routes, route{`POST`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE adds a DELETE route
|
// DELETE adds a DELETE route
|
||||||
func (r *Router) DELETE(path string, handle GetHandle) {
|
func (r *Router) DELETE(path string, handle Handle, middleware ...Middleware) {
|
||||||
r.routes = append(r.routes, route{`DELETE`, path, handle})
|
r.routes = append(r.routes, route{`DELETE`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT adds a PUT route
|
// PUT adds a PUT route
|
||||||
func (r *Router) PUT(path string, handle interface{}) {
|
func (r *Router) PUT(path string, handle interface{}, middleware ...Middleware) {
|
||||||
checkInterfaceHandle(handle)
|
checkInterfaceHandle(handle)
|
||||||
r.routes = append(r.routes, route{`PUT`, path, handle})
|
r.routes = append(r.routes, route{`PUT`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// PATCH adds a PATCH route
|
// PATCH adds a PATCH route
|
||||||
func (r *Router) PATCH(path string, handle interface{}) {
|
func (r *Router) PATCH(path string, handle interface{}, middleware ...Middleware) {
|
||||||
checkInterfaceHandle(handle)
|
checkInterfaceHandle(handle)
|
||||||
r.routes = append(r.routes, route{`PATCH`, path, handle})
|
r.routes = append(r.routes, route{`PATCH`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// HEAD adds a HEAD route
|
// HEAD adds a HEAD route
|
||||||
func (r *Router) HEAD(path string, handle GetHandle) {
|
func (r *Router) HEAD(path string, handle Handle, middleware ...Middleware) {
|
||||||
r.routes = append(r.routes, route{`HEAD`, path, handle})
|
r.routes = append(r.routes, route{`HEAD`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// OPTIONS adds a OPTIONS route
|
// OPTIONS adds a OPTIONS route
|
||||||
func (r *Router) OPTIONS(path string, handle GetHandle) {
|
func (r *Router) OPTIONS(path string, handle Handle, middleware ...Middleware) {
|
||||||
r.routes = append(r.routes, route{`OPTIONS`, path, handle})
|
r.routes = append(r.routes, route{`OPTIONS`, path, handle, middleware})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts the web server and binds to the given address
|
// Start starts the web server and binds to the given address
|
||||||
@ -82,19 +98,39 @@ func (r *Router) getHttpr() *httprouter.Router {
|
|||||||
httpr := httprouter.New()
|
httpr := httprouter.New()
|
||||||
|
|
||||||
for _, v := range r.routes {
|
for _, v := range r.routes {
|
||||||
if handle, ok := v.Handle.(GetHandle); ok {
|
handle, ok := v.Handle.(Handle)
|
||||||
httpr.Handle(v.Method, v.Path, handleGET(r, handle))
|
if !ok {
|
||||||
continue
|
handle = handlePOST(r, v.Handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpr.Handle(v.Method, v.Path, handlePOST(r, v.Handle))
|
httpr.Handle(v.Method, v.Path, handleReq(r, handle, append(r.middleware, v.Middleware...)))
|
||||||
|
}
|
||||||
|
|
||||||
|
httpr.NotFound = http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
handleReq(r, r.NotFoundHandler, r.middleware)(res, req, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
httpr.MethodNotAllowed = http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
handleReq(r, r.MethodNotAllowedHandler, r.middleware)(res, req, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
httpr.PanicHandler = func(res http.ResponseWriter, req *http.Request, err interface{}) {
|
||||||
|
c := newContext(r, res, req, nil)
|
||||||
|
r.ErrorHandler(c, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return httpr
|
return httpr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleErr(errHandler ErrorHandle, err interface{}) Handle {
|
||||||
|
return func(c *Context) error {
|
||||||
|
errHandler(c, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func checkInterfaceHandle(f interface{}) {
|
func checkInterfaceHandle(f interface{}) {
|
||||||
if _, ok := f.(GetHandle); ok {
|
if _, ok := f.(Handle); ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,34 +155,41 @@ func checkInterfaceHandle(f interface{}) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func handlePOST(r *Router, f interface{}) httprouter.Handle {
|
func handlePOST(r *Router, f interface{}) Handle {
|
||||||
funcRv, inputRt := reflect.ValueOf(f), reflect.TypeOf(f).In(1)
|
funcRv, inputRt := reflect.ValueOf(f), reflect.TypeOf(f).In(1)
|
||||||
|
|
||||||
return func(res http.ResponseWriter, req *http.Request, param httprouter.Params) {
|
return func(c *Context) error {
|
||||||
c := newContext(r, res, req, param)
|
|
||||||
|
|
||||||
data := reflect.New(inputRt)
|
data := reflect.New(inputRt)
|
||||||
{
|
|
||||||
err := json.NewDecoder(req.Body).Decode(data.Interface())
|
err := json.NewDecoder(c.Request.Body).Decode(data.Interface())
|
||||||
req.Body.Close()
|
c.Request.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.NoContent(400) // TODO: send info about error (BindError)
|
c.NoContent(400) // TODO: send info about error (BindError)
|
||||||
return
|
return nil
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out := funcRv.Call([]reflect.Value{reflect.ValueOf(c), data.Elem()})
|
out := funcRv.Call([]reflect.Value{reflect.ValueOf(c), data.Elem()})
|
||||||
err := out[0].Interface()
|
|
||||||
_ = err
|
if out[0].IsNil() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return out[0].Interface().(error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleGET(r *Router, f GetHandle) httprouter.Handle {
|
func handleReq(r *Router, handle Handle, m []Middleware) httprouter.Handle {
|
||||||
return func(res http.ResponseWriter, req *http.Request, param httprouter.Params) {
|
return func(res http.ResponseWriter, req *http.Request, param httprouter.Params) {
|
||||||
c := newContext(r, res, req, param)
|
c := newContext(r, res, req, param)
|
||||||
|
|
||||||
|
f := handle
|
||||||
|
for i := len(m) - 1; i >= 0; i-- { // TODO: 1,2,3 of 3,2,1
|
||||||
|
f = m[i](f)
|
||||||
|
}
|
||||||
|
|
||||||
err := f(c)
|
err := f(c)
|
||||||
|
|
||||||
fmt.Println(err)
|
if err != nil {
|
||||||
|
r.ErrorHandler(c, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user