Files
nl-im-service/internal/utils/response.go
2026-08-24 15:29:53 +08:00

183 lines
4.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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_inforesult_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)
}