82 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| ## Context
 | ||
| 
 | ||
| 当前 API 服务基于 Gin 构建。本次任务的目标是将其完整迁移到 Echo 框架,同时保持功能和接口的完全向后兼容。这包括路由、请求处理、中间件、Swagger 文档和 pprof 分析工具。
 | ||
| 
 | ||
| ## Goals / Non-Goals
 | ||
| 
 | ||
| - **Goals**:
 | ||
|     - 成功将 Web 框架从 Gin 迁移到 Echo v4。
 | ||
|     - 保持所有现有 API 端点的路径、方法和行为不变。
 | ||
|     - 确保所有自定义中间件(认证、审计日志)功能正常。
 | ||
|     - 确保 Swagger UI 可以在 `/swagger/index.html` 正常访问。
 | ||
|     - 确保 pprof 调试端点在 `/debug/pprof/*` 路径下正常工作。
 | ||
| - **Non-Goals**:
 | ||
|     - 增加任何新的 API 端点或功能。
 | ||
|     - 修改任何现有的 API 请求/响应模型。
 | ||
|     - 在本次变更中引入新的业务逻辑。
 | ||
| 
 | ||
| ## Decisions
 | ||
| 
 | ||
| 以下是从 Gin 到 Echo 的关键组件映射决策:
 | ||
|  
 | ||
| 1.  **框架实例**:
 | ||
|     - **From**: `gin.SetMode(cfg.Mode)`, `engine := gin.New()`, `engine.Use(gin.Recovery())`
 | ||
|     - **To**: `e := echo.New()`, `e.Debug = (cfg.Mode == "debug")`, `e.Use(middleware.Recover())`
 | ||
|     - **Rationale**: `echo.New()` 提供了干净的实例。Echo 的 `Debug` 属性控制调试模式,可以根据配置设置。Echo 提供了内置的 `middleware.Recover()` 来替代 Gin 的 Recovery 中间件。
 | ||
| 
 | ||
| 2.  **上下文对象 (Context) 与处理器签名**:
 | ||
|     - **From**: `func(c *gin.Context)`
 | ||
|     - **To**: `func(c echo.Context) error`
 | ||
|     - **Rationale**: 这是两个框架的核心区别。所有控制器处理函数签名都需要更新。常见方法映射如下:
 | ||
|         - `ctx.ShouldBindJSON(&req)` -> `c.Bind(&req)` (Echo 的 `Bind` 更通用)
 | ||
|         - `ctx.Param("id")` -> `c.Param("id")`
 | ||
|         - `ctx.GetHeader("Authorization")` -> `c.Request().Header.Get("Authorization")`
 | ||
|         - `ctx.Set/Get("key", value)` -> `c.Set/Get("key")`
 | ||
|         - `ctx.ClientIP()` -> `c.RealIP()`
 | ||
|         - `controller.SendResponse(ctx, ...)` -> `return controller.SendResponse(c, ...)`
 | ||
|         - `ctx.AbortWithStatusJSON(...)` -> 对于需要返回特定HTTP状态码的场景(如认证中间件),将使用一个专门的辅助函数 `return controller.SendErrorWithStatus(c, http.StatusUnauthorized, ...)`。
 | ||
| 
 | ||
| 3.  **中间件 (Middleware)**:
 | ||
|     - **From**: `func AuthMiddleware(...) gin.HandlerFunc { return func(c *gin.Context) { ... } }`
 | ||
|     - **To**: `func AuthMiddleware(...) echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { ...; return next(c) } } }`
 | ||
|     - **Rationale**: Echo 的中间件是一个包装器模式。我们需要将现有的 `AuthMiddleware` 和 `AuditLogMiddleware` 逻辑迁移到这个新的结构中。
 | ||
| 
 | ||
| 4.  **Swagger 集成**:
 | ||
|     - **From**: `github.com/swaggo/gin-swagger`
 | ||
|     - **To**: `github.com/swaggo/echo-swagger`
 | ||
