package config import ( auth_middleware "cls-server/internal/infrastructure/middleware/auth" Ihttp "cls-server/pkg/http" "cls-server/pkg/logger" "cls-server/pkg/sms" "cls-server/pkg/util/security" "cls-server/pkg/xorm_engine" "cls-server/ui" "context" "fmt" "github.com/cenkalti/backoff/v4" _ "github.com/go-sql-driver/mysql" "github.com/redis/go-redis/v9" "net" "net/http" "strings" middleware "cls-server/pkg/web/middleware" "github.com/gin-gonic/gin" "go.uber.org/fx" "xorm.io/xorm" "xorm.io/xorm/names" ) func NewGinEngine(lc fx.Lifecycle, auth *auth_middleware.AuthMiddleware, appConfig *AppConfig) *gin.Engine { if strings.ToLower(appConfig.ServerConfig.Mode) == "prod" { gin.SetMode(gin.ReleaseMode) } handler := gin.New() handler.Use(gin.Recovery()) handler.Use(auth.Handle()) handler.Use(middleware.ServeRoot("/", "dist", &ui.RESOURCE)) handler.NoRoute(func(context *gin.Context) { if context.Request.RequestURI != "/" { context.Redirect(http.StatusTemporaryRedirect, "/") } }) srv := &http.Server{Addr: fmt.Sprintf(":%d", appConfig.ServerConfig.Port), Handler: handler} lc.Append(fx.Hook{ OnStart: func(ctx context.Context) error { ln, err := net.Listen("tcp", srv.Addr) if err != nil { return err } log.Infof("Web server starting on port %v", srv.Addr) log.Info("Press Ctrl+C to stop") go func() { if err0 := srv.Serve(ln); err0 != nil { log.Error(err0) } }() return nil }, OnStop: func(ctx context.Context) error { return srv.Shutdown(ctx) }, }) return handler } func NewXormEngine(appConfig *AppConfig, l logger.New) *xorm_engine.Engine { dbConfig := appConfig.MysqlConfig url := fmt.Sprintf("%s:%s@(%s)/%s", dbConfig.Username, dbConfig.Password, dbConfig.Address, dbConfig.Database) engine, err := xorm.NewEngineWithParams("mysql", url, dbConfig.Params) if err != nil { log.Fatal(err) } fmt.Println("done") engine.SetTableMapper(names.NewPrefixMapper(names.GonicMapper{}, "lc_")) engine.SetColumnMapper(names.GonicMapper{}) engine.SetLogger(logger.NewXormLogger(l("xorm"))) if dbConfig.ShowSql { engine.ShowSQL(true) } if err = backoff.Retry(engine.Ping, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil { log.Fatal(err) } urlCls := fmt.Sprintf("%s:%s@(%s)/%s", dbConfig.Username, dbConfig.Password, dbConfig.Address, dbConfig.DatabaseCls) engineCls, err := xorm.NewEngineWithParams("mysql", urlCls, dbConfig.Params) if err != nil { log.Fatal(err) } if err = backoff.Retry(engineCls.Ping, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil { log.Fatal(err) } return xorm_engine.NewEngine(engine, engineCls) } func NewRedisClient(appConfig *AppConfig) redis.Cmdable { dbConfig := appConfig.RedisConfig var rdbCli redis.Cmdable switch dbConfig.Mode { case "sentinel": rdbCli = redis.NewFailoverClient(&redis.FailoverOptions{ MasterName: dbConfig.MasterName, SentinelAddrs: dbConfig.SentinelAddrs, SentinelUsername: dbConfig.SentinelUsername, SentinelPassword: dbConfig.SentinelPassword, Username: dbConfig.Username, Password: dbConfig.Password, DB: 0, }) case "cluster": rdbCli = redis.NewClusterClient(&redis.ClusterOptions{ Addrs: dbConfig.Addrs, Username: dbConfig.Username, Password: dbConfig.Password, }) default: rdbCli = redis.NewClient(&redis.Options{ Addr: dbConfig.Addr, Username: dbConfig.Username, Password: dbConfig.Password, DB: dbConfig.DB, }) } if err := backoff.Retry(func() error { return rdbCli.Ping(context.Background()).Err() }, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 10)); err != nil { log.Fatal(err) } return rdbCli } func NewLoggerFactory(config *AppConfig) logger.New { return func(name string) logger.Logger { var options []logger.Option if v, ok := config.LogConfig.Loggers[strings.ToLower(name)]; ok { options = append(options, logger.Level(logger.LogLevel(v))) } return logger.NewLogger(name, options...) } } func NewPasswordEncoder() security.PasswordEncoder { return &security.BCryptPasswordEncoder{} } func NewSmsService(client *Ihttp.Client) sms.IsmsService { return sms.NewDebugSmsService(client) } func NewInternalClient() *Ihttp.Client { return Ihttp.NewClient() } func NewJWTAuthMiddleware(appConfig *AppConfig, redis redis.Cmdable) *auth_middleware.AuthMiddleware { return auth_middleware.NewAuthMiddleware(appConfig.JwtConfig.Secret, nil, redis) }