-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2651 from astaxie/develop
v1.8.3
- Loading branch information
Showing
30 changed files
with
1,065 additions
and
116 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package param | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
|
||
beecontext "github.com/astaxie/beego/context" | ||
"github.com/astaxie/beego/logs" | ||
) | ||
|
||
// ConvertParams converts http method params to values that will be passed to the method controller as arguments | ||
func ConvertParams(methodParams []*MethodParam, methodType reflect.Type, ctx *beecontext.Context) (result []reflect.Value) { | ||
result = make([]reflect.Value, 0, len(methodParams)) | ||
for i := 0; i < len(methodParams); i++ { | ||
reflectValue := convertParam(methodParams[i], methodType.In(i), ctx) | ||
result = append(result, reflectValue) | ||
} | ||
return | ||
} | ||
|
||
func convertParam(param *MethodParam, paramType reflect.Type, ctx *beecontext.Context) (result reflect.Value) { | ||
paramValue := getParamValue(param, ctx) | ||
if paramValue == "" { | ||
if param.required { | ||
ctx.Abort(400, fmt.Sprintf("Missing parameter %s", param.name)) | ||
} else { | ||
paramValue = param.defaultValue | ||
} | ||
} | ||
|
||
reflectValue, err := parseValue(param, 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.in { | ||
case body: | ||
return string(ctx.Input.RequestBody) | ||
case header: | ||
return ctx.Input.Header(param.name) | ||
case path: | ||
return ctx.Input.Query(":" + param.name) | ||
default: | ||
return ctx.Input.Query(param.name) | ||
} | ||
} | ||
|
||
func parseValue(param *MethodParam, paramValue string, paramType reflect.Type) (result reflect.Value, err error) { | ||
if paramValue == "" { | ||
return reflect.Zero(paramType), nil | ||
} | ||
parser := getParser(param, paramType) | ||
value, err := parser.parse(paramValue, paramType) | ||
if err != nil { | ||
return result, err | ||
} | ||
|
||
return safeConvert(reflect.ValueOf(value), paramType) | ||
} | ||
|
||
func safeConvert(value reflect.Value, t reflect.Type) (result reflect.Value, err error) { | ||
defer func() { | ||
if r := recover(); r != nil { | ||
var ok bool | ||
err, ok = r.(error) | ||
if !ok { | ||
err = fmt.Errorf("%v", r) | ||
} | ||
} | ||
}() | ||
result = value.Convert(t) | ||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package param | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
) | ||
|
||
//MethodParam keeps param information to be auto passed to controller methods | ||
type MethodParam struct { | ||
name string | ||
in paramType | ||
required bool | ||
defaultValue string | ||
} | ||
|
||
type paramType byte | ||
|
||
const ( | ||
param paramType = iota | ||
path | ||
body | ||
header | ||
) | ||
|
||
//New creates a new MethodParam with name and specific options | ||
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} | ||
for _, option := range opts { | ||
option(param) | ||
} | ||
return | ||
} | ||
|
||
//Make creates an array of MethodParmas or an empty array | ||
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.in { | ||
case path: | ||
options = append(options, "param.InPath") | ||
case body: | ||
options = append(options, "param.InBody") | ||
case header: | ||
options = append(options, "param.InHeader") | ||
} | ||
if mp.defaultValue != "" { | ||
options = append(options, fmt.Sprintf(`param.Default("%s")`, mp.defaultValue)) | ||
} | ||
if len(options) > 0 { | ||
result += ", " | ||
} | ||
result += strings.Join(options, ", ") | ||
result += ")" | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package param | ||
|
||
import ( | ||
"fmt" | ||
) | ||
|
||
// MethodParamOption defines a func which apply options on a MethodParam | ||
type MethodParamOption func(*MethodParam) | ||
|
||
// IsRequired indicates that this param is required and can not be ommited from the http request | ||
var IsRequired MethodParamOption = func(p *MethodParam) { | ||
p.required = true | ||
} | ||
|
||
// InHeader indicates that this param is passed via an http header | ||
var InHeader MethodParamOption = func(p *MethodParam) { | ||
p.in = header | ||
} | ||
|
||
// InPath indicates that this param is part of the URL path | ||
var InPath MethodParamOption = func(p *MethodParam) { | ||
p.in = path | ||
} | ||
|
||
// InBody indicates that this param is passed as an http request body | ||
var InBody MethodParamOption = func(p *MethodParam) { | ||
p.in = body | ||
} | ||
|
||
// Default provides a default value for the http param | ||
func Default(defaultValue interface{}) MethodParamOption { | ||
return func(p *MethodParam) { | ||
if defaultValue != nil { | ||
p.defaultValue = fmt.Sprint(defaultValue) | ||
} | ||
} | ||
} |
Oops, something went wrong.