mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-02 06:56:36 +08:00
feat(core): implement cordis configuration extension and migrate all plugins
This commit is contained in:
@@ -4,19 +4,9 @@
|
||||
package driver_http
|
||||
|
||||
import (
|
||||
"Wavelet/pkg/config"
|
||||
"Wavelet/pkg/trace"
|
||||
"Wavelet/pkg/util"
|
||||
"context"
|
||||
"errors"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-contrib/sessions/redis"
|
||||
@@ -26,102 +16,82 @@ import (
|
||||
|
||||
// BuildEngine 构建并初始化 Gin 路由引擎及全部中间件和路由
|
||||
func BuildEngine() (*gin.Engine, error) {
|
||||
return BuildEngineWithConfig(httpAppConfig{}, httpRedisConfig{})
|
||||
}
|
||||
|
||||
// BuildEngineWithConfig constructs the Gin engine with explicitly injected configuration.
|
||||
func BuildEngineWithConfig(appCfg httpAppConfig, redisCfg httpRedisConfig) (*gin.Engine, error) {
|
||||
// 运行模式
|
||||
if config.Config.App.IsProduction() {
|
||||
if appCfg.Env == "production" || appCfg.Env == "prod" {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
setAPIPrefix(appCfg.APIPrefix)
|
||||
|
||||
// 初始化路由
|
||||
r := gin.New()
|
||||
r.Use(gin.Recovery())
|
||||
r.Use(corsMiddleware())
|
||||
|
||||
cfg := config.Config.Redis
|
||||
addrs := cfg.Addrs
|
||||
addrs := redisCfg.Addrs
|
||||
sessionAddr := "localhost:6379"
|
||||
if len(addrs) > 0 {
|
||||
sessionAddr = addrs[0]
|
||||
}
|
||||
|
||||
sessionSecret := appCfg.SessionSecret
|
||||
if sessionSecret == "" {
|
||||
sessionSecret = "wavelet-default-session-secret"
|
||||
}
|
||||
|
||||
sessionStore, err := redis.NewStoreWithDB(
|
||||
cfg.MinIdleConn,
|
||||
redisCfg.MinIdleConn,
|
||||
"tcp",
|
||||
sessionAddr,
|
||||
cfg.Username,
|
||||
cfg.Password,
|
||||
strconv.Itoa(cfg.DB),
|
||||
[]byte(config.Config.App.SessionSecret),
|
||||
redisCfg.Username,
|
||||
redisCfg.Password,
|
||||
strconv.Itoa(redisCfg.DB),
|
||||
[]byte(sessionSecret),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 设置 Session Redis Key 前缀
|
||||
if cfg.KeyPrefix != "" {
|
||||
if err := redis.SetKeyPrefix(sessionStore, cfg.KeyPrefix+"session:"); err != nil {
|
||||
if redisCfg.KeyPrefix != "" {
|
||||
if err := redis.SetKeyPrefix(sessionStore, redisCfg.KeyPrefix+"session:"); err != nil {
|
||||
log.Printf("[API] set session key prefix failed: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
sessionCookieName := appCfg.SessionCookieName
|
||||
if sessionCookieName == "" {
|
||||
sessionCookieName = "wavelet_session"
|
||||
}
|
||||
|
||||
sessionAge := appCfg.SessionAge
|
||||
if sessionAge <= 0 {
|
||||
sessionAge = 86400
|
||||
}
|
||||
|
||||
sessionStore.Options(sessions.Options{
|
||||
Path: "/",
|
||||
Domain: config.Config.App.SessionDomain,
|
||||
MaxAge: config.Config.App.SessionAge,
|
||||
HttpOnly: config.Config.App.SessionHTTPOnly,
|
||||
Secure: config.Config.App.SessionSecure,
|
||||
Domain: appCfg.SessionDomain,
|
||||
MaxAge: sessionAge,
|
||||
HttpOnly: appCfg.SessionHTTPOnly,
|
||||
Secure: appCfg.SessionSecure,
|
||||
SameSite: http.SameSiteLaxMode,
|
||||
})
|
||||
|
||||
r.Use(sessions.Sessions(config.Config.App.SessionCookieName, sessionStore))
|
||||
r.Use(sessions.Sessions(sessionCookieName, sessionStore))
|
||||
|
||||
appName := appCfg.AppName
|
||||
if appName == "" {
|
||||
appName = "Wavelet"
|
||||
}
|
||||
|
||||
// 补充中间件
|
||||
r.Use(otelgin.Middleware(config.Config.App.AppName), errorHandlerMiddleware(), loggerMiddleware())
|
||||
r.Use(otelgin.Middleware(appName), errorHandlerMiddleware(), loggerMiddleware())
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Serve 启动 HTTP API 服务。onStarted 仅会在 HTTP 地址成功绑定后调用。
|
||||
func Serve(onStarted func()) {
|
||||
r, err := BuildEngine()
|
||||
if err != nil {
|
||||
log.Fatalf("[API] init session store failed: %v\n", err)
|
||||
}
|
||||
|
||||
srv := &http.Server{
|
||||
Addr: config.Config.App.Addr,
|
||||
Handler: r,
|
||||
ReadHeaderTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
listener, err := (&net.ListenConfig{}).Listen(context.Background(), "tcp", config.Config.App.Addr)
|
||||
if err != nil {
|
||||
log.Fatalf("[API] server failed to listen on %s: %v\n", config.Config.App.Addr, err)
|
||||
}
|
||||
if onStarted != nil {
|
||||
onStarted()
|
||||
}
|
||||
|
||||
util.Go(func() {
|
||||
log.Printf("[API] server listening on %s\n", config.Config.App.Addr)
|
||||
if err := srv.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatalf("[API] server failed: %v\n", err)
|
||||
}
|
||||
})
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-quit
|
||||
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), time.Duration(config.Config.App.GracefulShutdownTimeout)*time.Second)
|
||||
|
||||
trace.Shutdown(shutdownCtx)
|
||||
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
log.Printf("[API] server forced to shutdown: %v\n", err)
|
||||
cancel()
|
||||
os.Exit(1)
|
||||
}
|
||||
cancel()
|
||||
|
||||
log.Println("[API] server exited")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user