From 7552670e4a1dd943e32d5347d598813145da22ae Mon Sep 17 00:00:00 2001 From: oneao Date: Wed, 13 Aug 2025 14:51:19 +0800 Subject: [PATCH] u --- code/base-project/.idea/.gitignore | 10 + code/base-project/.idea/base-project.iml | 9 + code/base-project/.idea/misc.xml | 6 + code/base-project/.idea/modules.xml | 8 + code/base-project/.idea/vcs.xml | 6 + .../go-project/base-farmework/cmd/app/main.go | 10 +- .../base-farmework/configs/app/.gitkeep | 0 .../configs/app/application.yaml | 2 +- .../configs/app/{db.yaml => datasource.yaml} | 0 .../base-farmework/internal/.gitkeep | 0 .../base-farmework/internal/app/api/auth.go | 10 + .../internal/app/handle/auth.go | 67 ++++-- .../base-farmework/internal/app/router.go | 4 +- code/go-project/base-farmework/pkg/.gitkeep | 0 .../base-farmework/pkg/config/application.go | 23 ++- .../base-farmework/pkg/config/datasource.go | 191 ++++++++++++++++++ .../base-farmework/pkg/config/db.go | 80 -------- .../base-farmework/pkg/middleware/auth.go | 30 ++- .../base-farmework/pkg/middleware/logger.go | 4 +- .../base-farmework/pkg/router/.gitkeep | 0 .../base-farmework/pkg/router/context.go | 56 +++-- .../base-farmework/pkg/router/router.go | 6 +- .../base-farmework/pkg/utils/{ => jwt}/jwt.go | 12 +- 23 files changed, 380 insertions(+), 154 deletions(-) create mode 100644 code/base-project/.idea/.gitignore create mode 100644 code/base-project/.idea/base-project.iml create mode 100644 code/base-project/.idea/misc.xml create mode 100644 code/base-project/.idea/modules.xml create mode 100644 code/base-project/.idea/vcs.xml delete mode 100644 code/go-project/base-farmework/configs/app/.gitkeep rename code/go-project/base-farmework/configs/app/{db.yaml => datasource.yaml} (100%) delete mode 100644 code/go-project/base-farmework/internal/.gitkeep delete mode 100644 code/go-project/base-farmework/pkg/.gitkeep create mode 100644 code/go-project/base-farmework/pkg/config/datasource.go delete mode 100644 code/go-project/base-farmework/pkg/config/db.go delete mode 100644 code/go-project/base-farmework/pkg/router/.gitkeep rename code/go-project/base-farmework/pkg/utils/{ => jwt}/jwt.go (85%) diff --git a/code/base-project/.idea/.gitignore b/code/base-project/.idea/.gitignore new file mode 100644 index 00000000..7bc07ec2 --- /dev/null +++ b/code/base-project/.idea/.gitignore @@ -0,0 +1,10 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Environment-dependent path to Maven home directory +/mavenHomeManager.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/code/base-project/.idea/base-project.iml b/code/base-project/.idea/base-project.iml new file mode 100644 index 00000000..d6ebd480 --- /dev/null +++ b/code/base-project/.idea/base-project.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/code/base-project/.idea/misc.xml b/code/base-project/.idea/misc.xml new file mode 100644 index 00000000..639900d1 --- /dev/null +++ b/code/base-project/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/base-project/.idea/modules.xml b/code/base-project/.idea/modules.xml new file mode 100644 index 00000000..5f89c66d --- /dev/null +++ b/code/base-project/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/code/base-project/.idea/vcs.xml b/code/base-project/.idea/vcs.xml new file mode 100644 index 00000000..b2bdec2d --- /dev/null +++ b/code/base-project/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/code/go-project/base-farmework/cmd/app/main.go b/code/go-project/base-farmework/cmd/app/main.go index 2865f0b4..c512f273 100644 --- a/code/go-project/base-farmework/cmd/app/main.go +++ b/code/go-project/base-farmework/cmd/app/main.go @@ -2,21 +2,19 @@ package main import ( "base-framework/internal/app" - commonConfig "base-framework/pkg/config" + "base-framework/pkg/config" "log" "net/http" "strconv" - - _ "github.com/lib/pq" ) func main() { - _, err := commonConfig.InitApplicationConfig("./configs/app/application.yaml") + _, err := config.InitApplicationConfig("./configs/app/application.yaml") if err != nil { log.Fatalf("加载配置失败: %v", err) } - err = commonConfig.InitDBConfig("./configs/app/db.yaml") + err = config.InitDBConfig("./configs/app/datasource.yaml") if err != nil { log.Fatalf("加载数据库配置失败: %v", err) return @@ -24,7 +22,7 @@ func main() { r := app.InitAppRouter() - err = http.ListenAndServe(":"+strconv.Itoa(commonConfig.Server.Port), r) + err = http.ListenAndServe(":"+strconv.Itoa(config.Server.Port), r) if err != nil { log.Fatalf("server start failed: %v", err) } diff --git a/code/go-project/base-farmework/configs/app/.gitkeep b/code/go-project/base-farmework/configs/app/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/code/go-project/base-farmework/configs/app/application.yaml b/code/go-project/base-farmework/configs/app/application.yaml index 8b39165e..b19a3cc0 100644 --- a/code/go-project/base-farmework/configs/app/application.yaml +++ b/code/go-project/base-farmework/configs/app/application.yaml @@ -2,4 +2,4 @@ server: port: 8082 jwt: secret: 3Bde3BGEbYqtqyEUzW3ry8jKFcaPH17fRmTmqE7MDr05Lwj95uruRKrrkb44TJ4s - expiry: 43200 # 12 * 60 * 60 秒过期 + expiry: 24h diff --git a/code/go-project/base-farmework/configs/app/db.yaml b/code/go-project/base-farmework/configs/app/datasource.yaml similarity index 100% rename from code/go-project/base-farmework/configs/app/db.yaml rename to code/go-project/base-farmework/configs/app/datasource.yaml diff --git a/code/go-project/base-farmework/internal/.gitkeep b/code/go-project/base-farmework/internal/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/code/go-project/base-farmework/internal/app/api/auth.go b/code/go-project/base-farmework/internal/app/api/auth.go index 778f64ec..b18c7d1b 100644 --- a/code/go-project/base-farmework/internal/app/api/auth.go +++ b/code/go-project/base-farmework/internal/app/api/auth.go @@ -1 +1,11 @@ package api + +import ( + "base-framework/internal/app/handle" + "base-framework/pkg/router" +) + +func InitAuth(r *router.Router) { + group := r.Group("/auth") + group.POST("/login", handle.Login) +} diff --git a/code/go-project/base-farmework/internal/app/handle/auth.go b/code/go-project/base-farmework/internal/app/handle/auth.go index c4b1604f..18a99f13 100644 --- a/code/go-project/base-farmework/internal/app/handle/auth.go +++ b/code/go-project/base-farmework/internal/app/handle/auth.go @@ -1,31 +1,66 @@ package handle -import "base-framework/pkg/router" +import ( + "base-framework/pkg/config" + "base-framework/pkg/router" + "base-framework/pkg/utils/jwt" + "base-framework/pkg/utils/response" +) +// Login 登录接口 func Login(c *router.Context) { - // 直接用 BindJSON 绑定请求体 JSON 到结构体 + // 绑定请求体 var req struct { - OrgID string `json:"orgID"` - UserID string `json:"userID"` + OrgID string `json:"orgId"` + UserID string `json:"userId"` Password string `json:"password"` } + if err := c.BindJSON(&req); err != nil { - c.JSON(400, map[string]string{"error": "请求体格式错误"}) + response.Error(c).Message("请求体不能为空").Send() return } - // 模拟校验 - if req.UserID == "" || req.Password == "" { - c.JSON(400, map[string]string{"error": "账号或密码不能为空"}) + if req.OrgID == "" { + response.Error(c).Message("机构码不能为空").Send() return } - // 登录成功,返回 token 示例 - c.JSON(200, map[string]interface{}{ - "code": "0000", - "message": "登录成功", - "data": map[string]string{ - "token": "这里是token字符串", - }, - }) + // 参数校验 + if req.UserID == "" { + response.Error(c).Message("账户不能为空").Send() + return + } + + if req.Password == "" { + response.Error(c).Message("密码不能为空").Send() + return + } + + // 检查是否有该机构号 + hasOrg := false + for k := range config.GetDBConfigs() { + if k == req.OrgID { + hasOrg = true + break + } + } + + if !hasOrg { + response.Error(c).Code(response.CodeInvalidOrgCode).Send() + return + } + + // 生成Token + token, err := jwt.CreateToken(req.OrgID, req.UserID) + + if err != nil { + response.Error(c).Message("生成令牌失败") + return + } + + response.Success(c).Data( + map[string]string{ + "token": token, + }).Send() } diff --git a/code/go-project/base-farmework/internal/app/router.go b/code/go-project/base-farmework/internal/app/router.go index 99c416b8..97dd96ae 100644 --- a/code/go-project/base-farmework/internal/app/router.go +++ b/code/go-project/base-farmework/internal/app/router.go @@ -10,14 +10,14 @@ func InitAppRouter() *router.Router { r := router.NewRouter() r.Use(middleware.Recover()) - r.Use(middleware.Auth()).ExcludePaths("/login") + r.Use(middleware.Auth()).ExcludePaths("/auth/login") r.Use(middleware.Logger()) initApi(r) - return r } func initApi(r *router.Router) { api.InitTest(r) + api.InitAuth(r) } diff --git a/code/go-project/base-farmework/pkg/.gitkeep b/code/go-project/base-farmework/pkg/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/code/go-project/base-farmework/pkg/config/application.go b/code/go-project/base-farmework/pkg/config/application.go index d498464b..02c22c10 100644 --- a/code/go-project/base-farmework/pkg/config/application.go +++ b/code/go-project/base-farmework/pkg/config/application.go @@ -1,25 +1,28 @@ package config import ( - "time" - "github.com/spf13/viper" + "time" ) -type ServerConfig struct { +// server 服务器配置结构体(包内私有) +type server struct { Port int } -type JWTConfig struct { +// jwt 配置结构体(包内私有) +type jwt struct { Secret string Expiry time.Duration } +// 全局导出变量,指向私有结构体实例 var ( - Server ServerConfig - JWT JWTConfig + Server *server + JWT *jwt ) +// InitApplicationConfig 初始化配置,传入配置文件路径 func InitApplicationConfig(configPath string) (error, error) { v := viper.New() v.SetConfigFile(configPath) @@ -29,13 +32,17 @@ func InitApplicationConfig(configPath string) (error, error) { return err, nil } - if err := v.UnmarshalKey("server", &Server); err != nil { + var s server + if err := v.UnmarshalKey("server", &s); err != nil { return err, nil } + Server = &s - if err := v.UnmarshalKey("jwt", &JWT); err != nil { + var j jwt + if err := v.UnmarshalKey("jwt", &j); err != nil { return err, nil } + JWT = &j return nil, nil } diff --git a/code/go-project/base-farmework/pkg/config/datasource.go b/code/go-project/base-farmework/pkg/config/datasource.go new file mode 100644 index 00000000..ea71d109 --- /dev/null +++ b/code/go-project/base-farmework/pkg/config/datasource.go @@ -0,0 +1,191 @@ +package config + +import ( + "database/sql" + "fmt" + "log" + "sync" + "time" + + "github.com/fsnotify/fsnotify" + "github.com/spf13/viper" + + _ "github.com/lib/pq" // PostgreSQL 驱动,根据实际数据库替换 +) + +// DBConfig 数据库配置结构体 +type DBConfig struct { + Host string + Port int + Username string + Password string + Dbname string + MaxOpenConns int // 最大打开连接数 + MaxIdleConns int // 最大空闲连接数 + ConnMaxLifetime time.Duration // 连接最大生命周期 +} + +// 默认连接池参数 +const ( + defaultMaxOpenConns = 10 + defaultMaxIdleConns = 5 + defaultConnMaxLifetime = time.Hour +) + +var ( + dbConfigs map[string]DBConfig // 配置副本 + dataSources = make(map[string]*sql.DB) // 连接池 + configsDSN = make(map[string]string) // key -> dsn + mu sync.RWMutex + v *viper.Viper +) + +// InitDBConfig 初始化并加载 db.yaml 配置,同时启动监听 +func InitDBConfig(configPath string) error { + v = viper.New() + v.SetConfigFile(configPath) + v.SetConfigType("yaml") + + if err := v.ReadInConfig(); err != nil { + return fmt.Errorf("读取数据库配置失败: %w", err) + } + + if err := unmarshalConfigs(); err != nil { + return err + } + + // 首次加载后,初始化数据源 + if err := ReloadDataSources(GetDBConfigs()); err != nil { + log.Printf("首次加载数据源失败: %v\n", err) + return err + } + + // 监听配置文件变化 + v.WatchConfig() + v.OnConfigChange(func(e fsnotify.Event) { + log.Printf("数据库配置文件发生变化: %s\n", e.Name) + if err := unmarshalConfigs(); err != nil { + log.Printf("重新加载数据库配置失败: %v\n", err) + } else { + if err := ReloadDataSources(GetDBConfigs()); err != nil { + log.Printf("更新数据源失败: %v\n", err) + } else { + log.Println("数据库连接池已更新") + } + } + }) + + return nil +} + +// unmarshalConfigs 解析配置到全局变量,线程安全 +func unmarshalConfigs() error { + mu.Lock() + defer mu.Unlock() + + temp := make(map[string]DBConfig) + if err := v.Unmarshal(&temp); err != nil { + return fmt.Errorf("解析数据库配置失败: %w", err) + } + dbConfigs = temp + return nil +} + +// GetDBConfigs 并发安全地返回当前数据库配置副本 +func GetDBConfigs() map[string]DBConfig { + mu.RLock() + defer mu.RUnlock() + + res := make(map[string]DBConfig, len(dbConfigs)) + for k, v := range dbConfigs { + res[k] = v + } + return res +} + +// buildDSN 构建 PostgreSQL DSN +func buildDSN(cfg DBConfig) string { + return fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", + cfg.Host, cfg.Port, cfg.Username, cfg.Password, cfg.Dbname) +} + +// ReloadDataSources 支持增量更新数据源 +func ReloadDataSources(newConfigs map[string]DBConfig) error { + mu.Lock() + defer mu.Unlock() + + retain := make(map[string]bool) + + for key, cfg := range newConfigs { + newDSN := buildDSN(cfg) + oldDSN, exists := configsDSN[key] + + if !exists { + db, err := sql.Open("postgres", newDSN) + if err != nil { + log.Printf("[db] 新增数据源 %s 失败: %v", key, err) + continue + } + applyDBConfig(db, cfg) + dataSources[key] = db + configsDSN[key] = newDSN + log.Printf("[db] 新增数据源 %s 成功", key) + } else if oldDSN != newDSN { + if oldDB := dataSources[key]; oldDB != nil { + _ = oldDB.Close() + } + db, err := sql.Open("postgres", newDSN) + if err != nil { + log.Printf("[db] 更新数据源 %s 失败: %v", key, err) + continue + } + applyDBConfig(db, cfg) + dataSources[key] = db + configsDSN[key] = newDSN + log.Printf("[db] 更新数据源 %s 成功", key) + } + // 配置没变,不用操作 + retain[key] = true + } + + // 关闭并移除不再需要的数据源 + for key, db := range dataSources { + if !retain[key] { + _ = db.Close() + delete(dataSources, key) + delete(configsDSN, key) + log.Printf("[db] 移除数据源 %s", key) + } + } + + return nil +} + +// applyDBConfig 设置 sql.DB 连接池参数,并应用默认值 +func applyDBConfig(db *sql.DB, cfg DBConfig) { + maxOpen := cfg.MaxOpenConns + if maxOpen <= 0 { + maxOpen = defaultMaxOpenConns + } + db.SetMaxOpenConns(maxOpen) + + maxIdle := cfg.MaxIdleConns + if maxIdle <= 0 { + maxIdle = defaultMaxIdleConns + } + db.SetMaxIdleConns(maxIdle) + + timeout := cfg.ConnMaxLifetime + if timeout <= 0 { + timeout = defaultConnMaxLifetime + } + db.SetConnMaxLifetime(timeout) +} + +// GetDB 获取数据库连接 +func GetDB(key string) (*sql.DB, bool) { + mu.RLock() + defer mu.RUnlock() + db, ok := dataSources[key] + return db, ok +} diff --git a/code/go-project/base-farmework/pkg/config/db.go b/code/go-project/base-farmework/pkg/config/db.go deleted file mode 100644 index 8bc062ef..00000000 --- a/code/go-project/base-farmework/pkg/config/db.go +++ /dev/null @@ -1,80 +0,0 @@ -package config - -import ( - "fmt" - "log" - "sync" - - "github.com/fsnotify/fsnotify" - "github.com/spf13/viper" -) - -// DBConfig 数据库单个配置结构 -type DBConfig struct { - Host string - Port int - Username string - Password string - Dbname string -} - -// dbConfigs 全局变量,存放所有数据库配置,key为配置名,如 test1, test2 -var ( - dbConfigs map[string]DBConfig - mu sync.RWMutex - v *viper.Viper -) - -// InitDBConfig 初始化并加载 db.yaml 配置,同时启动监听 -func InitDBConfig(configPath string) error { - v = viper.New() - v.SetConfigFile(configPath) - v.SetConfigType("yaml") - - if err := v.ReadInConfig(); err != nil { - return fmt.Errorf("读取数据库配置失败: %w", err) - } - - if err := unmarshalConfigs(); err != nil { - return err - } - - // 监听配置文件变化 - v.WatchConfig() - v.OnConfigChange(func(e fsnotify.Event) { - log.Printf("数据库配置文件发生变化: %s\n", e.Name) - if err := unmarshalConfigs(); err != nil { - log.Printf("重新加载数据库配置失败: %v\n", err) - } else { - log.Println("数据库配置已更新") - } - }) - - return nil -} - -// unmarshalConfigs 解析配置到全局变量,内部加锁保证并发安全 -func unmarshalConfigs() error { - mu.Lock() - defer mu.Unlock() - - temp := make(map[string]DBConfig) - if err := v.Unmarshal(&temp); err != nil { - return fmt.Errorf("解析数据库配置失败: %w", err) - } - dbConfigs = temp - return nil -} - -// GetDBConfigs 并发安全地返回当前的所有数据库配置副本 -func GetDBConfigs() map[string]DBConfig { - mu.RLock() - defer mu.RUnlock() - - // 返回一份拷贝,避免外部修改内部数据 - res := make(map[string]DBConfig, len(dbConfigs)) - for k, v := range dbConfigs { - res[k] = v - } - return res -} diff --git a/code/go-project/base-farmework/pkg/middleware/auth.go b/code/go-project/base-farmework/pkg/middleware/auth.go index 12217f5d..b4951fbb 100644 --- a/code/go-project/base-farmework/pkg/middleware/auth.go +++ b/code/go-project/base-farmework/pkg/middleware/auth.go @@ -3,18 +3,20 @@ package middleware import ( "base-framework/pkg/config" "base-framework/pkg/router" - "base-framework/pkg/utils" + "base-framework/pkg/utils/jwt" "base-framework/pkg/utils/response" "errors" - "fmt" + "log" "strings" ) func Auth() router.HandlerFunc { return func(c *router.Context) { + log.Println("[Auth] 开始鉴权") + tokenHeader := c.Header("Authorization") - userIdHeader := c.Header("user_id") - orgIDHeader := c.Header("org_id") + userIdHeader := c.Header("userId") + orgIDHeader := c.Header("orgId") // 缺少登录信息 if tokenHeader == "" || userIdHeader == "" || orgIDHeader == "" { @@ -24,17 +26,17 @@ func Auth() router.HandlerFunc { // Bearer token 格式校验 parts := strings.Fields(tokenHeader) - if len(parts) != 2 || strings.ToLower(parts[0]) != "Bearer" { + if len(parts) != 2 || strings.ToLower(parts[0]) != "bearer" { response.Error(c).Code(response.CodeInvalidToken).Send() return } // 解析 token tokenStr := parts[1] - claims, err := utils.VerifyToken(tokenStr) + claims, err := jwt.VerifyToken(tokenStr) if err != nil { switch { - case errors.Is(err, utils.ErrTokenExpired): + case errors.Is(err, jwt.ErrTokenExpired): response.Error(c).Code(response.CodeLoginExpired).Send() default: response.Error(c).Code(response.CodeInvalidToken).Send() @@ -54,10 +56,18 @@ func Auth() router.HandlerFunc { return } - configs := config.GetDBConfigs() + // 检查是否有该机构号 + hasOrg := false + for k := range config.GetDBConfigs() { + if k == orgIDHeader { + hasOrg = true + break + } + } - for k := range configs { - fmt.Println(k) + if !hasOrg { + response.Error(c).Code(response.CodeInvalidOrgCode).Send() + return } c.Next() diff --git a/code/go-project/base-farmework/pkg/middleware/logger.go b/code/go-project/base-farmework/pkg/middleware/logger.go index cec9d7e2..4e16fa1a 100644 --- a/code/go-project/base-farmework/pkg/middleware/logger.go +++ b/code/go-project/base-farmework/pkg/middleware/logger.go @@ -12,8 +12,6 @@ func Logger() router.HandlerFunc { c.Next() elapsed := time.Since(start) // 即使业务中断,这里也能执行,打印耗时 - path := c.Request.URL.Path - method := c.Request.Method - println(method, path, "耗时:", elapsed.String()) + println("耗时:", elapsed.String()) } } diff --git a/code/go-project/base-farmework/pkg/router/.gitkeep b/code/go-project/base-farmework/pkg/router/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/code/go-project/base-farmework/pkg/router/context.go b/code/go-project/base-farmework/pkg/router/context.go index bb48752c..077ba3dd 100644 --- a/code/go-project/base-farmework/pkg/router/context.go +++ b/code/go-project/base-farmework/pkg/router/context.go @@ -37,47 +37,48 @@ func (b *BodyCache) Load(r *http.Request) ([]byte, error) { return b.Data, b.Err } -// Context 自定义请求上下文,组合 BodyCache +// Context 自定义请求上下文,封装了请求信息、响应写入器、路由参数、中间件处理等功能 type Context struct { - Writer http.ResponseWriter - Request *http.Request - Params map[string]string - Index int - Handlers []HandlerFunc + writer http.ResponseWriter // HTTP 响应写入器,用于构造响应数据 + request *http.Request // HTTP 请求对象,包含请求相关信息 + params map[string]string // 路由参数,如动态路径中的变量值 + index int // 当前执行的中间件/处理函数索引,用于控制 Next 调用流程 + handlers []HandlerFunc // 本次请求的中间件和最终处理函数链 - BodyCache BodyCache // 请求体缓存 + bodyCache BodyCache // 请求体缓存,确保请求体只读一次且可多次读取 + keys map[string]interface{} // 用于存储请求生命周期内的自定义数据(如用户信息、orgId等) } // Next 执行下一个中间件或处理函数 func (c *Context) Next() { - c.Index++ - if c.Index < len(c.Handlers) { - c.Handlers[c.Index](c) + c.index++ + if c.index < len(c.handlers) { + c.handlers[c.index](c) } } // Param 获取路由参数 func (c *Context) Param(key string) string { - return c.Params[key] + return c.params[key] } // Header 获取请求头 func (c *Context) Header(key string) string { - return c.Request.Header.Get(key) + return c.request.Header.Get(key) } // JSON 返回 JSON 格式响应 func (c *Context) JSON(statusCode int, data interface{}) { - c.Writer.Header().Set("Content-Type", "application/json; charset=utf-8") - c.Writer.WriteHeader(statusCode) - if err := json.NewEncoder(c.Writer).Encode(data); err != nil { - http.Error(c.Writer, err.Error(), http.StatusInternalServerError) + c.writer.Header().Set("Content-Type", "application/json; charset=utf-8") + c.writer.WriteHeader(statusCode) + if err := json.NewEncoder(c.writer).Encode(data); err != nil { + http.Error(c.writer, err.Error(), http.StatusInternalServerError) } } // Body 方便读取请求体,实际调用 BodyCache 的 Load 方法 func (c *Context) Body() ([]byte, error) { - return c.BodyCache.Load(c.Request) + return c.bodyCache.Load(c.request) } // BindJSON 反序列化 JSON 请求体到 obj @@ -91,8 +92,25 @@ func (c *Context) BindJSON(obj interface{}) error { // PostForm 获取表单参数 func (c *Context) PostForm(key string) string { - if err := c.Request.ParseForm(); err != nil { + if err := c.request.ParseForm(); err != nil { return "" } - return c.Request.FormValue(key) + return c.request.FormValue(key) +} + +// Set 存储键值对 +func (c *Context) Set(key string, value interface{}) { + if c.keys == nil { + c.keys = make(map[string]interface{}) + } + c.keys[key] = value +} + +// Get 取值 +func (c *Context) Get(key string) (interface{}, bool) { + if c.keys == nil { + return nil, false + } + val, ok := c.keys[key] + return val, ok } diff --git a/code/go-project/base-farmework/pkg/router/router.go b/code/go-project/base-farmework/pkg/router/router.go index d5d8c933..edcc12e5 100644 --- a/code/go-project/base-farmework/pkg/router/router.go +++ b/code/go-project/base-farmework/pkg/router/router.go @@ -209,9 +209,9 @@ func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) { handlers = append(handlers, n.handler) c := &Context{ - Writer: w, - Request: req, - Params: params, + writer: w, + request: req, + params: params, index: -1, handlers: handlers, } diff --git a/code/go-project/base-farmework/pkg/utils/jwt.go b/code/go-project/base-farmework/pkg/utils/jwt/jwt.go similarity index 85% rename from code/go-project/base-farmework/pkg/utils/jwt.go rename to code/go-project/base-farmework/pkg/utils/jwt/jwt.go index 6c24ae57..bf2ae353 100644 --- a/code/go-project/base-farmework/pkg/utils/jwt.go +++ b/code/go-project/base-farmework/pkg/utils/jwt/jwt.go @@ -1,4 +1,4 @@ -package utils +package jwt import ( commonConfig "base-framework/pkg/config" @@ -22,20 +22,19 @@ type CustomClaims struct { // CreateToken 创建一个 JWT token func CreateToken(orgID, userID string) (string, error) { - expireTime := time.Now().Add(commonConfig.JWT.Expiry).Unix() + expireAt := time.Now().Add(commonConfig.JWT.Expiry) claims := CustomClaims{ OrgID: orgID, UserID: userID, StandardClaims: jwt.StandardClaims{ - ExpiresAt: expireTime, + ExpiresAt: expireAt.Unix(), IssuedAt: time.Now().Unix(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - signKey := []byte(commonConfig.JWT.Secret) - return token.SignedString(signKey) + return token.SignedString([]byte(commonConfig.JWT.Secret)) } // VerifyToken 验证并解析 JWT token @@ -52,7 +51,8 @@ func VerifyToken(tokenString string) (*CustomClaims, error) { if err != nil { // 判断是否过期错误 - if ve, ok := err.(*jwt.ValidationError); ok { + var ve *jwt.ValidationError + if errors.As(err, &ve) { if ve.Errors&jwt.ValidationErrorExpired != 0 { return nil, ErrTokenExpired }