package api import ( "github.com/gin-gonic/gin" "net/http" ) // Handler 请求处理函数 type Handler func(c *Context) // Router 路由接口 type Router interface { // AddMiddlewares 添加中间件 AddMiddlewares(middlewares ...Handler) Router // RegisterVersionedRouter 注册版本路由 RegisterVersionedRouter(version string, middlewares ...Handler) Router // VersionedRouter 获取版本路由 VersionedRouter(version string) Router // AddRoute 添加路由路径 AddRoute(method string, relativePath string, handlers ...Handler) Router // Static 静态路由(指向目录) Static(relativePath string, root string) // StaticFile 静态路由(指向文件) StaticFile(relativePath string, filepath string) // BasePath 路由的基础路径,即去掉http://ip:port之后的URL部分(不包括AddRoute的RelativePath) BasePath() string } type RootRouter struct { engine *gin.Engine versioned map[string]*PrefixRouter } func newRootRouter(engine *gin.Engine) *RootRouter { return &RootRouter{ engine: engine, versioned: make(map[string]*PrefixRouter), } } func (r *RootRouter) AddMiddlewares(middlewares ...Handler) Router { r.engine.Use(transferHandlers(middlewares...)...) return r } func (r *RootRouter) RegisterVersionedRouter(version string, middlewares ...Handler) Router { versioned := r.engine.Group(version, transferHandlers(middlewares...)...) r.versioned[version] = newPrefixRouter(versioned) return r.versioned[version] } func (r *RootRouter) Static(relativePath string, root string) { r.engine.Static(relativePath, root) } func (r *RootRouter) StaticFile(relativePath string, filepath string) { r.engine.StaticFile(relativePath, filepath) } func (r *RootRouter) BasePath() string { return r.engine.BasePath() } func (r *RootRouter) VersionedRouter(version string) Router { return r.versioned[version] } func (r *RootRouter) AddRoute(method string, relativePath string, handlers ...Handler) Router { r.engine.Handle(method, relativePath, transferHandlers(handlers...)...) return r } func (r *RootRouter) ServerHttp(w http.ResponseWriter, req *http.Request) { r.engine.ServeHTTP(w, req) } type PrefixRouter struct { groupRouter *gin.RouterGroup versioned map[string]*PrefixRouter } func newPrefixRouter(group *gin.RouterGroup) *PrefixRouter { return &PrefixRouter{ groupRouter: group, versioned: make(map[string]*PrefixRouter), } } func (r *PrefixRouter) AddMiddlewares(middlewares ...Handler) Router { r.groupRouter.Use(transferHandlers(middlewares...)...) return r } func (r *PrefixRouter) RegisterVersionedRouter(version string, middlewares ...Handler) Router { ginMiddlewares := make([]gin.HandlerFunc, 0) for _, m := range middlewares { innerM := m ginMiddlewares = append(ginMiddlewares, func(c *gin.Context) { innerM(&Context{Context: c}) }) } versioned := r.groupRouter.Group(version, ginMiddlewares...) r.versioned[version] = newPrefixRouter(versioned) return r.versioned[version] } func (r *PrefixRouter) VersionedRouter(version string) Router { return r.versioned[version] } func (r *PrefixRouter) AddRoute(method string, relativePath string, handlers ...Handler) Router { r.groupRouter.Handle(method, relativePath, transferHandlers(handlers...)...) return r } func (r *PrefixRouter) Static(relativePath string, root string) { r.groupRouter.Static(relativePath, root) } func (r *PrefixRouter) StaticFile(relativePath string, filepath string) { r.groupRouter.StaticFile(relativePath, filepath) } func (r *PrefixRouter) BasePath() string { return r.groupRouter.BasePath() } func transferHandlers(handlers ...Handler) []gin.HandlerFunc { ginHandlers := make([]gin.HandlerFunc, 0) for _, handler := range handlers { innerHandler := handler ginHandlers = append(ginHandlers, func(c *gin.Context) { innerHandler(&Context{Context: c}) }) } return ginHandlers }