Files
blog-server/internal/router/router.go

118 lines
2.4 KiB
Go

package router
import (
"net/http"
"os"
"path/filepath"
"server/internal/config"
"server/internal/middleware"
"server/internal/pkg/httputil"
"github.com/go-chi/chi/v5"
"go.uber.org/fx"
)
type Group string
const (
AdminPublicRoutes Group = "admin_public_routes"
AdminRoutes Group = "admin_routes"
SiteRoutes Group = "site_routes"
)
type Registrar interface {
Register(r chi.Router)
}
type Params struct {
fx.In
Jwt *middleware.JWTMiddleware
Auth *middleware.AuthMiddleware
Logger *middleware.LoggerMiddleware
AdminPublicRoutes []Registrar `group:"admin_public_routes"`
AdminRoutes []Registrar `group:"admin_routes"`
SiteRoutes []Registrar `group:"site_routes"`
}
func NewRouter(p Params) *chi.Mux {
mux := chi.NewRouter()
mux.Use(p.Logger.Middleware)
if config.IsDev() {
// 开放静态目录
registerStaticFiles(mux)
// 开发阶段:遍历所有已注册路由的清单接口(无鉴权)
mux.Get("/api/admin/routes", ListRoutes(mux))
}
mux.Route("/api/admin", func(r chi.Router) {
// 免鉴权接口
for _, route := range p.AdminPublicRoutes {
route.Register(r)
}
r.Group(func(r chi.Router) {
// jwt 和 auth中间件
r.Use(p.Jwt.Middleware)
r.Use(p.Auth.Middleware(mux))
// 循环挂载所有后台业务模块
for _, route := range p.AdminRoutes {
route.Register(r)
}
})
})
mux.Route("/api", func(r chi.Router) {
for _, route := range p.SiteRoutes {
route.Register(r)
}
})
return mux
}
func registerStaticFiles(r chi.Router) {
rootDir, _ := os.Getwd()
uploadsDir := filepath.Join(rootDir, "uploads")
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir(uploadsDir))))
}
// RouteInfo 路由信息
type RouteInfo struct {
Method string `json:"method"`
Path string `json:"path"`
}
// ListRoutes 遍历所有已注册的路由
func ListRoutes(mux *chi.Mux) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var routes []RouteInfo
err := chi.Walk(mux, func(method string, route string, _ http.Handler, _ ...func(http.Handler) http.Handler) error {
routes = append(routes, RouteInfo{Method: method, Path: route})
return nil
})
if err != nil {
httputil.Fail(w, err)
return
}
httputil.Ok(w, routes)
}
}
func AsRegistrar(group Group, f any) any {
return fx.Annotate(
f,
fx.As(new(Registrar)),
fx.ResultTags(`group:"`+string(group)+`"`),
)
}