/** * package utils * 作用:提供统一的API响应工具函数 * 说明:所有响应统一返回HTTP 200状态码,错误通过code字段标识 */ package utils import ( "net/http" "strconv" "time" "xk-websocket-v2/internal/model" "github.com/gin-gonic/gin" "github.com/spf13/viper" ) // 业务状态码常量 const ( CodeSuccess = 0 // 成功 CodeBadRequest = 400 // 参数错误 CodeUnauthorized = 401 // 未认证 CodeForbidden = 403 // 无权限 CodeNotFound = 404 // 资源不存在 CodeInternalError = 500 // 服务器错误 ) // 响应类型常量 const ( TypeSuccess = "success" TypeError = "error" ) /** * getECS * 作用:获取服务器标识 */ func getECS() string { ecs := viper.GetString("server.ecs") if ecs == "" { return "localhost" } return ecs } /** * formatDuration * 作用:格式化响应时间为 "XX ms" 格式 */ func formatDuration(d time.Duration) string { ms := d.Milliseconds() return strconv.FormatInt(ms, 10) + " ms" } /** * ResponseWithStatus * 作用:统一响应的单一组装口——构造含 interface_info(result_time/ecs)的 * ApiResponse 并按指定 HTTP 状态码返回。 * 说明:绝大多数业务接口经 Response 走 HTTP 200;少数需要真实 HTTP 状态码的 * 场景(如认证中间件的 401,前端请求层按状态码识别登出)直接调用本函数, * 保证所有出口的响应体结构完全一致,不再出现缺 interface_info 的手工构造 */ func ResponseWithStatus(c *gin.Context, httpStatus int, code int, message string, result interface{}, responseType string) { // 从Context获取请求开始时间 startTime, exists := c.Get("request_start_time") var duration time.Duration if exists { duration = time.Since(startTime.(time.Time)) } else { duration = 0 } response := model.ApiResponse{ Code: code, Message: message, Result: result, Type: responseType, InterfaceInfo: model.InterfaceInfo{ ResultTime: formatDuration(duration), Ecs: getECS(), }, } c.JSON(httpStatus, response) } /** * Response * 作用:统一的响应函数,所有业务响应都通过此函数返回 * 说明:统一返回HTTP 200状态码(错误经 code 字段标识),组装逻辑收口到 ResponseWithStatus */ func Response(c *gin.Context, code int, message string, result interface{}, responseType string) { ResponseWithStatus(c, http.StatusOK, code, message, result, responseType) } /** * Success * 作用:成功响应(无数据) */ func Success(c *gin.Context, message string) { if message == "" { message = "操作成功" } Response(c, CodeSuccess, message, nil, TypeSuccess) } /** * SuccessWithData * 作用:成功响应(带数据) */ func SuccessWithData(c *gin.Context, data interface{}, message string) { if message == "" { message = "获取成功" } Response(c, CodeSuccess, message, data, TypeSuccess) } /** * Error * 作用:错误响应(自定义状态码和消息) */ func Error(c *gin.Context, code int, message string) { if message == "" { message = "操作失败" } Response(c, code, message, nil, TypeError) } /** * BadRequest * 作用:参数错误响应(code=400) */ func BadRequest(c *gin.Context, message string) { if message == "" { message = "参数错误" } Response(c, CodeBadRequest, message, nil, TypeError) } /** * Unauthorized * 作用:未认证响应(code=401) */ func Unauthorized(c *gin.Context, message string) { if message == "" { message = "未认证" } Response(c, CodeUnauthorized, message, nil, TypeError) } /** * Forbidden * 作用:无权限响应(code=403) */ func Forbidden(c *gin.Context, message string) { if message == "" { message = "无权限" } Response(c, CodeForbidden, message, nil, TypeError) } /** * NotFound * 作用:资源不存在响应(code=404) */ func NotFound(c *gin.Context, message string) { if message == "" { message = "资源不存在" } Response(c, CodeNotFound, message, nil, TypeError) } /** * InternalError * 作用:服务器错误响应(code=500) */ func InternalError(c *gin.Context, message string) { if message == "" { message = "服务器错误" } Response(c, CodeInternalError, message, nil, TypeError) }