From 604b92573774dffed6e9d5b715c4cb8012904c79 Mon Sep 17 00:00:00 2001 From: Leon Date: Tue, 6 Feb 2024 22:33:41 +0800 Subject: [PATCH] Refactor code structure and configuration handling --- cmd/main.go | 34 +++++------------------ cmd/webserver/controller/auth.go | 29 ++++++++++---------- cmd/webserver/controller/share.go | 7 +++-- cmd/webserver/controller/user.go | 6 ++--- cmd/webserver/middleware/auth.go | 11 ++++---- cmd/webserver/middleware/logging.go | 11 ++++---- cmd/webserver/router.go | 8 +++--- internal/log/log.go | 7 ----- service/singleton/singleton.go | 42 +++++++++++++++++++++++++++++ 9 files changed, 83 insertions(+), 72 deletions(-) delete mode 100644 internal/log/log.go create mode 100644 service/singleton/singleton.go diff --git a/cmd/main.go b/cmd/main.go index 56add35..f9ea5bc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,14 +1,8 @@ package main import ( - "fmt" "go-gin/cmd/webserver" - "go-gin/internal/config" - "go-gin/internal/log" - "go-gin/model" - - config_utils "go-gin/pkg/config" - logger "go-gin/pkg/logger" + "go-gin/service/singleton" flag "github.com/spf13/pflag" ) @@ -27,27 +21,13 @@ func main() { flag.Parse() flag.Lookup("config").NoOptDefVal = "config" - initConfig(webServerCliParam.ConfigName) - initLog(config.Instance) - - webserver.ServerWeb(config.Instance) -} - -func initConfig(name string) { - _config, err := config_utils.ReadViperConfig(name, "yaml", []string{".", "./config", "../"}) - if err != nil { - panic(fmt.Errorf("unable to read config: %s", err)) - } + singleton.InitConfig(webServerCliParam.ConfigName) + singleton.InitLog(singleton.Config) + initService() - if err := _config.Unmarshal(&config.Instance); err != nil { - panic(fmt.Errorf("unable to unmarshal config: %s", err)) - } + webserver.ServerWeb(singleton.Config) } -func initLog(config *config.Config) { - logPath := config.Log.Path - if logPath == "" { - logPath = model.DefaultLogPath - } - log.ZLog = logger.NewLogger(config.Log.Level, logPath) +func initService() { + singleton.InitSingleton() } diff --git a/cmd/webserver/controller/auth.go b/cmd/webserver/controller/auth.go index 39dbc01..676c42e 100644 --- a/cmd/webserver/controller/auth.go +++ b/cmd/webserver/controller/auth.go @@ -7,9 +7,8 @@ import ( "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" - "go-gin/internal/config" - "go-gin/internal/log" "go-gin/model" + "go-gin/service/singleton" api_utils "go-gin/internal/api" ) @@ -20,21 +19,21 @@ func Login(c *gin.Context) { // get the body of the POST request err := c.BindJSON(&creds) if err != nil { - log.ZLog.Error().Msgf("Error binding JSON: %v", err) + singleton.Log.Error().Msgf("Error binding JSON: %v", err) api_utils.ResponseError(c, http.StatusBadRequest, "Invalid JSON") return } - users := config.Instance.Users + users := singleton.Config.Users expectedPassword, ok := users[creds.Username] if !ok || expectedPassword != creds.Password { - log.ZLog.Error().Msgf("Invalid credentials: %v", creds) + singleton.Log.Error().Msgf("Invalid credentials: %v", creds) api_utils.ResponseError(c, http.StatusUnauthorized, "Invalid credentials") return } - expirationTime := time.Now().Add(time.Duration(config.Instance.JWT.Expiration) * time.Minute) + expirationTime := time.Now().Add(time.Duration(singleton.Config.JWT.Expiration) * time.Minute) claims := &model.Claims{ Username: creds.Username, RegisteredClaims: jwt.RegisteredClaims{ @@ -44,9 +43,9 @@ func Login(c *gin.Context) { } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - tokenString, err := token.SignedString([]byte(config.Instance.JWT.Secret)) + tokenString, err := token.SignedString([]byte(singleton.Config.JWT.Secret)) if err != nil { - log.ZLog.Error().Msgf("Error signing token: %v", err) + singleton.Log.Error().Msgf("Error signing token: %v", err) api_utils.ResponseError(c, http.StatusInternalServerError, "Error signing token") return } @@ -59,7 +58,7 @@ func Refresh(c *gin.Context) { tokenString, err := api_utils.GetTokenString(c) if err != nil { - log.ZLog.Error().Msgf("Error getting token: %v", err) + singleton.Log.Error().Msgf("Error getting token: %v", err) c.JSON(http.StatusUnauthorized, &model.ErrorResponse{ Code: http.StatusUnauthorized, Message: "Unauthorized", @@ -69,15 +68,15 @@ func Refresh(c *gin.Context) { claims := &model.Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { - return []byte(config.Instance.JWT.Secret), nil + return []byte(singleton.Config.JWT.Secret), nil }) if err != nil { - log.ZLog.Error().Msgf("Error parsing token: %v", err) + singleton.Log.Error().Msgf("Error parsing token: %v", err) api_utils.ResponseError(c, http.StatusUnauthorized, "Unauthorized") return } if !token.Valid { - log.ZLog.Error().Msgf("Invalid token") + singleton.Log.Error().Msgf("Invalid token") c.JSON(http.StatusUnauthorized, &model.ErrorResponse{ Code: http.StatusUnauthorized, Message: "Invalid token", @@ -85,12 +84,12 @@ func Refresh(c *gin.Context) { return } - expirationTime := time.Now().Add(time.Duration(config.Instance.JWT.Expiration) * time.Minute) + expirationTime := time.Now().Add(time.Duration(singleton.Config.JWT.Expiration) * time.Minute) claims.ExpiresAt = jwt.NewNumericDate(expirationTime) token = jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - tokenString, err = token.SignedString([]byte(config.Instance.JWT.Secret)) + tokenString, err = token.SignedString([]byte(singleton.Config.JWT.Secret)) if err != nil { - log.ZLog.Error().Msgf("Error signing token: %v", err) + singleton.Log.Error().Msgf("Error signing token: %v", err) api_utils.ResponseError(c, http.StatusInternalServerError, "Error signing token") return } diff --git a/cmd/webserver/controller/share.go b/cmd/webserver/controller/share.go index 13dd9db..f8d5bee 100644 --- a/cmd/webserver/controller/share.go +++ b/cmd/webserver/controller/share.go @@ -5,16 +5,15 @@ import ( "net/http" "os" - "go-gin/internal/config" - "github.com/gin-gonic/gin" api_utils "go-gin/internal/api" + "go-gin/service/singleton" ) func GetCreation(c *gin.Context) { share_num := c.Param("share_num") - creation_file := fmt.Sprintf("%s/creation/%s.png", config.Instance.Upload.Dir, share_num) + creation_file := fmt.Sprintf("%s/creation/%s.png", singleton.Config.Upload.Dir, share_num) // Check if the file exists if _, err := os.Stat(creation_file); os.IsNotExist(err) { api_utils.ResponseError(c, http.StatusNotFound, "Creation not found") @@ -26,7 +25,7 @@ func GetCreation(c *gin.Context) { "creation/share", gin.H{ "share_num": share_num, - "config": config.Instance, + "config": singleton.Config, }, ) } diff --git a/cmd/webserver/controller/user.go b/cmd/webserver/controller/user.go index 8c74543..345d055 100644 --- a/cmd/webserver/controller/user.go +++ b/cmd/webserver/controller/user.go @@ -5,8 +5,8 @@ import ( "net/http" "strings" - "go-gin/internal/config" "go-gin/pkg/utils" + "go-gin/service/singleton" "github.com/gin-gonic/gin" @@ -24,10 +24,10 @@ func UploadCreation(c *gin.Context) { return } new_id := utils.GenHexStr(32) - c.SaveUploadedFile(file, fmt.Sprintf("%s/creation/%s.png", config.Instance.Upload.Dir, new_id)) + c.SaveUploadedFile(file, fmt.Sprintf("%s/creation/%s.png", singleton.Config.Upload.Dir, new_id)) api_utils.Response(c, gin.H{ "creation_id": new_id, - "share_url": fmt.Sprintf("%s/share/creation/%s", config.Instance.Server.BaseUrl, new_id), + "share_url": fmt.Sprintf("%s/share/creation/%s", singleton.Config.Server.BaseUrl, new_id), }) } diff --git a/cmd/webserver/middleware/auth.go b/cmd/webserver/middleware/auth.go index 2ce948b..d7beee2 100644 --- a/cmd/webserver/middleware/auth.go +++ b/cmd/webserver/middleware/auth.go @@ -3,9 +3,8 @@ package middleware import ( "net/http" - "go-gin/internal/config" - "go-gin/internal/log" "go-gin/model" + "go-gin/service/singleton" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" @@ -18,21 +17,21 @@ func AuthHanlder() gin.HandlerFunc { tokenString, err := api_utils.GetTokenString(c) if err != nil { - log.ZLog.Error().Msgf("Error getting token: %v", err) + singleton.Log.Error().Msgf("Error getting token: %v", err) api_utils.ResponseError(c, http.StatusUnauthorized, "Unauthorized") return } claims := &model.Claims{} token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { - return []byte(config.Instance.JWT.Secret), nil + return []byte(singleton.Config.JWT.Secret), nil }) if err != nil { - log.ZLog.Error().Msgf("Error parsing token: %v", err) + singleton.Log.Error().Msgf("Error parsing token: %v", err) api_utils.ResponseError(c, http.StatusUnauthorized, "Unauthorized") return } if !token.Valid { - log.ZLog.Error().Msgf("Invalid token") + singleton.Log.Error().Msgf("Invalid token") api_utils.ResponseError(c, http.StatusUnauthorized, "Invalid token") return } diff --git a/cmd/webserver/middleware/logging.go b/cmd/webserver/middleware/logging.go index 9d6cca1..5e9b439 100644 --- a/cmd/webserver/middleware/logging.go +++ b/cmd/webserver/middleware/logging.go @@ -1,10 +1,9 @@ package middleware import ( + "go-gin/service/singleton" "time" - "go-gin/internal/log" - "github.com/gin-gonic/gin" ) @@ -12,15 +11,15 @@ func LoggingHandler() gin.HandlerFunc { return func(c *gin.Context) { t := time.Now() - log.ZLog.Info().Msgf("Request Info:\nMethod: %s\nHost: %s\nURL: %s", + singleton.Log.Info().Msgf("Request Info:\nMethod: %s\nHost: %s\nURL: %s", c.Request.Method, c.Request.Host, c.Request.URL) - log.ZLog.Debug().Msgf("Request Header:\n%v", c.Request.Header) + singleton.Log.Debug().Msgf("Request Header:\n%v", c.Request.Header) c.Next() latency := time.Since(t) - log.ZLog.Info().Msgf("Response Time: %s\nStatus: %d", + singleton.Log.Info().Msgf("Response Time: %s\nStatus: %d", latency.String(), c.Writer.Status()) - log.ZLog.Debug().Msgf("Response Header:\n%v", c.Writer.Header()) + singleton.Log.Debug().Msgf("Response Header:\n%v", c.Writer.Header()) } } diff --git a/cmd/webserver/router.go b/cmd/webserver/router.go index 578f3d7..bf39219 100644 --- a/cmd/webserver/router.go +++ b/cmd/webserver/router.go @@ -8,9 +8,9 @@ import ( "go-gin/cmd/webserver/controller" "go-gin/cmd/webserver/middleware" "go-gin/internal/config" - "go-gin/internal/log" "go-gin/internal/tmpl" "go-gin/resource" + "go-gin/service/singleton" "github.com/gin-gonic/gin" ) @@ -33,7 +33,7 @@ func NewRoute(config *config.Config) *gin.Engine { func serveStatic(r *gin.Engine) { staticFs, err := fs.Sub(resource.StaticFS, "static") if err != nil { - log.ZLog.Fatal().Err(err).Msg("Error parsing static files") + singleton.Log.Fatal().Err(err).Msg("Error parsing static files") panic(err) } r.StaticFS("/static", http.FS(staticFs)) @@ -45,7 +45,7 @@ func loadTemplates(r *gin.Engine) { var err error new_tmpl, err = new_tmpl.ParseFS(resource.TemplateFS, "template/**/*.html", "template/*.html") if err != nil { - log.ZLog.Fatal().Err(err).Msg("Error parsing templates") + singleton.Log.Fatal().Err(err).Msg("Error parsing templates") panic(err) } r.SetHTMLTemplate(new_tmpl) @@ -55,7 +55,7 @@ func routers(r *gin.Engine) { // Logging middleware r.Use(middleware.LoggingHandler()) // Rate limit middleware - r.Use(middleware.RateLimiterHandler(config.Instance.RateLimit.Max)) + r.Use(middleware.RateLimiterHandler(singleton.Config.RateLimit.Max)) r.POST("/login", controller.Login) userGroup := r.Group("/v1/user") diff --git a/internal/log/log.go b/internal/log/log.go deleted file mode 100644 index 7e15b62..0000000 --- a/internal/log/log.go +++ /dev/null @@ -1,7 +0,0 @@ -package log - -import ( - "github.com/rs/zerolog" -) - -var ZLog *zerolog.Logger = &zerolog.Logger{} diff --git a/service/singleton/singleton.go b/service/singleton/singleton.go new file mode 100644 index 0000000..e2929b1 --- /dev/null +++ b/service/singleton/singleton.go @@ -0,0 +1,42 @@ +package singleton + +import ( + "fmt" + "go-gin/internal/config" + "go-gin/model" + + config_utils "go-gin/pkg/config" + logger "go-gin/pkg/logger" + + "github.com/rs/zerolog" + "gorm.io/gorm" +) + +var ( + Config *config.Config + Log *zerolog.Logger + DB *gorm.DB +) + +func InitSingleton() { + // TOO: init db +} + +func InitConfig(name string) { + _config, err := config_utils.ReadViperConfig(name, "yaml", []string{".", "./config", "../"}) + if err != nil { + panic(fmt.Errorf("unable to read config: %s", err)) + } + + if err := _config.Unmarshal(&Config); err != nil { + panic(fmt.Errorf("unable to unmarshal config: %s", err)) + } +} + +func InitLog(config *config.Config) { + logPath := config.Log.Path + if logPath == "" { + logPath = model.DefaultLogPath + } + Log = logger.NewLogger(config.Log.Level, logPath) +}