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
 | 
						||
}
 |