代码拉取完成,页面将自动刷新
package app
import (
"encoding/json"
"errors"
"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 = 32 << 20 // 32 MB
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, error) {
maxInput := maxBodySize
if maxInput < 0 {
maxInput = c.request.ContentLength
}
var err error
if c.request.Form == nil {
err = c.OrangeInput.ParseFormOrMulitForm(maxInput)
}
return c.request.Form, err
}
// 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.
input, err := c.Input()
if c.request.Method == "GET" && len(input) == 0 {
return err
}
if c.request.Method != "GET" && len(c.OrangeInput.FormBody) == 0 {
return err
}
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(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
}
var err error
value, err = exprValue(exprs, value)
if err != nil {
return errors.New(fieldT.Name + " " + err.Error())
}
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
}
var err error
value, err = exprValue(exprs, value)
if err != nil {
return errors.New(fieldT.Name + " " + err.Error())
}
switch fieldT.Type.Kind() {
case reflect.String:
fieldV.SetString(value)
}
}
return nil
}
// exprValue 标签表达式对参数进行处理
func exprValue(exprs []string, value string) (ret string, err error) {
for _, expr := range exprs {
switch expr {
case "notrim":
ret = value
default:
ret = strings.Trim(value, " ")
}
if strings.Contains(expr, "len:") {
size, _ := strconv.Atoi(expr[4:])
if size > 0 && len(ret) > size {
ret = ret[:size]
}
}
}
return ret, err
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。