129 lines
3.4 KiB
Go
129 lines
3.4 KiB
Go
// 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
|
||
}
|