// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. // // This Source Code Form is subject to the terms of the MIT License. // If a copy of the MIT was not distributed with this file, // You can obtain one at https://github.com/gogf/gf. package ghttp import ( "bytes" "encoding/json" "github.com/gogf/gf/container/gvar" "github.com/gogf/gf/encoding/gjson" "github.com/gogf/gf/encoding/gurl" "github.com/gogf/gf/encoding/gxml" "github.com/gogf/gf/text/gregex" "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gconv" "github.com/gogf/gf/util/gvalid" "io/ioutil" "mime/multipart" "strings" ) var ( // xmlHeaderBytes is the most common XML format header. xmlHeaderBytes = []byte(" 0 { // Trim space/new line characters. body = bytes.TrimSpace(body) // JSON format checks. if body[0] == '{' && body[len(body)-1] == '}' { _ = json.Unmarshal(body, &r.bodyMap) } // XML format checks. if len(body) > 5 && bytes.EqualFold(body[:5], xmlHeaderBytes) { r.bodyMap, _ = gxml.DecodeWithoutRoot(body) } if body[0] == '<' && body[len(body)-1] == '>' { r.bodyMap, _ = gxml.DecodeWithoutRoot(body) } // Default parameters decoding. if r.bodyMap == nil { r.bodyMap, _ = gstr.Parse(r.GetBodyString()) } } } // parseForm parses the request form for HTTP method PUT, POST, PATCH. // The form data is pared into r.formMap. // // Note that if the form was parsed firstly, the request body would be cleared and empty. func (r *Request) parseForm() { if r.parsedForm { return } r.parsedForm = true if contentType := r.Header.Get("Content-Type"); contentType != "" { var err error if gstr.Contains(contentType, "multipart/") { // multipart/form-data, multipart/mixed if err = r.ParseMultipartForm(r.Server.config.FormParsingMemory); err != nil { panic(err) } } else if gstr.Contains(contentType, "form") { // application/x-www-form-urlencoded if err = r.Request.ParseForm(); err != nil { panic(err) } } if len(r.PostForm) > 0 { // Re-parse the form data using united parsing way. params := "" for name, values := range r.PostForm { // Invalid parameter name. // Only allow chars of: '\w', '[', ']', '-'. if !gregex.IsMatchString(`^[\w\-\[\]]+$`, name) { if len(r.PostForm) == 1 { // It might be JSON/XML content. r.bodyContent = gconv.UnsafeStrToBytes(name + strings.Join(values, " ")) } params = "" break } if len(values) == 1 { if len(params) > 0 { params += "&" } params += name + "=" + gurl.Encode(values[0]) } else { if len(name) > 2 && name[len(name)-2:] == "[]" { name = name[:len(name)-2] for _, v := range values { if len(params) > 0 { params += "&" } params += name + "[]=" + gurl.Encode(v) } } else { if len(params) > 0 { params += "&" } params += name + "=" + gurl.Encode(values[len(values)-1]) } } } if r.formMap, err = gstr.Parse(params); err != nil { panic(err) } } if r.formMap == nil { r.parseBody() if len(r.bodyMap) > 0 { r.formMap = r.bodyMap } } } } // GetMultipartForm parses and returns the form as multipart form. func (r *Request) GetMultipartForm() *multipart.Form { r.parseForm() return r.MultipartForm } // GetMultipartFiles returns the post files array. // Note that the request form should be type of multipart. func (r *Request) GetMultipartFiles(name string) []*multipart.FileHeader { form := r.GetMultipartForm() if form == nil { return nil } if v := form.File[name]; len(v) > 0 { return v } // Support "name[]" as array parameter. if v := form.File[name+"[]"]; len(v) > 0 { return v } return nil }