feat: 接入swagger功能

This commit is contained in:
TsMask
2025-01-07 17:12:35 +08:00
parent bbc2fe5900
commit 92f6ae8787
11 changed files with 1103 additions and 403 deletions

View File

@@ -1,16 +1,19 @@
package main
import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"
"os"
"strconv"
"strings"
"sync"
_ "net/http/pprof"
"github.com/chenjiandongx/ginprom"
"github.com/gin-gonic/gin"
"github.com/prometheus/client_golang/prometheus/promhttp"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
"be.ems/features"
"be.ems/features/dbrest"
"be.ems/features/event"
@@ -18,191 +21,76 @@ import (
"be.ems/features/lm"
"be.ems/features/mml"
"be.ems/features/pm"
featuresCfg "be.ems/lib/config"
"be.ems/lib/dborm"
"be.ems/lib/global"
"be.ems/lib/log"
"be.ems/lib/routes"
"be.ems/restagent/config"
"be.ems/src"
"be.ems/src/framework/config"
"be.ems/src/framework/logger"
"be.ems/src/framework/middleware"
"github.com/gin-gonic/gin"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
"be.ems/src/framework/utils/parse"
_ "be.ems/swagger2docs"
)
// const defaultConfigFile = "./etc/restconf.yaml"
// func init() {
// cfile := flag.String("c", defaultConfigFile, "config file")
// pv := flag.Bool("v", false, "print version")
// ph := flag.Bool("h", false, "print help")
// flag.Parse()
// if *pv {
// fmt.Printf("OMC restagent version: %s\n%s\n%s\n\n", global.Version, global.BuildTime, global.GoVer)
// os.Exit(0)
// }
// if *ph {
// flag.Usage()
// os.Exit(0)
// }
// config.ReadConfig(*cfile)
// config.UriPrefix = config.GetYamlConfig().OMC.UriPrefix
// //fmt.Println(config.UriPrefix)
// }
// func listenIPv6(ipv6 string, port int) {
// //
// addr := &net.TCPAddr{
// IP: net.ParseIP(ipv6),
// Port: port,
// }
// listener, err := net.ListenTCP("tcp6", addr)
// if err != nil {
// fmt.Println("Failed to listen:", err)
// return
// }
// server := &http.Server{}
// err = server.Serve(listener)
// if err != nil {
// fmt.Println("Failed to serve:", err)
// }
// }
func HttpListen(addr string, router http.Handler) {
// 创建HTTP服务器
h2s := &http2.Server{
// ...
}
server := &http.Server{
Addr: addr,
Handler: h2c.NewHandler(router, h2s),
}
// // support http 2.0 server
// err := http2.ConfigureServer(server, &http2.Server{})
// if err != nil {
// fmt.Println("ConfigureServer err:", err)
// os.Exit(11)
// }
err := server.ListenAndServe()
if err != nil {
fmt.Println("ListenAndServe err:", err)
os.Exit(12)
}
}
func HttpListenTLS(addr, caFile, certFile, keyFile string, clientAuthType int, router http.Handler) {
// 加载根证书
caCert, err := os.ReadFile(caFile)
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 创建自定义的TLS配置
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS13,
ClientCAs: caCertPool,
ClientAuth: tls.ClientAuthType(clientAuthType),
}
// 创建HTTP服务器
server := &http.Server{
Addr: addr,
Handler: router,
TLSConfig: tlsConfig,
}
// support http 2.0 server
http2.ConfigureServer(server, &http2.Server{})
if err != nil {
fmt.Println("ConfigureServer err:", err)
os.Exit(13)
}
err = server.ListenAndServeTLS(certFile, keyFile)
if err != nil {
fmt.Println("ListenAndServeTLS err:", err)
os.Exit(14)
}
}
func HttpListenWebServerTLS(addr, caFile, certFile, keyFile string, clientAuthType int) {
// 加载根证书
caCert, err := os.ReadFile(caFile)
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// 创建自定义的TLS配置
tlsConfig := &tls.Config{
MinVersion: tls.VersionTLS10,
MaxVersion: tls.VersionTLS13,
ClientCAs: caCertPool,
ClientAuth: tls.ClientAuthType(clientAuthType),
}
// 创建HTTP服务器
server := &http.Server{
Addr: addr,
TLSConfig: tlsConfig,
}
// support http 2.0 server
http2.ConfigureServer(server, &http2.Server{})
if err != nil {
fmt.Println("ConfigureServer err:", err)
os.Exit(9)
}
err = server.ListenAndServeTLS(certFile, keyFile)
if err != nil {
fmt.Println("ListenAndServeTLS err:", err)
os.Exit(10)
}
}
func HttpListenWebServer(addr string) {
// 创建HTTP服务器
server := &http.Server{
Addr: addr,
}
// support http 2.0 server
err := http2.ConfigureServer(server, &http2.Server{})
if err != nil {
fmt.Println("ConfigureServer err:", err)
os.Exit(7)
}
err = server.ListenAndServe()
if err != nil {
fmt.Println("ListenAndServe err:", err)
os.Exit(8)
}
}
var wg sync.WaitGroup
// @title OMC Swagger API
// @version 1.0.5
// @description OMC Service Interface Info
//
// @tag.name chart
// @tag.description chart interface
// @tag.name common
// @tag.description common interface
// @tag.name monitor
// @tag.description monitor interface
// @tag.name network_data
// @tag.description network data interface
// @tag.name network_element
// @tag.description network element interface
// @tag.name system
// @tag.description system interface
// @tag.name tool
// @tag.description tool interface
// @tag.name trace
// @tag.description trace interface
// @tag.name ws
// @tag.description ws interface
//
// @host 127.0.0.1:33040
// @BasePath /
// @schemes http https
//
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name Authorization
// @description Get the key through the login interface, fill in e.g. Bearer <access_token>
func main() {
// src 配置中心初始加载
// 初始配置加载
src.ConfigurationInit()
// 程序注册
app := src.AppEngine()
// Swagger 接口文档
app.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
conf := config.GetYamlConfig()
loadFeatures(app)
if conf.Pprof.Enabled {
// 启用pprof HTTP服务
go func() {
fmt.Println(http.ListenAndServe(conf.Pprof.Addr, nil))
}()
}
loadPprof(app)
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", config.GetLogLevel())
loadServer(app)
loadWebServer()
wg.Wait()
}
// loadFeatures mux路由模块
func loadFeatures(app *gin.Engine) {
conf := featuresCfg.GetYamlConfig()
log.InitLogger(conf.Logger.File, conf.Logger.Duration, conf.Logger.Count, "omc:restagent", featuresCfg.GetLogLevel())
fmt.Printf("OMC restagent version: %s\n", global.Version)
log.Infof("========================= OMC restagent startup =========================")
log.Infof("OMC restagent version: %s %s %s", global.Version, global.BuildTime, global.GoVer)
@@ -249,71 +137,138 @@ func main() {
// 将 mux.Router 注册到 gin.Engine
// 默认路由组
defaultUriGroup := app.Group(config.DefaultUriPrefix)
defaultUriGroup := app.Group(featuresCfg.DefaultUriPrefix)
defaultUriGroup.Use(middleware.PreAuthorize(nil))
defaultUriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
// 可配置前缀路由组
uriGroup := app.Group(config.UriPrefix)
uriGroup := app.Group(featuresCfg.UriPrefix)
uriGroup.Any("/*any", gin.WrapH(routes.NewRouter()))
// AMF上报的UE事件, 无前缀,暂时特殊处理
app.POST(event.UriUEEventAMF, event.PostUEEventFromAMF)
// register feature service gin.Engine
features.InitServiceEngine(app)
// var listenLocalhost bool = false
for _, rest := range conf.Rest {
// ipv4 goroutines
if rest.IPv4 != "" {
listen := rest.IPv4 + ":" + strconv.Itoa(int(rest.Port))
if strings.ToLower(rest.Scheme) == "https" {
go HttpListenTLS(listen, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
} else {
go HttpListen(listen, app)
}
}
// if rest.IPv4 != "0.0.0.0" && !listenLocalhost {
// listenLocalhost = true
// // 默认启动localhost侦听
// listenLocal := "127.0.0.1" + ":" + strconv.Itoa(int(rest.Port))
// if strings.ToLower(rest.Scheme) == "https" {
// go HttpListenTLS(listenLocal, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
// } else {
// go HttpListen(listenLocal, app)
// }
// }
// ipv6 goroutines
if rest.IPv6 != "" {
listenv6 := "[" + rest.IPv6 + "]" + ":" + strconv.Itoa(int(rest.Port))
if strings.ToLower(rest.Scheme) == "https" {
go HttpListenTLS(listenv6, rest.CaFile, rest.CertFile, rest.KeyFile, rest.ClientAuthType, app)
} else {
go HttpListen(listenv6, app)
}
}
// if rest.IPv6 != "::" {
// // 默认启动localhost侦听
// listenv6Local := "[" + "::1" + "]" + ":" + strconv.Itoa(int(rest.Port))
// if strings.ToLower(rest.Scheme) == "https" {
// go HttpListenTLS(listenv6Local, rest.CaFile, rest.CertFile, rest.KeyFile, app)
// } else {
// go HttpListen(listenv6Local, app)
// }
// }
}
if conf.WebServer.Enabled {
fs := http.FileServer(http.Dir(conf.WebServer.RootDir))
http.Handle("/", fs)
for _, listen := range conf.WebServer.Listen {
if strings.ToLower(listen.Scheme) == "https" {
go HttpListenWebServerTLS(listen.Addr, listen.CaFile, listen.CertFile, listen.KeyFile, listen.ClientAuthType)
} else {
go HttpListenWebServer(listen.Addr)
}
}
}
select {}
}
// loadPprof 性能分析监控
func loadPprof(app *gin.Engine) {
pprofEnabled := config.Get("pprof.enabled")
if pprofEnabled != nil && pprofEnabled.(bool) {
app.Use(ginprom.PromMiddleware(nil))
app.GET("/metrics", ginprom.PromHandler(promhttp.Handler()))
pprofAddr := config.Get("pprof.addr").(string)
wg.Add(1)
// 启用pprof HTTP服务
go func(addr string) {
defer wg.Done()
fmt.Println(http.ListenAndServe(addr, nil))
}(pprofAddr)
}
}
// loadServer 多个HTTP服务启动
func loadServer(app *gin.Engine) {
httpArr := config.Get("rest")
if httpArr == nil {
logger.Errorf("rest config not found")
return
}
for _, v := range httpArr.([]any) {
rest := v.(map[string]any)
port := parse.Number(rest["port"])
ipv4 := fmt.Sprint(rest["ipv4"])
ipv6 := fmt.Sprint(rest["ipv6"])
schema := fmt.Sprint(rest["schema"])
if schema == "https" && schema != "<nil>" {
certFile := fmt.Sprint(rest["certfile"])
keyFile := fmt.Sprint(rest["keyfile"])
addr := ""
if ipv4 != "" && ipv4 != "<nil>" {
addr = fmt.Sprintf("%s:%d", ipv4, port)
}
if ipv6 != "" && ipv6 != "<nil>" {
addr = fmt.Sprintf("[%s]:%d", ipv6, port)
}
if addr == "" {
continue
}
// 启动HTTPS服务
wg.Add(1)
go func(addr string, certFile string, keyFile string) {
defer wg.Done()
err := app.RunTLS(addr, certFile, keyFile)
logger.Errorf("run tls err:%v", err)
}(addr, certFile, keyFile)
} else {
addr := ""
if ipv4 != "" && ipv4 != "<nil>" {
addr = fmt.Sprintf("%s:%d", ipv4, port)
}
if ipv6 != "" && ipv6 != "<nil>" {
addr = fmt.Sprintf("[%s]:%d", ipv6, port)
}
if addr == "" {
continue
}
// 启动HTTP服务
wg.Add(1)
go func(addr string) {
defer wg.Done()
err := app.Run(addr)
logger.Errorf("run err:%v", err)
}(addr)
}
}
}
// loadWebServer 前端静态资源服务
func loadWebServer() {
webEnabled := config.Get("webServer.enabled")
if webEnabled == nil {
logger.Errorf("webServer config not found")
return
}
if webEnabled.(bool) {
rootDir := config.Get("webServer.rootDir").(string)
if rootDir != "" {
var web *gin.Engine
gin.SetMode(gin.ReleaseMode)
web = gin.New()
web.Use(gin.Recovery())
gin.DisableConsoleColor()
web.StaticFS("/", http.Dir(rootDir))
// 多个HTTP服务启动
listenArr := config.Get("webServer.listen")
for _, v := range listenArr.([]any) {
listen := v.(map[string]any)
addr := fmt.Sprint(listen["addr"])
schema := fmt.Sprint(listen["schema"])
if schema == "https" && schema != "<nil>" {
certFile := fmt.Sprint(listen["certfile"])
keyFile := fmt.Sprint(listen["keyfile"])
if addr == "" || addr == "<nil>" {
continue
}
// 启动HTTPS服务
wg.Add(1)
go func(addr string, certFile string, keyFile string) {
defer wg.Done()
err := web.RunTLS(addr, certFile, keyFile)
logger.Errorf("web run tls err:%v", err)
}(addr, certFile, keyFile)
} else {
if addr == "" || addr == "<nil>" {
continue
}
// 启动HTTP服务
wg.Add(1)
go func(addr string) {
defer wg.Done()
err := web.Run(addr)
logger.Errorf("web run err:%v", err)
}(addr)
}
}
}
}
}