// 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 = contentTypeArr[0] if _, exist := requestBodyParseAdaptorTable[contentType]; !exist { return nil, errors.New(contentType + " : adaptor not found") } bodyData, err := ReadBody(ctx) if nil != err { return nil, err } 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 }