mirror of
https://github.com/astaxie/beego.git
synced 2025-07-15 01:01:03 +00:00
all types working + controller comments generation
This commit is contained in:
@ -9,39 +9,51 @@ import (
|
||||
)
|
||||
|
||||
func convertParam(param *MethodParam, paramType reflect.Type, ctx *beecontext.Context) (result reflect.Value) {
|
||||
var strValue string
|
||||
var reflectValue reflect.Value
|
||||
switch param.location {
|
||||
case body:
|
||||
strValue = string(ctx.Input.RequestBody)
|
||||
case header:
|
||||
strValue = ctx.Input.Header(param.name)
|
||||
default:
|
||||
strValue = ctx.Input.Query(param.name)
|
||||
}
|
||||
|
||||
if strValue == "" {
|
||||
paramValue := getParamValue(param, ctx)
|
||||
if paramValue == "" {
|
||||
if param.required {
|
||||
ctx.Abort(400, fmt.Sprintf("Missing parameter %s", param.name))
|
||||
} else {
|
||||
strValue = param.defValue
|
||||
paramValue = param.defValue
|
||||
}
|
||||
}
|
||||
if strValue == "" {
|
||||
reflectValue = reflect.Zero(paramType)
|
||||
|
||||
reflectValue, err := parseValue(paramValue, paramType)
|
||||
if err != nil {
|
||||
logs.Debug(fmt.Sprintf("Error converting param %s to type %s. Value: %v, Error: %s", param.name, paramType, paramValue, err))
|
||||
ctx.Abort(400, fmt.Sprintf("Invalid parameter %s. Can not convert %v to type %s", param.name, paramValue, paramType))
|
||||
}
|
||||
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
func getParamValue(param *MethodParam, ctx *beecontext.Context) string {
|
||||
switch param.location {
|
||||
case body:
|
||||
return string(ctx.Input.RequestBody)
|
||||
case header:
|
||||
return ctx.Input.Header(param.name)
|
||||
// if strValue == "" && strings.Contains(param.name, "_") { //magically handle X-Headers?
|
||||
// strValue = ctx.Input.Header(strings.Replace(param.name, "_", "-", -1))
|
||||
// }
|
||||
case path:
|
||||
return ctx.Input.Query(":" + param.name)
|
||||
default:
|
||||
return ctx.Input.Query(param.name)
|
||||
}
|
||||
}
|
||||
|
||||
func parseValue(paramValue string, paramType reflect.Type) (result reflect.Value, err error) {
|
||||
if paramValue == "" {
|
||||
return reflect.Zero(paramType), nil
|
||||
} else {
|
||||
value, err := param.parser.parse(strValue, paramType)
|
||||
value, err := parse(paramValue, paramType)
|
||||
if err != nil {
|
||||
logs.Debug(fmt.Sprintf("Error converting param %s to type %s. Value: %s, Error: %s", param.name, paramType, strValue, err))
|
||||
ctx.Abort(400, fmt.Sprintf("Invalid parameter %s. Can not convert %s to type %s", param.name, strValue, paramType))
|
||||
return result, err
|
||||
}
|
||||
|
||||
reflectValue, err = safeConvert(reflect.ValueOf(value), paramType)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return safeConvert(reflect.ValueOf(value), paramType)
|
||||
}
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
func ConvertParams(methodParams []*MethodParam, methodType reflect.Type, ctx *beecontext.Context) (result []reflect.Value) {
|
||||
|
@ -1,9 +1,13 @@
|
||||
package param
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//Keeps param information to be auto passed to controller methods
|
||||
type MethodParam struct {
|
||||
name string
|
||||
parser paramParser
|
||||
location paramLocation
|
||||
required bool
|
||||
defValue string
|
||||
@ -13,45 +17,51 @@ type paramLocation byte
|
||||
|
||||
const (
|
||||
param paramLocation = iota
|
||||
path
|
||||
body
|
||||
header
|
||||
)
|
||||
|
||||
type MethodParamOption func(*MethodParam)
|
||||
|
||||
func Bool(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, boolParser{}, opts)
|
||||
}
|
||||
|
||||
func String(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, stringParser{}, opts)
|
||||
}
|
||||
|
||||
func Int(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, intParser{}, opts)
|
||||
}
|
||||
|
||||
func Float(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, floatParser{}, opts)
|
||||
}
|
||||
|
||||
func Time(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, timeParser{}, opts)
|
||||
}
|
||||
|
||||
func Json(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, jsonParser{}, opts)
|
||||
}
|
||||
|
||||
func AsSlice(param *MethodParam) *MethodParam {
|
||||
param.parser = sliceParser(param.parser)
|
||||
return param
|
||||
func New(name string, opts ...MethodParamOption) *MethodParam {
|
||||
return newParam(name, nil, opts)
|
||||
}
|
||||
|
||||
func newParam(name string, parser paramParser, opts []MethodParamOption) (param *MethodParam) {
|
||||
param = &MethodParam{name: name, parser: parser}
|
||||
param = &MethodParam{name: name}
|
||||
for _, option := range opts {
|
||||
option(param)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Make(list ...*MethodParam) []*MethodParam {
|
||||
if len(list) > 0 {
|
||||
return list
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (mp *MethodParam) String() string {
|
||||
options := []string{}
|
||||
result := "param.New(\"" + mp.name + "\""
|
||||
if mp.required {
|
||||
options = append(options, "param.IsRequired")
|
||||
}
|
||||
switch mp.location {
|
||||
case path:
|
||||
options = append(options, "param.InPath")
|
||||
case body:
|
||||
options = append(options, "param.InBody")
|
||||
case header:
|
||||
options = append(options, "param.InHeader")
|
||||
}
|
||||
if mp.defValue != "" {
|
||||
options = append(options, fmt.Sprintf(`param.Default("%s")`, mp.defValue))
|
||||
}
|
||||
if len(options) > 0 {
|
||||
result += ", "
|
||||
}
|
||||
result += strings.Join(options, ", ")
|
||||
result += ")"
|
||||
return result
|
||||
}
|
||||
|
@ -4,6 +4,8 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type MethodParamOption func(*MethodParam)
|
||||
|
||||
var IsRequired MethodParamOption = func(p *MethodParam) {
|
||||
p.required = true
|
||||
}
|
||||
@ -12,6 +14,10 @@ var InHeader MethodParamOption = func(p *MethodParam) {
|
||||
p.location = header
|
||||
}
|
||||
|
||||
var InPath MethodParamOption = func(p *MethodParam) {
|
||||
p.location = path
|
||||
}
|
||||
|
||||
var InBody MethodParamOption = func(p *MethodParam) {
|
||||
p.location = body
|
||||
}
|
||||
|
@ -12,6 +12,45 @@ type paramParser interface {
|
||||
parse(value string, toType reflect.Type) (interface{}, error)
|
||||
}
|
||||
|
||||
func parse(value string, t reflect.Type) (interface{}, error) {
|
||||
parser := getParser(t)
|
||||
return parser.parse(value, t)
|
||||
}
|
||||
|
||||
func getParser(t reflect.Type) paramParser {
|
||||
switch t.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
return intParser{}
|
||||
case reflect.Slice:
|
||||
if t.Elem().Kind() == reflect.Uint8 { //treat []byte as string
|
||||
return stringParser{}
|
||||
}
|
||||
elemParser := getParser(t.Elem())
|
||||
if elemParser == (jsonParser{}) {
|
||||
return elemParser
|
||||
}
|
||||
return sliceParser(elemParser)
|
||||
case reflect.Bool:
|
||||
return boolParser{}
|
||||
case reflect.String:
|
||||
return stringParser{}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return floatParser{}
|
||||
case reflect.Ptr:
|
||||
elemParser := getParser(t.Elem())
|
||||
if elemParser == (jsonParser{}) {
|
||||
return elemParser
|
||||
}
|
||||
return ptrParser(elemParser)
|
||||
default:
|
||||
if t.PkgPath() == "time" && t.Name() == "Time" {
|
||||
return timeParser{}
|
||||
}
|
||||
return jsonParser{}
|
||||
}
|
||||
}
|
||||
|
||||
type parserFunc func(value string, toType reflect.Type) (interface{}, error)
|
||||
|
||||
func (f parserFunc) parse(value string, toType reflect.Type) (interface{}, error) {
|
||||
@ -92,3 +131,21 @@ func sliceParser(elemParser paramParser) paramParser {
|
||||
return result.Interface(), nil
|
||||
})
|
||||
}
|
||||
|
||||
func ptrParser(elemParser paramParser) paramParser {
|
||||
return parserFunc(func(value string, toType reflect.Type) (interface{}, error) {
|
||||
parsedValue, err := elemParser.parse(value, toType.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
newValPtr := reflect.New(toType.Elem())
|
||||
newVal := reflect.Indirect(newValPtr)
|
||||
convertedVal, err := safeConvert(reflect.ValueOf(parsedValue), toType.Elem())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newVal.Set(convertedVal)
|
||||
return newValPtr.Interface(), nil
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user