gin/request/parse_body/execute.go

129 lines
3.4 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 parse_body ...
//
// Description : parse_body ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-10-22 16:43
package parse_body
import (
"bytes"
"errors"
"git.zhangdeman.cn/zhangdeman/gin/request/abstract"
"git.zhangdeman.cn/zhangdeman/serialize"
"github.com/gin-gonic/gin"
"io"
"strings"
)
var (
requestBodyParseAdaptorTable = map[string]abstract.RequestBodyParseAdaptor{}
)
func init() {
requestBodyParseAdaptorTable["xml"] = serialize.Xml
requestBodyParseAdaptorTable["ini"] = serialize.Ini
requestBodyParseAdaptorTable["yml"] = serialize.Yml
requestBodyParseAdaptorTable["yaml"] = serialize.Yml
requestBodyParseAdaptorTable["json"] = serialize.JSON
requestBodyParseAdaptorTable["x-www-form-urlencoded"] = serialize.JSON
}
// Register 注册适配器实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:45 2024/10/22
func Register(requestType string, adaptor abstract.RequestBodyParseAdaptor) {
if nil == adaptor {
return
}
requestBodyParseAdaptorTable[requestType] = adaptor
}
// Execute 解析请求BODY数据
func Execute(ctx *gin.Context, receiver any) ([]byte, error) {
contentType := strings.ToLower(strings.ReplaceAll(ctx.ContentType(), " ", ""))
if len(contentType) == 0 {
return []byte("{}"), nil
}
// 裁剪出真实的类型,之所以截取,是因为 content_type 中可能还包含编码信息, 如 : application/json;chaset=utf8
contentTypeArr := strings.Split(contentType, ";")
contentTypeFormatArr := strings.Split(contentTypeArr[0], "/")
if len(contentTypeFormatArr) != 2 {
return nil, errors.New(contentType + " : content_type format error")
}
// 裁剪出真实的类型,之所以截取,是因为 content_type 中可能还包含编码信息, 如 : application/json;charset=utf8
contentType = contentTypeFormatArr[1]
if _, exist := requestBodyParseAdaptorTable[contentType]; !exist {
return nil, errors.New(contentType + " : adaptor not found")
}
var (
bodyData []byte
err error
exist bool
body any
)
bodyKey := "_body_read_result"
if body, exist = ctx.Get(bodyKey); exist && nil != body {
bodyData = body.([]byte)
} else {
if bodyData, err = ReadBody(ctx); nil != err {
return nil, err
}
// 设置读取结果
ctx.Set(bodyKey, bodyData)
}
if err = requestBodyParseAdaptorTable[contentType].Unmarshal(bodyData, receiver); nil != err {
return nil, err
}
byteData := serialize.JSON.MarshalForByteIgnoreError(receiver)
return byteData, nil
}
// ExecuteForMap 高层级包装表单解析为map
func ExecuteForMap(ctx *gin.Context) (map[string]any, error) {
var (
err error
result map[string]any
)
if _, err = Execute(ctx, &result); nil != err {
return nil, err
}
return result, nil
}
// ReadBody 读取请求Body
func ReadBody(ctx *gin.Context) ([]byte, error) {
var (
data []byte
err error
)
// 判断form url encode
if strings.Contains(ctx.ContentType(), "x-www-form-urlencoded") {
if err = ctx.Request.ParseForm(); nil != err {
return nil, err
}
body := map[string]any{}
for paramName, itemParam := range ctx.Request.PostForm {
if len(itemParam) > 0 {
body[paramName] = itemParam[0]
} else {
body[paramName] = ""
}
}
return serialize.JSON.MarshalForByteIgnoreError(body), nil
}
// 读取Body信息
if data, err = io.ReadAll(ctx.Request.Body); nil != err {
return nil, err
}
// 重置Body信息
ctx.Request.Body = io.NopCloser(bytes.NewBuffer(data))
return data, nil
}