package main import ( "bufio" "fmt" "io" "os" "regexp" "scd_check_tools/global" "scd_check_tools/models/bo" "scd_check_tools/tools" "strings" "github.com/astaxie/beego/orm" ) //自动分析api接口及定义,并写入权限定义表 type ApiDoc struct { } //启动接口分析。建议在系统启动是同步开启 //仅对controller中定义的接口进行分析 //注意:原global_const_code表中的code字段长度设计为30,需要调整为200,以便写入足够长的接口地址。其中的parentcode和name都可以适当加长到100 func (c *ApiDoc) Run() { gofiles := map[string]string{ "基础服务": "./controllers/apiController.go", "数据导入导出服务": "./controllers/excelController.go", "文件服务": "./controllers/attachmentController.go", "检测任务服务": "./controllers/taskController.go", "通知提醒服务": "./controllers/noticeController.go", "规则配置服务": "./controllers/rueController.go", "SCD校验服务": "./controllers/scdCompController.go", "SCD可视化服务": "./controllers/screenController.go", "统计分析服务": "./controllers/statController.go", "版本及升级管理服务": "./upgrade/versionController.go", } db := orm.NewOrm() db.Raw("ALTER TABLE global_const_code MODIFY COLUMN `code` varchar(200)").Exec() db.Raw("ALTER TABLE global_const_code MODIFY COLUMN `parentcode` varchar(100)").Exec() db.Raw("ALTER TABLE global_const_code MODIFY COLUMN `name` varchar(100)").Exec() code := "pl_service" db.Raw("insert IGNORE into global_const_code(code,parentcode,name)values(?,?,?)", code, "sysmenu", "接口服务").Exec() for apiDesc, t1 := range gofiles { v_servicecodes := strings.Split(strings.ReplaceAll(t1, ".go", ""), "/") servicecode := v_servicecodes[len(v_servicecodes)-1] doclist, _ := c.readMethodDocLine(t1) if len(doclist) > 0 { fmt.Println(fmt.Sprintf("%s:%+v", apiDesc, doclist)) db.Raw("insert IGNORE into global_const_code(code,parentcode,name)values(?,?,?)", servicecode, "pl_service", apiDesc).Exec() for _, d := range doclist { fmt.Println(fmt.Sprintf("%+v", d)) db.Raw("insert IGNORE into global_const_code(code,parentcode,name)values(?,?,?)", d[1], servicecode, d[0]).Exec() } } } } //缓存接口定义。在正式环境中启用 func (c *ApiDoc) CacheApiDoc() { gc := new(bo.Global) lst, _ := gc.GetChildrenGlobalCode("pl_service") if len(lst) == 0 { return } for _, r := range lst { code := tools.IsEmpty(r["code"]) global.ApiDocCache.Store(fmt.Sprintf("apidoc_%s", code), true) childlst, _ := gc.GetChildrenGlobalCode(code) if len(childlst) > 0 { for _, rc := range childlst { code = tools.IsEmpty(rc["code"]) global.ApiDocCache.Store(fmt.Sprintf("apidoc_%s", code), true) } } } } //判断指定的api定义是否存在 func (c *ApiDoc) Exist(api string) bool { _, h := global.ApiDocCache.Load(fmt.Sprintf("apidoc_%s", api)) return h } func (c *ApiDoc) readMethodDocLine(fileName string) ([][]string, error) { f, err := os.Open(fileName) if err != nil { return nil, err } buf := bufio.NewReader(f) var result [][]string var comments_summary = false var notAuth = true comments_summary_text := "" reg := regexp.MustCompile("\\s+") //去除空白字符,包括空格、tab等 regPostGet := regexp.MustCompile("\\[.*?\\]") for { line, err := buf.ReadString('\n') if err != nil { if err == io.EOF { //读取结束,会报EOF return result, nil } return nil, err } line = reg.ReplaceAllString(line, "") if strings.HasPrefix(line, "//@NotAuth") { notAuth = false } if strings.HasPrefix(line, "//@Summary") || strings.HasPrefix(line, "//@Title") { if comments_summary { continue } comments_summary = true comments_summary_text = line[10:] } if strings.HasPrefix(line, "//@router") { if comments_summary && notAuth { result = append(result, []string{comments_summary_text, "/api" + regPostGet.ReplaceAllString(line[9:], "")}) } comments_summary_text = "" comments_summary = false notAuth = true } } return result, nil }