156 lines
4.6 KiB
Go
156 lines
4.6 KiB
Go
|
package nf
|
||
|
|
||
|
import (
|
||
|
"math"
|
||
|
"net/http"
|
||
|
"path"
|
||
|
"regexp"
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
// regEnLetter matches english letters for http method name
|
||
|
regEnLetter = regexp.MustCompile("^[A-Z]+$")
|
||
|
|
||
|
// anyMethods for RouterGroup Any method
|
||
|
anyMethods = []string{
|
||
|
http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch,
|
||
|
http.MethodHead, http.MethodOptions, http.MethodDelete, http.MethodConnect,
|
||
|
http.MethodTrace,
|
||
|
}
|
||
|
)
|
||
|
|
||
|
// IRouter defines all router handle interface includes single and group router.
|
||
|
type IRouter interface {
|
||
|
IRoutes
|
||
|
Group(string, ...HandlerFunc) *RouterGroup
|
||
|
}
|
||
|
|
||
|
// IRoutes defines all router handle interface.
|
||
|
type IRoutes interface {
|
||
|
Use(...HandlerFunc) IRoutes
|
||
|
|
||
|
Handle(string, string, ...HandlerFunc) IRoutes
|
||
|
Any(string, ...HandlerFunc) IRoutes
|
||
|
Get(string, ...HandlerFunc) IRoutes
|
||
|
Post(string, ...HandlerFunc) IRoutes
|
||
|
Delete(string, ...HandlerFunc) IRoutes
|
||
|
Patch(string, ...HandlerFunc) IRoutes
|
||
|
Put(string, ...HandlerFunc) IRoutes
|
||
|
Options(string, ...HandlerFunc) IRoutes
|
||
|
Head(string, ...HandlerFunc) IRoutes
|
||
|
Match([]string, string, ...HandlerFunc) IRoutes
|
||
|
|
||
|
//StaticFile(string, string) IRoutes
|
||
|
//StaticFileFS(string, string, http.FileSystem) IRoutes
|
||
|
//Static(string, string) IRoutes
|
||
|
//StaticFS(string, http.FileSystem) IRoutes
|
||
|
}
|
||
|
|
||
|
type RouterGroup struct {
|
||
|
Handlers []HandlerFunc
|
||
|
basePath string
|
||
|
app *App
|
||
|
root bool
|
||
|
}
|
||
|
|
||
|
var _ IRouter = (*RouterGroup)(nil)
|
||
|
|
||
|
func (group *RouterGroup) Use(middleware ...HandlerFunc) IRoutes {
|
||
|
group.Handlers = append(group.Handlers, middleware...)
|
||
|
return group.returnObj()
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
|
||
|
return &RouterGroup{
|
||
|
Handlers: group.combineHandlers(handlers...),
|
||
|
basePath: group.calculateAbsolutePath(relativePath),
|
||
|
app: group.app,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) BasePath() string {
|
||
|
return group.basePath
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
absolutePath := group.calculateAbsolutePath(relativePath)
|
||
|
handlers = group.combineHandlers(handlers...)
|
||
|
group.app.addRoute(httpMethod, absolutePath, handlers...)
|
||
|
return group.returnObj()
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Handle(httpMethod, relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
if matched := regEnLetter.MatchString(httpMethod); !matched {
|
||
|
panic("http method " + httpMethod + " is not valid")
|
||
|
}
|
||
|
return group.handle(httpMethod, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Post(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodPost, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Get(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodGet, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Delete(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodDelete, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Patch(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodPatch, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Put(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodPut, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Options(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodOptions, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Head(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
return group.handle(http.MethodHead, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
// Any registers a route that matches all the HTTP methods.
|
||
|
// GET, POST, PUT, PATCH, HEAD, OPTIONS, DELETE, CONNECT, TRACE.
|
||
|
func (group *RouterGroup) Any(relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
for _, method := range anyMethods {
|
||
|
group.handle(method, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
return group.returnObj()
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) Match(methods []string, relativePath string, handlers ...HandlerFunc) IRoutes {
|
||
|
for _, method := range methods {
|
||
|
group.handle(method, relativePath, handlers...)
|
||
|
}
|
||
|
|
||
|
return group.returnObj()
|
||
|
}
|
||
|
|
||
|
const abortIndex int8 = math.MaxInt8 >> 1
|
||
|
|
||
|
func (group *RouterGroup) combineHandlers(handlers ...HandlerFunc) []HandlerFunc {
|
||
|
finalSize := len(group.Handlers) + len(handlers)
|
||
|
elsePanic(finalSize < int(abortIndex), "too many handlers")
|
||
|
mergedHandlers := make([]HandlerFunc, finalSize)
|
||
|
copy(mergedHandlers, group.Handlers)
|
||
|
copy(mergedHandlers[len(group.Handlers):], handlers)
|
||
|
return mergedHandlers
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) calculateAbsolutePath(relativePath string) string {
|
||
|
return path.Join(group.basePath, relativePath)
|
||
|
}
|
||
|
|
||
|
func (group *RouterGroup) returnObj() IRoutes {
|
||
|
if group.root {
|
||
|
return group.app
|
||
|
}
|
||
|
return group
|
||
|
}
|