20 Star 164 Fork 26

qiqi / orange

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
request.go 6.46 KB
一键复制 编辑 原始数据 按行查看 历史
qiqi 提交于 2021-01-11 20:04 . 默认去除首尾空格优化
package app
import (
"encoding/json"
"fmt"
"gitee.com/zhucheer/orange/cfg"
"net/url"
"reflect"
"strconv"
"strings"
"time"
)
const (
formatTime = "15:04:05"
formatDate = "2006-01-02"
formatDateTime = "2006-01-02 15:04:05"
formatDateTimeT = "2006-01-02T15:04:05"
)
var sliceOfInts = reflect.TypeOf([]int(nil))
var sliceOfStrings = reflect.TypeOf([]string(nil))
var maxBodySize int64 = 10240
func initRequest() {
maxBodySize = cfg.GetInt64("app.maxBody", cfg.ConfigDef.GetInt64("app.maxBody"))
}
// Input returns the input data map from POST or PUT request body and query string.
func (c *Context) Input() url.Values {
if c.request.Form == nil {
c.OrangeInput.ParseFormOrMulitForm(maxBodySize)
}
return c.request.Form
}
// ParseForm maps input data map to obj struct.
func (c *Context) ParseForm(obj interface{}) error {
// if body is empty do not return error, nothing to do.
if c.request.Method == "GET" && len(c.Input()) == 0 {
return nil
}
if c.request.Method != "GET" && len(c.OrangeInput.FormBody) == 0 {
return nil
}
contextType := c.request.Header.Get("Content-Type")
if strings.Contains(contextType, "application/json") && c.request.Method != "GET" {
return ParseJson(c.OrangeInput.FormBody, obj)
} else {
return ParseForm(c.Input(), obj)
}
}
// ShouldBind is an alias for ParseForm
func (c *Context) ShouldBind(obj interface{}) error {
return c.ParseForm(obj)
}
func ParseJson(jsonByte []byte, obj interface{}) error {
err := json.Unmarshal(jsonByte, obj)
if err != nil {
return err
}
objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj)
if !isStructPtr(objT) {
return fmt.Errorf("%v must be a struct pointer", obj)
}
objT = objT.Elem()
objV = objV.Elem()
return parseJsonStructValue(objT, objV)
}
// ParseForm will parse form values to struct via tag.
func ParseForm(form url.Values, obj interface{}) error {
objT := reflect.TypeOf(obj)
objV := reflect.ValueOf(obj)
if !isStructPtr(objT) {
return fmt.Errorf("%v must be a struct pointer", obj)
}
objT = objT.Elem()
objV = objV.Elem()
return parseFormToStruct(form, objT, objV)
}
func isStructPtr(t reflect.Type) bool {
return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
}
// ParseForm will parse form values to struct via tag.
// Support for anonymous struct.
func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) error {
for i := 0; i < objT.NumField(); i++ {
fieldV := objV.Field(i)
if !fieldV.CanSet() {
continue
}
fieldT := objT.Field(i)
if fieldT.Anonymous && fieldT.Type.Kind() == reflect.Struct {
err := parseFormToStruct(form, fieldT.Type, fieldV)
if err != nil {
return err
}
continue
}
tags := strings.Split(fieldT.Tag.Get("json"), ",")
exprs := strings.Split(fieldT.Tag.Get("expr"), ",")
var tag string
if len(tags) == 0 || len(tags[0]) == 0 {
tag = fieldT.Name
} else if tags[0] == "-" {
continue
} else {
tag = tags[0]
}
value := form.Get(tag)
if len(value) == 0 {
continue
}
value = exprValue(exprs, value)
switch fieldT.Type.Kind() {
case reflect.Bool:
if strings.ToLower(value) == "on" || strings.ToLower(value) == "1" || strings.ToLower(value) == "yes" {
fieldV.SetBool(true)
continue
}
if strings.ToLower(value) == "off" || strings.ToLower(value) == "0" || strings.ToLower(value) == "no" {
fieldV.SetBool(false)
continue
}
b, err := strconv.ParseBool(value)
if err != nil {
return err
}
fieldV.SetBool(b)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
x, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
fieldV.SetInt(x)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
x, err := strconv.ParseUint(value, 10, 64)
if err != nil {
return err
}
fieldV.SetUint(x)
case reflect.Float32, reflect.Float64:
x, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
fieldV.SetFloat(x)
case reflect.Interface:
fieldV.Set(reflect.ValueOf(value))
case reflect.String:
fieldV.SetString(value)
case reflect.Struct:
switch fieldT.Type.String() {
case "time.Time":
var (
t time.Time
err error
)
if len(value) >= 25 {
value = value[:25]
t, err = time.ParseInLocation(time.RFC3339, value, time.Local)
} else if len(value) >= 19 {
if strings.Contains(value, "T") {
value = value[:19]
t, err = time.ParseInLocation(formatDateTimeT, value, time.Local)
} else {
value = value[:19]
t, err = time.ParseInLocation(formatDateTime, value, time.Local)
}
} else if len(value) >= 10 {
if len(value) > 10 {
value = value[:10]
}
t, err = time.ParseInLocation(formatDate, value, time.Local)
} else if len(value) >= 8 {
if len(value) > 8 {
value = value[:8]
}
t, err = time.ParseInLocation(formatTime, value, time.Local)
}
if err != nil {
return err
}
fieldV.Set(reflect.ValueOf(t))
}
case reflect.Slice:
if fieldT.Type == sliceOfInts {
formVals := form[tag]
fieldV.Set(reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf(int(1))), len(formVals), len(formVals)))
for i := 0; i < len(formVals); i++ {
val, err := strconv.Atoi(formVals[i])
if err != nil {
return err
}
fieldV.Index(i).SetInt(int64(val))
}
} else if fieldT.Type == sliceOfStrings {
formVals := form[tag]
fieldV.Set(reflect.MakeSlice(reflect.SliceOf(reflect.TypeOf("")), len(formVals), len(formVals)))
for i := 0; i < len(formVals); i++ {
fieldV.Index(i).SetString(formVals[i])
}
}
}
}
return nil
}
func parseJsonStructValue(objT reflect.Type, objV reflect.Value) error {
for i := 0; i < objT.NumField(); i++ {
fieldV := objV.Field(i)
if !fieldV.CanSet() {
continue
}
fieldT := objT.Field(i)
if fieldT.Type.Kind() == reflect.Struct {
err := parseJsonStructValue(fieldT.Type, fieldV)
if err != nil {
return err
}
continue
}
exprs := strings.Split(fieldT.Tag.Get("expr"), ",")
value := fieldV.String()
if len(value) == 0 {
continue
}
value = exprValue(exprs, value)
switch fieldT.Type.Kind() {
case reflect.String:
fieldV.SetString(value)
}
}
return nil
}
// exprValue 标签表达式对参数进行处理
func exprValue(exprs []string, value string) (ret string) {
for _, expr := range exprs {
switch expr {
case "notrim":
ret = value
default:
ret = strings.Trim(value, " ")
}
}
return ret
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/zhucheer/orange.git
git@gitee.com:zhucheer/orange.git
zhucheer
orange
orange
v0.3.3

搜索帮助

344bd9b3 5694891 D2dac590 5694891