加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
virtrouter.go 16.80 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745
package lessgo
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"os"
pathpkg "path"
"sort"
"strings"
"sync"
"github.com/henrylee2cn/lessgo/utils"
"github.com/henrylee2cn/lessgoext/uuid"
)
// 单独注册的静态文件虚拟路由(无法在Root()下使用,暂不支持运行时修改)
type VirtFile struct {
Path string
File string
Middlewares []*MiddlewareConfig
}
// 从单独静态文件虚拟路由注册真实路由
func (this *VirtFile) route() {
app.file(this.Path, this.File, getMiddlewareFuncs(this.Middlewares)...)
}
// 单独注册的静态目录虚拟路由(无法在Root()下使用,暂不支持运行时修改)
type VirtStatic struct {
Prefix string
Root string
Middlewares []*MiddlewareConfig
}
// 从单独静态目录虚拟路由注册真实路由
func (this *VirtStatic) route() {
app.static(this.Prefix, this.Root, getMiddlewareFuncs(this.Middlewares)...)
}
// 虚拟路由(在Root()下使用,支持运行时修改)
type VirtRouter struct {
Id string `json:"id""` // UUID
Type int `json:"type""` // 操作类型: 根目录/路由分组/操作
Prefix string `json:"prefix"` // 路由节点的url前缀(不含参数)
Middlewares []*MiddlewareConfig `json:"middlewares"` // 中间件列表 (允许运行时修改)
Enable bool `json:"enable"` // 是否启用当前路由节点
Dynamic bool `json:"dynamic"` // 是否动态追加的节点
Hid string `json:"hid"` // 操作ApiHandler.id
Children virtRouterSlice `json:"children"` // 子节点
Parent *VirtRouter `json:"-"` // 父节点
path string `json:"-"` // 路由匹配模式
suffix string `json:"-"` // 路由匹配模式path参数后缀
apiHandler *ApiHandler `json:"-"` // 操作
params []Param `json:"-"` // 所有参数的列表,含前面节点的中间件
}
// 虚拟路由节点类型
const (
ROOT int = iota
GROUP
HANDLER
)
var (
// 虚拟路由记录表,便于快速查找路由节点
virtRouterMap = map[string]*VirtRouter{}
virtRouterMapLock sync.RWMutex
// 非动态节点不可修改
notDynamicError = fmt.Errorf("The specified node is not dynamic, and therefore can not be modified.")
)
// 获取操作的请求方法列表(已排序)
func (vr *VirtRouter) Methods() []string {
return vr.apiHandler.Methods()
}
// 操作的描述
func (vr *VirtRouter) Description() string {
return vr.apiHandler.Desc
}
// 节点所有参数的说明列表
func (vr *VirtRouter) Params() []Param {
return vr.params
}
// 操作的返回结果说明列表
func (vr *VirtRouter) HTTP200() []Result {
return vr.apiHandler.HTTP200
}
// 子孙虚拟路由节点列表
func (vr *VirtRouter) Progeny() []*VirtRouter {
vrs := []*VirtRouter{vr}
for _, novre := range vr.Children {
vrs = append(vrs, novre.Progeny()...)
}
return vrs
}
// 虚拟路由节点path
func (vr *VirtRouter) Path() string {
return vr.path
}
// 节点排序
func (v *VirtRouter) Sort() *VirtRouter {
sort.Sort(v.Children)
for _, child := range v.Children {
child.Sort()
}
return v
}
// 设置虚拟路由节点url前缀
func (vr *VirtRouter) SetPrefix(prefix string) (err error) {
if !vr.Dynamic {
return notDynamicError
}
_orgin := vr.Prefix
vr.Prefix = prefix
vr.reset()
err = saveVirtRouterConfig()
if err != nil {
// 数据回滚
vr.Prefix = _orgin
vr.reset()
}
return
}
// 操作的参数匹配模式
func (vr *VirtRouter) Suffix() string {
return vr.suffix
}
// 启用/禁用虚拟路由节点
func (vr *VirtRouter) SetEnable(able bool) (err error) {
if !vr.Dynamic {
return notDynamicError
}
_orgin := vr.Enable
vr.Enable = able
err = saveVirtRouterConfig()
if err != nil {
// 数据回滚
vr.Enable = _orgin
}
return
}
// 配置中间件(仅在源码中使用),
// 因为源码路由书写格式需要,仅允许返回*VirtRouter一个参数,
// 而动态配置时需要有error反馈因此,该方法仅限源码中使用。
func (vr *VirtRouter) Use(middlewares ...*ApiMiddleware) *VirtRouter {
if vr.Dynamic {
Log.Error("Specified node is dynamic, please use ResetUse(middlewares []string) (err error).")
return vr
}
l := len(middlewares)
if l == 0 {
return vr
}
_l := len(vr.Middlewares)
ms := make([]*MiddlewareConfig, _l+l)
copy(ms, vr.Middlewares)
for i, m := range middlewares {
m.init()
ms[i+_l] = m.NewMiddlewareConfig()
}
vr.Middlewares = ms
vr.reset()
return vr
}
// 重置中间件
func (vr *VirtRouter) ResetUse(middlewares []*MiddlewareConfig) (err error) {
if !vr.Dynamic {
return notDynamicError
}
if middlewares == nil {
middlewares = []*MiddlewareConfig{}
}
orgin := vr.Middlewares
vr.Middlewares = middlewares
vr.reset()
err = saveVirtRouterConfig()
if err != nil {
// 数据回滚
vr.Middlewares = orgin
vr.reset()
}
return
}
// 获取虚拟路由节点的中间件
func (vr *VirtRouter) GetMiddlewareConfig(name string) (*MiddlewareConfig, bool) {
for _, m := range vr.Middlewares {
if m.Name == name {
return m, true
}
}
return nil, false
}
// 为节点更换操作
func (vr *VirtRouter) SetApiHandler(hid string) (err error) {
if !vr.Dynamic {
return notDynamicError
}
vh := getApiHandler(hid)
if vh == nil {
return fmt.Errorf("Specified ApiHandler does not exist.")
}
_hid := vr.Hid
_vh := vr.apiHandler
vr.Hid = hid
vr.apiHandler = vh
vr.reset()
err = saveVirtRouterConfig()
if err != nil {
// 数据回滚
vr.Hid = _hid
vr.apiHandler = _vh
vr.reset()
}
return
}
// 添加子节点(仅限动态配置时使用)
func (vr *VirtRouter) AddChild(virtRouter *VirtRouter) (err error) {
if !virtRouter.Dynamic {
return notDynamicError
}
return vr.addChild(virtRouter)
}
// 删除子节点(仅限动态配置时使用)
func (vr *VirtRouter) DelChild(virtRouter *VirtRouter) (err error) {
if !virtRouter.Dynamic {
return notDynamicError
}
return vr.delChild(virtRouter)
}
// 删除自身(仅限动态配置时使用)
func (vr *VirtRouter) Delete() (err error) {
if !vr.Dynamic {
return notDynamicError
}
return vr.delete()
}
// 添加子节点
func (vr *VirtRouter) addChild(virtRouter *VirtRouter) (err error) {
if virtRouter == nil {
return fmt.Errorf("Can not add an empty node.")
}
if virtRouter.Type == ROOT {
return fmt.Errorf("Can not add an root node.")
}
virtRouter.Parent = vr
children := make([]*VirtRouter, len(vr.Children))
copy(children, vr.Children)
vr.Children = append(vr.Children, virtRouter)
virtRouter.reset()
err = saveVirtRouterConfig()
if err != nil {
// 数据回滚
vr.Children = children
} else {
addVirtRouter(virtRouter)
}
return
}
// 删除自身
func (vr *VirtRouter) delete() error {
if vr.Parent != nil {
vr.Parent.delChild(vr)
return nil
}
return fmt.Errorf("Can not delete the root node.")
}
// 删除子节点
func (vr *VirtRouter) delChild(virtRouter *VirtRouter) (err error) {
if virtRouter == nil {
return fmt.Errorf("Can not delete an empty node.")
}
var exist bool
for i, child := range vr.Children {
if child == virtRouter {
children := make([]*VirtRouter, len(vr.Children))
copy(children, vr.Children)
vr.Children = append(vr.Children[:i], vr.Children[i+1:]...)
err = saveVirtRouterConfig()
if err != nil {
// 数据回滚
vr.Children = children
return
} else {
exist = true
}
break
}
}
if exist {
for _, node := range virtRouter.Progeny() {
delVirtRouter(node)
}
return nil
}
return fmt.Errorf("node %v does not have child node: %v.", vr.Description(), virtRouter.Description())
}
// 对从配置文件读来的路由进行部分字段的初始化
func (vr *VirtRouter) initFromConfig(updateVirtRouterMap bool) {
// 获取操作
vr.apiHandler = getApiHandler(vr.Hid)
if vr.apiHandler == nil {
// 移除无效的操作类节点
if vr.Type == HANDLER {
parent := vr.Parent
if parent == nil {
return
}
for i, child := range parent.Children {
if child == vr {
parent.Children = append(parent.Children[:i], parent.Children[i+1:]...)
return
}
}
return
}
// 为根节点或分组节点时
// 为分组类节点添加空操作
vr.apiHandler = NilApiHandler("?")
}
// 设置节点path和params
vr.setParamsAndPath()
// 更新节点索引
if updateVirtRouterMap {
setVirtRouter(vr)
}
for _, child := range vr.Children {
child.Parent = vr
child.initFromConfig(updateVirtRouterMap)
}
}
// 格式化路由
// 设置节点及其子节点的path和params
// 根据path排序同级节点
func (vr *VirtRouter) reset() {
vr.setParamsAndPathForTree()
if vr.Parent != nil {
sort.Sort(vr.Parent.Children)
}
}
// 设置节点及其子节点的path和params
func (vr *VirtRouter) setParamsAndPathForTree() {
vr.setParamsAndPath()
for _, child := range vr.Children {
child.setParamsAndPathForTree()
}
}
// 设置节点path和params
func (vr *VirtRouter) setParamsAndPath() {
paramMap := make(map[string]Param)
pk := []string{}
// 继承父节点信息
var parentPath = "/"
if vr.Parent != nil {
parentPath = vr.Parent.path
for _, p := range vr.Parent.params {
k := p.In + p.Name
paramMap[k] = p
pk = append(pk, k)
}
}
// 处理中间件中参数信息
for _, m := range vr.Middlewares {
err := m.initApiMiddleware()
if err != nil {
Log.Error(err.Error())
continue
}
for _, p := range m.GetApiMiddleware().Params {
k := p.In + p.Name
had, ok := paramMap[k]
if ok {
p.Required = had.Required || p.Required
} else {
pk = append(pk, k)
}
paramMap[k] = p
}
}
// 处理操作中参数信息
if vr.apiHandler != nil {
for _, p := range vr.apiHandler.Params {
k := p.In + p.Name
had, ok := paramMap[k]
if ok {
p.Required = had.Required || p.Required
} else {
pk = append(pk, k)
}
paramMap[k] = p
}
}
// 设置节点最终参数列表
vr.params = make([]Param, len(pk))
vr.suffix = ""
for k, v := range pk {
vr.params[k] = paramMap[v]
// 设置URL中path参数
if vr.params[k].In == "path" {
vr.params[k].Required = true //path参数不可缺省
if vr.Type == HANDLER {
vr.suffix += "/:" + vr.params[k].Name
}
}
}
// 设置节点path
if vr.Type == HANDLER {
vr.path = pathpkg.Join("/", parentPath, vr.Prefix, vr.suffix)
} else {
vr.path = pathpkg.Join("/", parentPath, vr.Prefix)
}
}
// 注册真实路由
func (vr *VirtRouter) route(g *Group) {
if !vr.Enable {
return
}
mws := getMiddlewareFuncs(vr.Middlewares)
prefix := pathpkg.Join("/", vr.Prefix, vr.suffix)
prefix2 := pathpkg.Join("/", strings.TrimSuffix(vr.Prefix, "/index"), vr.suffix)
omitIndex := prefix2 != prefix && vr.suffix == ""
switch vr.Type {
case GROUP:
var childGroup *Group
if omitIndex {
// "/index"分组会被默认为"/"
childGroup = g.group(prefix2, mws...)
} else {
childGroup = g.group(prefix, mws...)
}
for _, child := range vr.Children {
child.route(childGroup)
}
case HANDLER:
if omitIndex {
g.match(vr.Methods(), prefix2, vr.apiHandler.Handler, mws...)
}
g.match(vr.Methods(), prefix, vr.apiHandler.Handler, mws...)
}
}
// 虚拟路由配置文件数据结构
type virtRouterConfig struct {
Md5 string `json:"md5"`
VirtRouter *VirtRouter `json:"virtrouter"`
}
// 标记源码路由初始化完成
var canSaveVirtRouterConfig bool
// 读取虚拟路由配置
func readVirtRouterConfig() (md5 string, vr *VirtRouter, err error) {
f, err := os.OpenFile(ROUTERCONFIG_FILE, os.O_CREATE|os.O_RDONLY, 0777)
if err != nil {
return
}
defer f.Close()
b, err := ioutil.ReadAll(f)
if err != nil {
return
}
if !bytes.Contains(b, utils.String2Bytes("{")) {
return "", nil, nil
}
vrc := virtRouterConfig{}
err = json.Unmarshal(b, &vrc)
if err != nil {
return
}
return vrc.Md5, vrc.VirtRouter, err
}
// 保存虚拟路由配置到配置文件
func saveVirtRouterConfig() error {
if !canSaveVirtRouterConfig {
// 源码路由初始化未完成时不做保存操作
return nil
}
os.Remove(ROUTERCONFIG_FILE)
f, err := os.OpenFile(ROUTERCONFIG_FILE, os.O_CREATE|os.O_WRONLY, 0777)
if err != nil {
return err
}
defer f.Close()
b, err := json.MarshalIndent(virtRouterConfig{
Md5: Md5,
VirtRouter: lessgo.virtRouter,
}, "", " ")
if err != nil {
return err
}
f.Write(b)
return nil
}
type virtRouterSlice []*VirtRouter
func (vs virtRouterSlice) Len() int {
return len(vs)
}
func (vs virtRouterSlice) Less(i, j int) bool {
return vs[i].path <= vs[j].path
}
func (vs virtRouterSlice) Swap(i, j int) {
vs[i], vs[j] = vs[j], vs[i]
}
// 根据id获取虚拟路由节点
func GetVirtRouter(id string) (*VirtRouter, bool) {
virtRouterMapLock.RLock()
defer virtRouterMapLock.RUnlock()
vr, ok := virtRouterMap[id]
return vr, ok
}
// 根据path获取虚拟路由节点
func GetVirtRouterByPath(path string) (*VirtRouter, bool) {
virtRouterMapLock.RLock()
defer virtRouterMapLock.RUnlock()
for _, vr := range virtRouterMap {
if vr.path == path {
return vr, true
}
}
return nil, false
}
// 创建虚拟路由动态分组
func NewGroupVirtRouter(prefix, desc string) *VirtRouter {
prefix = cleanPrefix(prefix)
ah := NilApiHandler(desc)
return &VirtRouter{
Id: uuid.New().String(),
Type: GROUP,
Prefix: prefix,
Enable: true,
Dynamic: true,
apiHandler: ah,
Middlewares: []*MiddlewareConfig{},
Hid: ah.id,
}
}
// 创建虚拟路由动态操作
func NewHandlerVirtRouter(prefix, hid string, middlewares ...*MiddlewareConfig) (*VirtRouter, error) {
prefix = strings.Split(prefix, "/:")[0]
vr := &VirtRouter{
Id: uuid.New().String(),
Type: HANDLER,
Prefix: prefix,
Enable: true,
Dynamic: true,
Middlewares: middlewares,
Hid: hid,
}
err := vr.SetApiHandler(hid)
return vr, err
}
// 创建虚拟路由根节点
func newRootVirtRouter() *VirtRouter {
ah := NilApiHandler("root")
root := &VirtRouter{
Id: uuid.New().String(),
Type: ROOT,
Prefix: "/",
Dynamic: false,
Enable: true,
apiHandler: ah,
Middlewares: []*MiddlewareConfig{},
Hid: ah.id,
}
root.reset()
return root
}
// 从配置文件初始化虚拟路由
// 路由各级兄弟节点排序
func initVirtRouterConfig() {
defer func() {
lessgo.virtRouter.Sort()
}()
md5, vr, err := readVirtRouterConfig()
if err != nil {
Log.Error("Reading the config/virtrouter.config fails: %v.", err)
return
}
// 重新运行程序
if md5 == Md5 {
if vr != nil {
cleanVirtRouter()
vr.initFromConfig(true)
lessgo.virtRouter = vr
}
canSaveVirtRouterConfig = true
return
}
defer func() {
// 标记源码路由初始化完成
canSaveVirtRouterConfig = true
// 覆盖保存配置
err := saveVirtRouterConfig()
if err != nil {
Log.Error("Save the config/virtrouter.config failed: %v.", err)
}
}()
// 第一次运行程序
if md5 == "" {
return
}
// 程序被重新编译后第一次运行
if vr != nil {
vr.initFromConfig(false)
merge(lessgo.virtRouter, vr)
// os.Remove(ROUTERCONFIG_FILE)
}
return
}
// 虚拟路由树同级节点合并,将b合并入a,冲突时以a为准
func merge(a, b *VirtRouter) {
// 类型不同不合并
if a.Type != b.Type {
return
}
// 类型为操作时
if a.Type == HANDLER {
if a.Prefix != b.Prefix || a.apiHandler.Method != b.apiHandler.Method {
b.Dynamic = true //强制为动态的配置路由
a.Parent.addChild(b) //并入正式虚拟路由树中
}
return
}
// 类型为根路由或分组时
// 路由前缀不同时可合并
if a.Prefix != b.Prefix {
b.Dynamic = true //强制为动态的配置路由
a.Parent.addChild(b) //并入正式虚拟路由树中
return
}
var has *VirtRouter
for _, bc := range b.Children {
has = nil
for _, ac := range a.Children {
if ac.Prefix == b.Prefix {
has = ac
break
}
}
if has == nil {
// 当前源码路由中不存在的节点,直接增加
b.Dynamic = true //强制为动态的配置路由
a.Parent.addChild(b) //并入正式虚拟路由树中
} else {
merge(bc, has)
}
}
}
// 添加路由节点
func addVirtRouter(vr *VirtRouter) bool {
virtRouterMapLock.Lock()
defer virtRouterMapLock.Unlock()
if _, ok := virtRouterMap[vr.Id]; ok {
return false
}
virtRouterMap[vr.Id] = vr
return true
}
// 覆盖设置路由节点
func setVirtRouter(vr *VirtRouter) {
virtRouterMapLock.Lock()
defer virtRouterMapLock.Unlock()
virtRouterMap[vr.Id] = vr
}
// 删除路由节点
func delVirtRouter(vr *VirtRouter) {
virtRouterMapLock.Lock()
defer virtRouterMapLock.Unlock()
delete(virtRouterMap, vr.Id)
}
// 清空全部路由节点索引
func cleanVirtRouter() {
virtRouterMapLock.Lock()
defer virtRouterMapLock.Unlock()
virtRouterMap = map[string]*VirtRouter{}
}
// 格式化path前缀
func cleanPrefix(prefix string) string {
prefix = strings.Split(prefix, ":")[0]
return pathpkg.Join("/", prefix)
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化