mirror of
https://gitee.com/johng/gf
synced 2026-07-04 13:02:36 +08:00
improve parameter parsing feature for ghttp.Request
This commit is contained in:
@ -5,20 +5,20 @@ import (
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Uid int `json:"uid"`
|
||||
Name string `json:"name" params:"username"`
|
||||
Pass1 string `json:"pass1" params:"password1,userpass1"`
|
||||
Pass2 string `json:"pass2" params:"password3,userpass2"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
type User struct {
|
||||
Uid int `json:"uid"`
|
||||
Name string `json:"name" p:"username"`
|
||||
Pass1 string `json:"pass1" p:"password1"`
|
||||
Pass2 string `json:"pass2" p:"password2"`
|
||||
}
|
||||
|
||||
s := g.Server()
|
||||
s.BindHandler("/user", func(r *ghttp.Request) {
|
||||
user := new(User)
|
||||
r.GetToStruct(user)
|
||||
//r.GetPostToStruct(user)
|
||||
//r.GetQueryToStruct(user)
|
||||
var user *User
|
||||
if err := r.Parse(&user); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
r.Response.WriteJson(user)
|
||||
})
|
||||
s.SetPort(8199)
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db := g.DB()
|
||||
// 开启调试模式,以便于记录所有执行的SQL
|
||||
db.SetDebug(true)
|
||||
|
||||
db.Table("user").Delete("score < ", 60)
|
||||
s := g.Server()
|
||||
s.BindHandler("/test", func(r *ghttp.Request) {
|
||||
fmt.Println(r.GetBody())
|
||||
r.Response.Write(r.GetBody())
|
||||
})
|
||||
s.SetPort(8199)
|
||||
s.Run()
|
||||
}
|
||||
|
||||
11
.example/other/test2.go
Normal file
11
.example/other/test2.go
Normal file
@ -0,0 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
r := ghttp.PostContent("http://127.0.0.1:8199/test", `<doc><id>1</id><name>john</name><password1>123Abc!@#</password1><password2>123Abc!@#</password2></doc>`)
|
||||
fmt.Println(r)
|
||||
}
|
||||
@ -8,7 +8,6 @@
|
||||
package gxml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/clbanning/mxj"
|
||||
@ -16,7 +15,7 @@ import (
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
)
|
||||
|
||||
// 将XML内容解析为map变量
|
||||
// Decode parses <content> into and returns as map.
|
||||
func Decode(content []byte) (map[string]interface{}, error) {
|
||||
res, err := convert(content)
|
||||
if err != nil {
|
||||
@ -25,23 +24,42 @@ func Decode(content []byte) (map[string]interface{}, error) {
|
||||
return mxj.NewMapXml(res)
|
||||
}
|
||||
|
||||
// 将map变量解析为XML格式内容
|
||||
func Encode(v map[string]interface{}, rootTag ...string) ([]byte, error) {
|
||||
return mxj.Map(v).Xml(rootTag...)
|
||||
// DecodeWithoutRoot parses <content> into a map, and returns the map without root level.
|
||||
func DecodeWithoutRoot(content []byte) (map[string]interface{}, error) {
|
||||
res, err := convert(content)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, err := mxj.NewMapXml(res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, v := range m {
|
||||
if r, ok := v.(map[string]interface{}); ok {
|
||||
return r, nil
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func EncodeWithIndent(v map[string]interface{}, rootTag ...string) ([]byte, error) {
|
||||
return mxj.Map(v).XmlIndent("", "\t", rootTag...)
|
||||
// Encode encodes map <m> to a XML format content as bytes.
|
||||
// The optional parameter <rootTag> is used to specify the XML root tag.
|
||||
func Encode(m map[string]interface{}, rootTag ...string) ([]byte, error) {
|
||||
return mxj.Map(m).Xml(rootTag...)
|
||||
}
|
||||
|
||||
// XML格式内容直接转换为JSON格式内容
|
||||
// Encode encodes map <m> to a XML format content as bytes with indent.
|
||||
// The optional parameter <rootTag> is used to specify the XML root tag.
|
||||
func EncodeWithIndent(m map[string]interface{}, rootTag ...string) ([]byte, error) {
|
||||
return mxj.Map(m).XmlIndent("", "\t", rootTag...)
|
||||
}
|
||||
|
||||
// ToJson converts <content> as XML format into JSON format bytes.
|
||||
func ToJson(content []byte) ([]byte, error) {
|
||||
res, err := convert(content)
|
||||
if err != nil {
|
||||
fmt.Println("convert error. ", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mv, err := mxj.NewMapXml(res)
|
||||
if err == nil {
|
||||
return mv.Json()
|
||||
@ -50,7 +68,7 @@ func ToJson(content []byte) ([]byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// XML字符集预处理
|
||||
// convert converts the encoding of given XML content from XML root tag into UTF-8 encoding content.
|
||||
func convert(xml []byte) (res []byte, err error) {
|
||||
patten := `<\?xml.*encoding\s*=\s*['|"](.*?)['|"].*\?>`
|
||||
matchStr, err := gregex.MatchString(patten, string(xml))
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/text/gregex"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
@ -91,10 +92,11 @@ func (c *Client) Post(url string, data ...interface{}) (resp *ClientResponse, er
|
||||
// Custom Content-Type.
|
||||
req.Header.Set("Content-Type", v)
|
||||
} else {
|
||||
// Auto detecting and setting the post content format: JSON.
|
||||
if json.Valid(paramBytes) {
|
||||
// Auto detecting and setting the post content format: JSON.
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
} else {
|
||||
} else if gregex.IsMatchString(`^\w+=.+`, param) {
|
||||
// If the parameters passed like "name=value", it then uses form type.
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,15 +7,39 @@
|
||||
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/gstr"
|
||||
"github.com/gogf/gf/util/gconv"
|
||||
"github.com/gogf/gf/util/gvalid"
|
||||
"io/ioutil"
|
||||
"mime/multipart"
|
||||
)
|
||||
|
||||
var (
|
||||
// xmlHeaderBytes is the most common XML format header.
|
||||
xmlHeaderBytes = []byte("<?xml")
|
||||
)
|
||||
|
||||
// Parse calls r.GetStruct to convert the parameters, which are sent from client,
|
||||
// to given struct, and then calls gvalid.CheckStruct validating the struct according
|
||||
// to the validation tag of the struct.
|
||||
//
|
||||
// See GetStruct, gvalid.CheckStruct.
|
||||
func (r *Request) Parse(pointer interface{}) error {
|
||||
if err := r.GetStruct(pointer); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := gvalid.CheckStruct(pointer, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get is alias of GetRequest, which is one of the most commonly used functions for
|
||||
// retrieving parameter.
|
||||
// See GetRequest.
|
||||
@ -131,18 +155,18 @@ func (r *Request) GetMapStrStr(def ...map[string]interface{}) map[string]string
|
||||
// GetStruct is alias of GetRequestToStruct.
|
||||
// See GetRequestToStruct.
|
||||
func (r *Request) GetStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
return r.GetRequestToStruct(pointer, mapping...)
|
||||
return r.GetRequestStruct(pointer, mapping...)
|
||||
}
|
||||
|
||||
// GetToStruct is alias of GetRequestToStruct.
|
||||
// See GetRequestToStruct.
|
||||
// Deprecated.
|
||||
func (r *Request) GetToStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
return r.GetRequestToStruct(pointer, mapping...)
|
||||
return r.GetRequestStruct(pointer, mapping...)
|
||||
}
|
||||
|
||||
// ParseQuery parses query string into r.queryMap.
|
||||
func (r *Request) ParseQuery() {
|
||||
// parseQuery parses query string into r.queryMap.
|
||||
func (r *Request) parseQuery() {
|
||||
if r.parsedQuery {
|
||||
return
|
||||
}
|
||||
@ -157,19 +181,36 @@ func (r *Request) ParseQuery() {
|
||||
}
|
||||
|
||||
// ParseRaw parses the request raw data into r.rawMap.
|
||||
func (r *Request) ParseBody() {
|
||||
// Note that it also supports JSON data from client request.
|
||||
func (r *Request) parseBody() {
|
||||
if r.parsedBody {
|
||||
return
|
||||
}
|
||||
r.parsedBody = true
|
||||
if body := r.GetBodyString(); len(body) > 0 {
|
||||
r.bodyMap, _ = gstr.Parse(body)
|
||||
if body := r.GetBody(); len(body) > 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.
|
||||
// parseForm parses the request form for HTTP method PUT, POST, PATCH.
|
||||
// The form data is pared into r.formMap.
|
||||
func (r *Request) ParseForm() {
|
||||
func (r *Request) parseForm() {
|
||||
if r.parsedForm {
|
||||
return
|
||||
}
|
||||
@ -217,7 +258,7 @@ func (r *Request) ParseForm() {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
r.ParseBody()
|
||||
r.parseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
r.formMap = r.bodyMap
|
||||
}
|
||||
@ -227,7 +268,7 @@ func (r *Request) ParseForm() {
|
||||
|
||||
// GetMultipartForm parses and returns the form as multipart form.
|
||||
func (r *Request) GetMultipartForm() *multipart.Form {
|
||||
r.ParseForm()
|
||||
r.parseForm()
|
||||
return r.MultipartForm
|
||||
}
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
|
||||
// SetForm sets custom form value with key-value pair.
|
||||
func (r *Request) SetForm(key string, value interface{}) {
|
||||
r.ParseForm()
|
||||
r.parseForm()
|
||||
if r.formMap == nil {
|
||||
r.formMap = make(map[string]interface{})
|
||||
}
|
||||
@ -25,7 +25,7 @@ func (r *Request) SetForm(key string, value interface{}) {
|
||||
// It returns <def> if <key> does not exist in the form.
|
||||
// It returns nil if <def> is not passed.
|
||||
func (r *Request) GetForm(key string, def ...interface{}) interface{} {
|
||||
r.ParseForm()
|
||||
r.parseForm()
|
||||
if len(r.formMap) > 0 {
|
||||
if v, ok := r.formMap[key]; ok {
|
||||
return v
|
||||
@ -105,7 +105,7 @@ func (r *Request) GetFormInterfaces(key string, def ...interface{}) []interface{
|
||||
// The parameter <kvMap> specifies the keys retrieving from client parameters,
|
||||
// the associated values are the default values if the client does not pass.
|
||||
func (r *Request) GetFormMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseForm()
|
||||
r.parseForm()
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
if len(r.formMap) == 0 {
|
||||
return kvMap[0]
|
||||
@ -158,7 +158,7 @@ func (r *Request) GetFormMapStrVar(kvMap ...map[string]interface{}) map[string]*
|
||||
// given struct object. Note that the parameter <pointer> is a pointer to the struct object.
|
||||
// The optional parameter <mapping> is used to specify the key to attribute mapping.
|
||||
func (r *Request) GetFormStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
r.ParseForm()
|
||||
r.parseForm()
|
||||
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
|
||||
if len(mapping) > 0 {
|
||||
for k, v := range mapping[0] {
|
||||
|
||||
@ -18,14 +18,16 @@ import (
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: form > body.
|
||||
//
|
||||
// Deprecated.
|
||||
func (r *Request) GetPost(key string, def ...interface{}) interface{} {
|
||||
r.ParseForm()
|
||||
r.parseForm()
|
||||
if len(r.formMap) > 0 {
|
||||
if v, ok := r.formMap[key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
r.ParseBody()
|
||||
r.parseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
return v
|
||||
@ -37,66 +39,82 @@ func (r *Request) GetPost(key string, def ...interface{}) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostVar(key string, def ...interface{}) *gvar.Var {
|
||||
return gvar.New(r.GetPost(key, def...))
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostString(key string, def ...interface{}) string {
|
||||
return r.GetPostVar(key, def...).String()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostBool(key string, def ...interface{}) bool {
|
||||
return r.GetPostVar(key, def...).Bool()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostInt(key string, def ...interface{}) int {
|
||||
return r.GetPostVar(key, def...).Int()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostInt32(key string, def ...interface{}) int32 {
|
||||
return r.GetPostVar(key, def...).Int32()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostInt64(key string, def ...interface{}) int64 {
|
||||
return r.GetPostVar(key, def...).Int64()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostInts(key string, def ...interface{}) []int {
|
||||
return r.GetPostVar(key, def...).Ints()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostUint(key string, def ...interface{}) uint {
|
||||
return r.GetPostVar(key, def...).Uint()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostUint32(key string, def ...interface{}) uint32 {
|
||||
return r.GetPostVar(key, def...).Uint32()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostUint64(key string, def ...interface{}) uint64 {
|
||||
return r.GetPostVar(key, def...).Uint64()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostFloat32(key string, def ...interface{}) float32 {
|
||||
return r.GetPostVar(key, def...).Float32()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostFloat64(key string, def ...interface{}) float64 {
|
||||
return r.GetPostVar(key, def...).Float64()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostFloats(key string, def ...interface{}) []float64 {
|
||||
return r.GetPostVar(key, def...).Floats()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostArray(key string, def ...interface{}) []string {
|
||||
return r.GetPostVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostStrings(key string, def ...interface{}) []string {
|
||||
return r.GetPostVar(key, def...).Strings()
|
||||
}
|
||||
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostInterfaces(key string, def ...interface{}) []interface{} {
|
||||
return r.GetPostVar(key, def...).Interfaces()
|
||||
}
|
||||
@ -107,9 +125,11 @@ func (r *Request) GetPostInterfaces(key string, def ...interface{}) []interface{
|
||||
//
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: form > body.
|
||||
//
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseForm()
|
||||
r.ParseBody()
|
||||
r.parseForm()
|
||||
r.parseBody()
|
||||
var ok, filter bool
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
filter = true
|
||||
@ -146,6 +166,8 @@ func (r *Request) GetPostMap(kvMap ...map[string]interface{}) map[string]interfa
|
||||
// as map[string]string. The parameter <kvMap> specifies the keys
|
||||
// retrieving from client parameters, the associated values are the default values if the client
|
||||
// does not pass.
|
||||
//
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostMapStrStr(kvMap ...map[string]interface{}) map[string]string {
|
||||
postMap := r.GetPostMap(kvMap...)
|
||||
if len(postMap) > 0 {
|
||||
@ -162,6 +184,8 @@ func (r *Request) GetPostMapStrStr(kvMap ...map[string]interface{}) map[string]s
|
||||
// as map[string]*gvar.Var. The parameter <kvMap> specifies the keys
|
||||
// retrieving from client parameters, the associated values are the default values if the client
|
||||
// does not pass.
|
||||
//
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostMapStrVar(kvMap ...map[string]interface{}) map[string]*gvar.Var {
|
||||
postMap := r.GetPostMap(kvMap...)
|
||||
if len(postMap) > 0 {
|
||||
@ -178,6 +202,8 @@ func (r *Request) GetPostMapStrVar(kvMap ...map[string]interface{}) map[string]*
|
||||
// and converts them to given struct object. Note that the parameter <pointer> is a pointer
|
||||
// to the struct object. The optional parameter <mapping> is used to specify the key to
|
||||
// attribute mapping.
|
||||
//
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
|
||||
if len(mapping) > 0 {
|
||||
@ -189,6 +215,7 @@ func (r *Request) GetPostStruct(pointer interface{}, mapping ...map[string]strin
|
||||
}
|
||||
|
||||
// GetPostToStruct is alias of GetQueryStruct. See GetPostStruct.
|
||||
//
|
||||
// Deprecated.
|
||||
func (r *Request) GetPostToStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
return r.GetPostStruct(pointer, mapping...)
|
||||
|
||||
@ -15,7 +15,7 @@ import (
|
||||
|
||||
// SetQuery sets custom query value with key-value pair.
|
||||
func (r *Request) SetQuery(key string, value interface{}) {
|
||||
r.ParseQuery()
|
||||
r.parseQuery()
|
||||
if r.queryMap == nil {
|
||||
r.queryMap = make(map[string]interface{})
|
||||
}
|
||||
@ -29,13 +29,13 @@ func (r *Request) SetQuery(key string, value interface{}) {
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: query > body.
|
||||
func (r *Request) GetQuery(key string, def ...interface{}) interface{} {
|
||||
r.ParseQuery()
|
||||
r.parseQuery()
|
||||
if len(r.queryMap) > 0 {
|
||||
if v, ok := r.queryMap[key]; ok {
|
||||
return v
|
||||
}
|
||||
}
|
||||
r.ParseBody()
|
||||
r.parseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
if v, ok := r.bodyMap[key]; ok {
|
||||
return v
|
||||
@ -118,8 +118,8 @@ func (r *Request) GetQueryInterfaces(key string, def ...interface{}) []interface
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: query > body.
|
||||
func (r *Request) GetQueryMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseQuery()
|
||||
r.ParseBody()
|
||||
r.parseQuery()
|
||||
r.parseBody()
|
||||
var m map[string]interface{}
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
if len(r.queryMap) == 0 && len(r.bodyMap) == 0 {
|
||||
@ -193,7 +193,7 @@ func (r *Request) GetQueryMapStrVar(kvMap ...map[string]interface{}) map[string]
|
||||
// to the struct object. The optional parameter <mapping> is used to specify the key to
|
||||
// attribute mapping.
|
||||
func (r *Request) GetQueryStruct(pointer interface{}, mapping ...map[string]string) error {
|
||||
r.ParseQuery()
|
||||
r.parseQuery()
|
||||
tagMap := structs.TagMapName(pointer, paramTagPriority, true)
|
||||
if len(mapping) > 0 {
|
||||
for k, v := range mapping[0] {
|
||||
|
||||
@ -26,7 +26,7 @@ func (r *Request) GetRequest(key string, def ...interface{}) interface{} {
|
||||
value = r.GetForm(key)
|
||||
}
|
||||
if value == nil {
|
||||
r.ParseBody()
|
||||
r.parseBody()
|
||||
if len(r.bodyMap) > 0 {
|
||||
value = r.bodyMap[key]
|
||||
}
|
||||
@ -168,9 +168,9 @@ func (r *Request) GetRequestInterfaces(key string, def ...interface{}) []interfa
|
||||
// Note that if there're multiple parameters with the same name, the parameters are retrieved and overwrote
|
||||
// in order of priority: router < query < body < form < custom.
|
||||
func (r *Request) GetRequestMap(kvMap ...map[string]interface{}) map[string]interface{} {
|
||||
r.ParseQuery()
|
||||
r.ParseForm()
|
||||
r.ParseBody()
|
||||
r.parseQuery()
|
||||
r.parseForm()
|
||||
r.parseBody()
|
||||
var ok, filter bool
|
||||
var length int
|
||||
if len(kvMap) > 0 && kvMap[0] != nil {
|
||||
|
||||
@ -17,7 +17,51 @@ import (
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Params_Json(t *testing.T) {
|
||||
func Test_Params_Json_Request(t *testing.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `p:"password1" v:"password1"`
|
||||
Pass2 string `p:"password2" v:"required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致"`
|
||||
}
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/get", func(r *ghttp.Request) {
|
||||
r.Response.WriteExit(r.Get("id"), r.Get("name"))
|
||||
})
|
||||
s.BindHandler("/map", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
r.Response.WriteExit(m["id"], m["name"], m["password1"], m["password2"])
|
||||
}
|
||||
})
|
||||
s.BindHandler("/parse", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
var user *User
|
||||
if err := r.Parse(&user); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
r.Response.WriteExit(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
}
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/get", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john`)
|
||||
gtest.Assert(client.GetContent("/map", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john123Abc!@#123Abc!@#`)
|
||||
gtest.Assert(client.PostContent("/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john123Abc!@#123Abc!@#`)
|
||||
gtest.Assert(client.PostContent("/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123"}`), `密码强度不足; 两次密码不一致`)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Params_Json_Response(t *testing.T) {
|
||||
type User struct {
|
||||
Uid int
|
||||
Name string
|
||||
|
||||
@ -23,33 +23,49 @@ func Test_Params_Struct(t *testing.T) {
|
||||
Id int
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `params:"password1"`
|
||||
Pass2 string `params:"password2" gvalid:"passwd1 @required|length:2,20|password3#||密码强度不足"`
|
||||
Pass1 string `p:"password1"`
|
||||
Pass2 string `p:"password2" v:"passwd1 @required|length:2,20|password3#||密码强度不足"`
|
||||
}
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/struct1", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
user := new(User)
|
||||
r.GetToStruct(user)
|
||||
r.Response.Write(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
if err := r.GetStruct(user); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
r.Response.WriteExit(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
}
|
||||
})
|
||||
s.BindHandler("/struct2", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
user := (*User)(nil)
|
||||
r.GetToStruct(&user)
|
||||
if err := r.GetStruct(&user); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
if user != nil {
|
||||
r.Response.Write(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
r.Response.WriteExit(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
}
|
||||
}
|
||||
})
|
||||
s.BindHandler("/struct-valid", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
user := new(User)
|
||||
r.GetToStruct(user)
|
||||
err := gvalid.CheckStruct(user, nil)
|
||||
r.Response.Write(err.Maps())
|
||||
if err := r.GetStruct(user); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
if err := gvalid.CheckStruct(user, nil); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
s.BindHandler("/parse", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
var user *User
|
||||
if err := r.Parse(&user); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
r.Response.WriteExit(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
}
|
||||
})
|
||||
s.SetPort(p)
|
||||
@ -65,6 +81,10 @@ func Test_Params_Struct(t *testing.T) {
|
||||
gtest.Assert(client.PostContent("/struct1", `id=1&name=john&password1=123&password2=456`), `1john123456`)
|
||||
gtest.Assert(client.PostContent("/struct2", `id=1&name=john&password1=123&password2=456`), `1john123456`)
|
||||
gtest.Assert(client.PostContent("/struct2", ``), ``)
|
||||
gtest.Assert(client.PostContent("/struct-valid", `id=1&name=john&password1=123&password2=0`), `{"passwd1":{"length":"字段长度为2到20个字符","password3":"密码强度不足"}}`)
|
||||
gtest.Assert(client.PostContent("/struct-valid", `id=1&name=john&password1=123&password2=0`), `字段长度为2到20个字符; 密码强度不足`)
|
||||
gtest.Assert(client.PostContent("/parse", `id=1&name=john&password1=123&password2=0`), `字段长度为2到20个字符; 密码强度不足`)
|
||||
gtest.Assert(client.GetContent("/parse", `id=1&name=john&password1=123&password2=456`), `密码强度不足`)
|
||||
gtest.Assert(client.GetContent("/parse", `id=1&name=john&password1=123Abc!@#&password2=123Abc!@#`), `1john123Abc!@#123Abc!@#`)
|
||||
gtest.Assert(client.PostContent("/parse", `{"id":1,"name":"john","password1":"123Abc!@#","password2":"123Abc!@#"}`), `1john123Abc!@#123Abc!@#`)
|
||||
})
|
||||
}
|
||||
|
||||
65
net/ghttp/ghttp_unit_param_xml_test.go
Normal file
65
net/ghttp/ghttp_unit_param_xml_test.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Copyright 2018 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_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/frame/g"
|
||||
"github.com/gogf/gf/net/ghttp"
|
||||
"github.com/gogf/gf/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Params_Xml_Request(t *testing.T) {
|
||||
type User struct {
|
||||
Id int
|
||||
Name string
|
||||
Time *time.Time
|
||||
Pass1 string `p:"password1" v:"password1"`
|
||||
Pass2 string `p:"password2" v:"required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致"`
|
||||
}
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/get", func(r *ghttp.Request) {
|
||||
r.Response.WriteExit(r.Get("id"), r.Get("name"))
|
||||
})
|
||||
s.BindHandler("/map", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
r.Response.WriteExit(m["id"], m["name"], m["password1"], m["password2"])
|
||||
}
|
||||
})
|
||||
s.BindHandler("/parse", func(r *ghttp.Request) {
|
||||
if m := r.GetMap(); len(m) > 0 {
|
||||
var user *User
|
||||
if err := r.Parse(&user); err != nil {
|
||||
r.Response.WriteExit(err)
|
||||
}
|
||||
r.Response.WriteExit(user.Id, user.Name, user.Pass1, user.Pass2)
|
||||
}
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouterMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
content1 := `<doc><id>1</id><name>john</name><password1>123Abc!@#</password1><password2>123Abc!@#</password2></doc>`
|
||||
content2 := `<doc><id>1</id><name>john</name><password1>123Abc!@#</password1><password2>123</password2></doc>`
|
||||
gtest.Assert(client.GetContent("/get", content1), `1john`)
|
||||
gtest.Assert(client.PostContent("/get", content1), `1john`)
|
||||
gtest.Assert(client.GetContent("/map", content1), `1john123Abc!@#123Abc!@#`)
|
||||
gtest.Assert(client.PostContent("/map", content1), `1john123Abc!@#123Abc!@#`)
|
||||
gtest.Assert(client.PostContent("/parse", content1), `1john123Abc!@#123Abc!@#`)
|
||||
gtest.Assert(client.PostContent("/parse", content2), `密码强度不足; 两次密码不一致`)
|
||||
})
|
||||
}
|
||||
@ -87,7 +87,15 @@ var (
|
||||
)
|
||||
|
||||
// SetTimeZone sets the time zone for current whole process.
|
||||
// The parameter <zone> is an area string specifying corresponding time zone, eg: Asia/Shanghai.
|
||||
// The parameter <zone> is an area string specifying corresponding time zone,
|
||||
// eg: Asia/Shanghai.
|
||||
//
|
||||
// Note that the time zone database needed by LoadLocation may not be
|
||||
// present on all systems, especially non-Unix systems.
|
||||
// LoadLocation looks in the directory or uncompressed zip file
|
||||
// named by the ZONEINFO environment variable, if any, then looks in
|
||||
// known installation locations on Unix systems,
|
||||
// and finally looks in $GOROOT/lib/time/zoneinfo.zip.
|
||||
func SetTimeZone(zone string) error {
|
||||
location, err := time.LoadLocation(zone)
|
||||
if err == nil {
|
||||
|
||||
@ -65,6 +65,13 @@ type CustomMsg = map[string]interface{}
|
||||
// 解析单条sequence tag,格式: [数值键名/别名@]校验规则[#错误提示],
|
||||
// 其中校验规则如果有多个那么以"|"符号分隔,错误提示同理。
|
||||
func parseSequenceTag(tag string) (name, rule, msg string) {
|
||||
// Just a alias name.
|
||||
// Eg: password1
|
||||
if gregex.IsMatchString(`^\w+$`, tag) {
|
||||
return tag, "", ""
|
||||
}
|
||||
// Complete sequence tag.
|
||||
// Eg: required|length:2,20|password3|same:password1#||密码强度不足|两次密码不一致
|
||||
match, _ := gregex.MatchString(`\s*((\w+)\s*@){0,1}\s*([^#]+)\s*(#\s*(.*)){0,1}\s*`, tag)
|
||||
return strings.TrimSpace(match[2]), strings.TrimSpace(match[3]), strings.TrimSpace(match[5])
|
||||
}
|
||||
|
||||
@ -21,7 +21,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
gSINGLE_RULE_PATTERN = `^([\w-]+):{0,1}(.*)` // 单条规则匹配正则
|
||||
// 单条规则匹配正则
|
||||
gSINGLE_RULE_PATTERN = `^([\w-]+):{0,1}(.*)`
|
||||
)
|
||||
|
||||
var (
|
||||
@ -113,6 +114,9 @@ var (
|
||||
//
|
||||
// 3. params参数为联合校验参数,支持任意的map/struct/*struct类型,对于需要联合校验的规则有效,如:required-*、same、different;
|
||||
func Check(value interface{}, rules string, msgs interface{}, params ...interface{}) *Error {
|
||||
if rules == "" {
|
||||
return nil
|
||||
}
|
||||
// 内部会将参数全部转换为字符串类型进行校验
|
||||
val := strings.TrimSpace(gconv.String(value))
|
||||
data := make(map[string]string)
|
||||
|
||||
@ -112,6 +112,11 @@ func (e *Error) String() string {
|
||||
return strings.Join(e.Strings(), "; ")
|
||||
}
|
||||
|
||||
// Error implements interface of error.Error.
|
||||
func (e *Error) Error() string {
|
||||
return e.String()
|
||||
}
|
||||
|
||||
// 只返回错误信息,构造成字符串数组返回
|
||||
func (e *Error) Strings() (errs []string) {
|
||||
errs = make([]string, 0)
|
||||
|
||||
Reference in New Issue
Block a user