|     - **Rationale**: 这是 `swaggo` 官方为 Echo 提供的适配库,可以无缝替换。
 | ||
| 
 | ||
| 5.  **Pprof 与其他 `net/http` 处理器集成**:
 | ||
|     - **From**: `gin.WrapH` 和 `gin.WrapF`
 | ||
|     - **To**: `echo.WrapHandler` 和 `echo.WrapFunc`
 | ||
|     - **Rationale**: Echo 提供了类似的 `net/http` 处理器包装函数。
 | ||
| 
 | ||
| 6.  **控制器辅助函数与审计逻辑重构**:
 | ||
|     - **Affected Files**: `response.go`, `auth_utils.go`, `controller_helpers.go`
 | ||
|     - **Change**:
 | ||
|         - 所有辅助函数中的 `*gin.Context` 都将替换为 `echo.Context`。
 | ||
|         - **`response.go` 将被重构**:`setAuditDetails` 函数将成为设置所有审计信息(包括操作状态和失败详情)的唯一入口。`SendSuccessWithAudit` 和 `SendErrorWithAudit` 会调用它来将最终结果存入 `echo.Context`。
 | ||
|         - `controller_helpers.go` 中的泛型辅助函数将修改为返回 `error`,以适配 Echo 的错误处理链。
 | ||
|     - **Rationale**: 这种重构使得审计逻辑更加清晰和内聚,避免了在中间件中进行复杂的响应体捕获。
 | ||
| 
 | ||
| 7.  **DTO 注解 (Annotations)**:
 | ||
|     - **From**: Gin 相关的注解,主要包括 `binding:"..."` 和 `form:"..."`。
 | ||
|     - **To**: Echo 兼容的注解,主要包括 `validate:"..."` 和 `query:"..."`。
 | ||
|     - **Rationale**: Gin 使用 `binding` 标签进行请求参数绑定和验证,`form` 标签用于表单或查询参数绑定。Echo 框架通常结合 `go-playground/validator` 库进行验证,其对应的标签为 `validate`。对于查询参数,Echo 默认使用 `query` 标签。
 | ||
|     - **通用修改规则**:
 | ||
|         - `json:"..."` 标签保持不变。
 | ||
|         - `example:"..."` 标签保持不变。
 | ||
|         - 将 `binding:"required"` 替换为 `validate:"required"`。
 | ||
|         - 将 `form:"field,default=value"` 替换为 `query:"field"`。`default` 行为需在代码中手动实现(如在 DTO 构造函数中设置默认值),标签中不再需要。
 | ||
|         - 将 `form:"field"` 替换为 `query:"field"`。
 | ||
|         - 对于 `json:"...,omitempty"` 的字段,在 `validate` 标签中也添加 `omitempty`。
 | ||
|         - 对于结构体切片或数组字段,在 `validate` 标签中添加 `dive` 以递归验证切片元素。
 | ||
|         - 根据字段的业务含义,添加更具体的 `validate` 规则(例如 `min=0`, `cron` 等)。
 | ||
| 
 | ||
| ## Risks / Trade-offs
 | ||
| 
 | ||
| - **Risk**: 迁移工作量大,可能遗漏某些 Gin 特有的功能或上下文用法,导致运行时错误。
 | ||
| - **Mitigation**: 采用逐个文件、逐个控制器修改的方式,每修改完一部分就进行编译检查。在完成所有编码后,进行全面的手动 API 测试。
 | ||
| - **Risk (Resolved)**: `AuditLogMiddleware` 中间件最初的设计依赖于捕获响应体,这在 Echo 中难以实现。
 | ||
| - **Resolution**: 我们通过重构 `response.go` 解决了这个问题。现在,控制器在调用响应函数时,会将最终的操作状态(成功/失败)和结果详情直接存入 `echo.Context`。`AuditLogMiddleware` 只需从上下文中读取这些信息即可,**完全消除了捕获和解析响应体的需要**,使得设计更加清晰和高效。
 |