gin/response/response.go

172 lines
5.4 KiB
Go

// Package response ...
//
// Description : response ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022-06-25 20:52
package response
import (
"git.zhangdeman.cn/zhangdeman/dynamic-struct/wrapper"
"fmt"
"git.zhangdeman.cn/zhangdeman/serialize"
"net/http"
"strings"
"time"
"git.zhangdeman.cn/zhangdeman/exception"
"git.zhangdeman.cn/zhangdeman/gin/define"
"github.com/gin-gonic/gin"
)
const (
// hasSendResponseFlag 已经发送响应数据的标识, 一旦识别到, 重复调用不会执行
hasSendResponseFlag = "GIN_PKG_HAS_SEND_RESPONSE"
)
var (
// 成功的业务状态码
successBusinessCode any = "200"
)
// SetBusinessSuccessCode 设置成状态码
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:01 2024/8/17
func SetBusinessSuccessCode(code any) {
successBusinessCode = code
}
// Success 成功的响应
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:37 2022/6/25
func Success(ctx *gin.Context, data any) {
successException := exception.NewSuccess(data)
Send(ctx, successException.GetCode(), successException.GetHttpCode(), successException.GetData(), nil)
}
// SuccessWithExtension 返回扩展数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:52 2024/9/24
func SuccessWithExtension(ctx *gin.Context, data any, responseOption *define.ResponseOption) {
successException := exception.NewSuccess(data)
Send(ctx, successException.GetCode(), successException.GetHttpCode(), successException.GetData(), responseOption)
}
// Send 基础的发送数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:40 2022/6/25
func Send(ctx *gin.Context, code any, httpCode int, data any, responseOption *define.ResponseOption) {
if nil == responseOption {
responseOption = &define.ResponseOption{
ContentType: "application/json",
Extension: make(map[string]any),
}
}
if len(responseOption.ContentType) == 0 {
responseOption.ContentType = "application/json"
}
if len(responseOption.XmlName) == 0 {
responseOption.XmlName = "ResponseData"
}
// 设置请求是否成功的标识
ctx.Set(define.GetHttpHandleConfig().RequestIsSuccessField, fmt.Sprintf("%v", code) == fmt.Sprintf("%v", successBusinessCode))
if ctx.GetBool(hasSendResponseFlag) {
// 已经发送过数据, 后面在发送数据, 不执行
return
}
// 设置数据已发送的标识
defer ctx.Set(hasSendResponseFlag, true)
finishRequestTime := time.Now()
responseData := BuildResponseData(ctx, finishRequestTime, code, data, responseOption.Extension)
// 记录完成时间
responseConfig := define.GetHttpHandleConfig()
ctx.Set(responseConfig.FinishRequestTimeField, finishRequestTime.UnixMilli())
ctx.Set(responseConfig.ResponseDataField, responseData)
responseException := exception.New(code, httpCode, responseData)
responseContentType := getResponseDataType(responseOption.ContentType)
responseInstance, _ := wrapper.NewJson(serialize.JSON.MarshalForStringIgnoreError(responseException.GetData()), &wrapper.Option{XmlName: responseOption.XmlName})
finalResponseData, _ := responseInstance.Marshal(responseContentType)
ctx.Data(responseException.GetHttpCode(), responseContentType, finalResponseData)
}
// getResponseDataType 获取相应数据类型
func getResponseDataType(contentType string) string {
if contentType == "" {
return "json"
}
applicationInfo := strings.Split(contentType, ";")[0]
applicationInfoArr := strings.Split(applicationInfo, "/")
return applicationInfoArr[len(applicationInfoArr)-1]
}
// BuildResponseData 构建响应数据
func BuildResponseData(ctx *gin.Context, finishTime time.Time, code any, data any, extension map[string]any) map[string]any {
responseConfig := define.GetHttpHandleConfig()
responseData := map[string]any{
responseConfig.ResponseCodeField: code,
responseConfig.ResponseMessageField: exception.GetMessage(code),
responseConfig.ResponseTraceIDField: ctx.GetString(responseConfig.ResponseTraceIDField),
responseConfig.ResponseDataField: data,
responseConfig.HandleRequestCostField: finishTime.UnixMilli() - ctx.GetInt64(responseConfig.StartRequestTimeField),
}
if responseConfig.EnableExtensionOutput && nil != extension {
responseData[responseConfig.ExtensionOutputField] = extension
}
return responseData
}
// SendWithStatusOK ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 22:41 2022/6/25
func SendWithStatusOK(ctx *gin.Context, code any, data any) {
Send(ctx, code, http.StatusOK, data, nil)
}
// SendWithException 使用exception发送数据
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 13:08 2022/6/26
func SendWithException(ctx *gin.Context, e exception.IException, data map[string]any) {
if nil == e {
e = exception.NewSuccess(data)
}
if !define.GetHttpHandleConfig().DisableDebugStackOutput && nil != e {
stack := e.GetStack()
if len(stack) > 0 {
fmt.Println(stack)
}
}
outputData := map[string]any{
"e_data": e.GetData(),
"u_e_data": data,
}
Send(ctx, e.GetCode(), e.GetHttpCode(), outputData, nil)
}
// JSON ctx.JSON 的平替, 增加了数据是否已相应的标识
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:51 2023/2/15
func JSON(ctx *gin.Context, httpCode int, data any) {
if ctx.GetBool(hasSendResponseFlag) {
// 已经发送过数据, 后面在发送数据, 不执行
return
}
// 设置数据已发送的标识
defer ctx.Set(hasSendResponseFlag, true)
ctx.JSON(httpCode, data)
}