Ai
2 Star 10 Fork 5

百家饭/OpenApi Log Cat

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
config.go 6.68 KB
一键复制 编辑 原始数据 按行查看 历史
刘铭 提交于 2023-03-13 09:41 +08:00 . 增加测试例
package config
import (
"compress/gzip"
"io"
"net/url"
"os"
"path/filepath"
"strconv"
"strings"
"gitee.com/bjf-fhe/apicat/errors"
"gitee.com/bjf-fhe/apicat/openapi"
"gitee.com/bjf-fhe/apicat/utils"
"github.com/getkin/kin-openapi/openapi3"
"github.com/sirupsen/logrus"
)
const notifyForNoAPI = `----------------------------
您提供的OpenAPI定义文件加载错误,本次将使用常见API定义
作为定义文件,请编辑OpenAPI定义文件,以便得到更准确的
接口分析功能,包括未定义API访问判断等错误判断都需要使
用OpenAPI定义才可获得。
如何编辑OpenAPI文件请参考:
https://gitee.com/bjf-fhe/apicat/blob/master/edit-openapi.md
----------------------------
`
type Config struct {
Definition string
UserName string
Password string
Config string
// Format string
//除了指定Server外,允许单独指定Url前缀
BaseUrl string
Server string
ServerVariables []string
SourceMode string
StaticFileTypes []string
Debug int
TimeFormat string
File string
//用于加载常见URL
WellknownAPIs string
wellknown *openapi3.T
//缓存文件的路径
DbName string
//IP Hash长度
IPHashLength int
reader io.Reader
}
func (c *Config) GetTimeFormat() string {
return c.TimeFormat
}
func (c *Config) GetFileName() string {
return c.File
}
func (c *Config) IsLocalFile() bool {
if c.reader != nil {
//reader模式,统一认为是本地文件
return true
}
_, err := os.Stat(c.File)
if err == nil {
return true
}
if !os.IsNotExist(err) {
logrus.Error("check file exists error:", err)
}
return false
}
func (c *Config) Check(loadWellknown bool) (err error) {
var logLvl = logrus.Level(c.Debug)
logrus.Info("日志级别开始设置为", logLvl)
logrus.SetLevel(logLvl)
var wellknown = "./wellknown.yaml"
if c.WellknownAPIs != "" {
wellknown = c.WellknownAPIs
} else if !loadWellknown {
return nil
} else {
_, err := os.Stat(wellknown)
if err != nil && os.IsNotExist(err) {
logrus.Errorln("当前目录没有wellknown.yaml文件,将尝试从用户目录读取")
var home string
home, err = os.UserHomeDir()
if err == nil {
wellknown = filepath.Join(home, ".apicat", "wellknown.yaml")
}
}
}
{
var err error //允许wellknown加载错误,所以该错误独立处理
var loader = openapi3.NewLoader()
c.wellknown, err = loader.LoadFromFile(wellknown)
if err == nil {
logrus.Errorln("加载Wellknown文件:" + wellknown + "成功")
} else {
logrus.Errorln("指定的Wellknown文件路径"+wellknown+"加载错误", err)
logrus.Error(`wellknown文件用于定义常见的访问路径,以加强URL判断准确性,可以访问以下路径获取:https://gitee.com/bjf-fhe/apicat/raw/master/example/wellknown.yaml`)
}
}
return errors.Wrap(err, errors.ConfigCheckError)
}
func (c *Config) IsStaticPath(path string) bool {
for _, v := range c.StaticFileTypes {
if strings.HasSuffix(path, v) {
return true
}
}
return false
}
func (c *Config) IsWellknownView(path, method string) bool {
if c.wellknown != nil {
pathDef, ok := c.wellknown.Paths[path]
if ok {
op := openapi.GetOperation(pathDef, method)
return op != nil
}
}
return false
}
//LoadWellknownAsApi 将wellknown作为定义文件进行加载,主要为了初始使用或者体验使用,本函数调用时,wellknown应该已经加载完毕
func (c *Config) LoadWellknownAsApi() (api *openapi3.T, baseUrl string, err error) {
if c.wellknown == nil {
return nil, "", errors.New(errors.DefinitionWellknownEmpty)
}
baseUrl, err = c.getBaseUrlFromDef(c.wellknown)
return c.wellknown, baseUrl, err
}
func (c *Config) getBaseUrlFromDef(api *openapi3.T) (baseUrl string, err error) {
var iS int
//优先使用BaseUrl,其次使用Server
if c.BaseUrl != "" {
baseUrl = c.BaseUrl
} else if c.Server != "" {
iS, err = strconv.Atoi(c.Server)
}
if err == nil {
//根据server获得baseUrl配置
if len(api.Servers) == 0 {
logrus.Errorln("OpenAPI定义文档并未提供服务器信息,使用默认前缀'/'")
} else if len(api.Servers) > iS+1 {
logrus.Errorf("提供的服务器信息编号%d不存在,提供的服务器信息包括:", iS)
for k, v := range api.Servers {
logrus.Errorf("[%d](%s)%s", k, v.Description, v.URL)
}
} else {
var inputedVariables = make(map[string]string)
for _, arg := range c.ServerVariables {
parts := strings.SplitN(arg, ":", 2)
if len(parts) == 2 {
inputedVariables[parts[0]] = parts[1]
}
}
var server = api.Servers[iS]
for k := range server.Variables {
if inputed, ok := inputedVariables[k]; ok {
server.Variables[k].Default = inputed
}
}
baseUrl, err = server.BasePath()
if err != nil {
err = errors.Wrap(err, errors.DefinitionServerError)
}
}
} else {
err = errors.Wrap(err, errors.ConfigCheckServerConfigWrong)
}
return
}
func (c *Config) GetBaseUrlFromDef(api *openapi3.T) (baseUrl string, err error) {
baseUrl, err = c.getBaseUrlFromDef(api)
if err != nil {
return
}
var u *url.URL
u, err = url.Parse(baseUrl)
if err != nil {
err = errors.Wrap(err, errors.DefinitionServerParseError)
return
}
baseUrl = u.Path //因为nginx日志没有域名信息,只需要path部分
if baseUrl != "/" {
logrus.Infoln("判定的根路径为:", baseUrl)
} else {
baseUrl = ""
}
logrus.Info("开始进行日志读取分析")
return
}
// LoadApi 加载API定义文件, 如果loadWellknown为true,则在加载失败时,将尝试从wellknown中加载
func (c *Config) LoadApi(loadWellknown bool) (api *openapi3.T, baseUrl string, err error) {
err = c.Check(loadWellknown)
if err == nil {
api, err = openapi.Load(c.Definition, c.UserName, c.Password)
if err == nil {
baseUrl, err = c.GetBaseUrlFromDef(api)
} else {
//使用wellknown作为定义
logrus.Errorln("API加载错误", err)
os.Stderr.Write([]byte(notifyForNoAPI))
api, baseUrl, err = c.LoadWellknownAsApi()
}
}
return
}
func (c *Config) OpenFile() (io.Reader, error) {
var readCloser io.ReadCloser
var err error
if c.reader != nil {
if rc, ok := c.reader.(io.ReadCloser); ok {
readCloser = rc
}
} else {
readCloser, err = os.Open(c.File)
if err != nil {
return nil, err
}
}
if strings.HasSuffix(c.File, ".gz") {
var zc = utils.ZipReadCloser{}
if readCloser != nil {
zc.Zip, err = gzip.NewReader(readCloser)
zc.Low = readCloser
} else {
//readCloser为nil只可能c.reader不为空且c.reader不是readcloser
zc.Zip, err = gzip.NewReader(c.reader)
}
return &zc, err
} else if readCloser != nil {
return readCloser, nil
}
return c.reader, nil
}
func (c *Config) HasFeatureDB() bool {
return true
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/bjf-fhe/apicat.git
git@gitee.com:bjf-fhe/apicat.git
bjf-fhe
apicat
OpenApi Log Cat
v0.9.0

搜索帮助