From 5d1eac52448c49e6397b2fc632df43dd27f5cb82 Mon Sep 17 00:00:00 2001 From: Skyenought <1808644906@qq.com> Date: Wed, 23 Aug 2023 01:57:31 +0800 Subject: [PATCH] fix(fiberi18n): use sync.Map and utils.CopyString to fix concurrent problem --- casbin/go.mod | 2 +- casbin/go.sum | 4 +-- fiberi18n/config.go | 11 ++++---- fiberi18n/i18n.go | 69 ++++++++++++++++++++++----------------------- paseto/go.mod | 2 +- paseto/go.sum | 4 +-- 6 files changed, 46 insertions(+), 46 deletions(-) diff --git a/casbin/go.mod b/casbin/go.mod index c9d771ca..b3d6c801 100644 --- a/casbin/go.mod +++ b/casbin/go.mod @@ -3,7 +3,7 @@ module github.com/gofiber/contrib/casbin go 1.18 require ( - github.com/casbin/casbin/v2 v2.75.0 + github.com/casbin/casbin/v2 v2.75.1 github.com/gofiber/fiber/v2 v2.48.0 ) diff --git a/casbin/go.sum b/casbin/go.sum index 52a778a7..acb84044 100644 --- a/casbin/go.sum +++ b/casbin/go.sum @@ -2,8 +2,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/casbin/casbin/v2 v2.75.0 h1:vSgtloFgyijYrFAoMKH1u9vdT7R55WDU74hJDDWT+5w= -github.com/casbin/casbin/v2 v2.75.0/go.mod h1:mzGx0hYW9/ksOSpw3wNjk3NRAroq5VMFYUQ6G43iGPk= +github.com/casbin/casbin/v2 v2.75.1 h1:TZpaeiIgS5jl6zhtwBCcYwpsSGdV63JbKiXsRE8b0k4= +github.com/casbin/casbin/v2 v2.75.1/go.mod h1:mzGx0hYW9/ksOSpw3wNjk3NRAroq5VMFYUQ6G43iGPk= github.com/gofiber/fiber/v2 v2.48.0 h1:cRVMCb9aUJDsyHxGFLwz/sGzDggdailZZyptU9F9cU0= github.com/gofiber/fiber/v2 v2.48.0/go.mod h1:xqJgfqrc23FJuqGOW6DVgi3HyZEm2Mn9pRqUb2kHSX8= github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= diff --git a/fiberi18n/config.go b/fiberi18n/config.go index 1906a90d..247270c7 100644 --- a/fiberi18n/config.go +++ b/fiberi18n/config.go @@ -2,8 +2,10 @@ package fiberi18n import ( "os" + "sync" "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/utils" "github.com/nicksnyder/go-i18n/v2/i18n" "golang.org/x/text/language" "gopkg.in/yaml.v2" @@ -52,7 +54,7 @@ type Config struct { ctx *fiber.Ctx bundle *i18n.Bundle - localizerMap map[string]*i18n.Localizer + localizerMap *sync.Map } type Loader interface { @@ -77,18 +79,16 @@ var ConfigDefault = &Config{ func defaultLangHandler(c *fiber.Ctx, defaultLang string) string { var lang string - lang = c.Query("lang") + lang = utils.CopyString(c.Query("lang")) if lang != "" { return lang } - - lang = c.Get("Accept-Language") + lang = utils.CopyString(c.Get("Accept-Language")) if lang != "" { return lang } return defaultLang - } func configDefault(config ...*Config) *Config { @@ -135,5 +135,6 @@ func configDefault(config ...*Config) *Config { if cfg.LangHandler == nil { cfg.LangHandler = ConfigDefault.LangHandler } + return cfg } diff --git a/fiberi18n/i18n.go b/fiberi18n/i18n.go index ca5b4164..9be5d530 100644 --- a/fiberi18n/i18n.go +++ b/fiberi18n/i18n.go @@ -3,6 +3,7 @@ package fiberi18n import ( "fmt" "path" + "sync" "github.com/gofiber/fiber/v2" "github.com/nicksnyder/go-i18n/v2/i18n" @@ -13,59 +14,56 @@ var appCfg *Config // New creates a new middleware handler func New(config ...*Config) fiber.Handler { appCfg = configDefault(config...) - appCfg.bundle = initBundle() - loadMessages() - appCfg.localizerMap = initLocalizerMap() + // init bundle + bundle := i18n.NewBundle(appCfg.DefaultLanguage) + bundle.RegisterUnmarshalFunc(appCfg.FormatBundleFile, appCfg.UnmarshalFunc) + appCfg.bundle = bundle + + appCfg.loadMessages().initLocalizerMap() return func(c *fiber.Ctx) error { if appCfg.Next != nil && appCfg.Next(c) { return c.Next() } + appCfg.ctx = c + return c.Next() } } -func initBundle() *i18n.Bundle { - bundle := i18n.NewBundle(appCfg.DefaultLanguage) - bundle.RegisterUnmarshalFunc(appCfg.FormatBundleFile, appCfg.UnmarshalFunc) - - return bundle -} - -func loadMessage(filepath string) { - buf, err := appCfg.Loader.LoadMessage(filepath) +func (c *Config) loadMessage(filepath string) { + buf, err := c.Loader.LoadMessage(filepath) if err != nil { panic(err) } - if _, err := appCfg.bundle.ParseMessageFileBytes(buf, filepath); err != nil { + if _, err := c.bundle.ParseMessageFileBytes(buf, filepath); err != nil { panic(err) } } -func loadMessages() { - for _, lang := range appCfg.AcceptLanguages { - bundleFile := fmt.Sprintf("%s.%s", lang.String(), appCfg.FormatBundleFile) - filepath := path.Join(appCfg.RootPath, bundleFile) - - loadMessage(filepath) +func (c *Config) loadMessages() *Config { + for _, lang := range c.AcceptLanguages { + bundleFilePath := fmt.Sprintf("%s.%s", lang.String(), c.FormatBundleFile) + filepath := path.Join(c.RootPath, bundleFilePath) + c.loadMessage(filepath) } + return c } -func initLocalizerMap() map[string]*i18n.Localizer { - localizerMap := map[string]*i18n.Localizer{} +func (c *Config) initLocalizerMap() { + localizerMap := &sync.Map{} - for _, lang := range appCfg.AcceptLanguages { + for _, lang := range c.AcceptLanguages { s := lang.String() - localizerMap[s] = i18n.NewLocalizer(appCfg.bundle, s) + localizerMap.Store(s, i18n.NewLocalizer(c.bundle, s)) } - lang := appCfg.DefaultLanguage.String() - if _, ok := localizerMap[lang]; !ok { - localizerMap[lang] = i18n.NewLocalizer(appCfg.bundle, lang) + lang := c.DefaultLanguage.String() + if _, ok := localizerMap.Load(lang); !ok { + localizerMap.Store(lang, i18n.NewLocalizer(c.bundle, lang)) } - - return localizerMap + c.localizerMap = localizerMap } /* @@ -100,14 +98,15 @@ GetMessage get the i18n message }) */ func GetMessage(params interface{}) (string, error) { - var localizeConfig *i18n.LocalizeConfig - lang := appCfg.LangHandler(appCfg.ctx, appCfg.DefaultLanguage.String()) - localizer, hasValue := appCfg.localizerMap[lang] - if !hasValue { - localizer = appCfg.localizerMap[appCfg.DefaultLanguage.String()] + + localizer, _ := appCfg.localizerMap.Load(lang) + if localizer == nil { + defaultLang := appCfg.DefaultLanguage.String() + localizer, _ = appCfg.localizerMap.Load(defaultLang) } + var localizeConfig *i18n.LocalizeConfig switch paramValue := params.(type) { case string: localizeConfig = &i18n.LocalizeConfig{MessageID: paramValue} @@ -115,9 +114,9 @@ func GetMessage(params interface{}) (string, error) { localizeConfig = paramValue } - message, err := localizer.Localize(localizeConfig) + message, err := localizer.(*i18n.Localizer).Localize(localizeConfig) if err != nil { - return "", fmt.Errorf("i18n.Localize error: %v", err.Error()) + return "", fmt.Errorf("i18n.Localize error: %v", err) } return message, nil } diff --git a/paseto/go.mod b/paseto/go.mod index c66aa695..9b8aeab2 100644 --- a/paseto/go.mod +++ b/paseto/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/gofiber/fiber/v2 v2.48.0 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/o1egl/paseto v1.0.0 golang.org/x/crypto v0.12.0 ) diff --git a/paseto/go.sum b/paseto/go.sum index f45f7431..7bf4f363 100644 --- a/paseto/go.sum +++ b/paseto/go.sum @@ -10,8 +10,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gofiber/fiber/v2 v2.48.0 h1:cRVMCb9aUJDsyHxGFLwz/sGzDggdailZZyptU9F9cU0= github.com/gofiber/fiber/v2 v2.48.0/go.mod h1:xqJgfqrc23FJuqGOW6DVgi3HyZEm2Mn9pRqUb2kHSX8= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY= github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=