2017-12-16 05:38:28 +01:00
package mvc
2017-12-04 04:08:05 +01:00
import (
"reflect"
"github.com/kataras/iris/context"
"github.com/kataras/iris/core/memstore"
"github.com/kataras/iris/core/router/macro"
"github.com/kataras/iris/core/router/macro/interpreter/ast"
)
2017-12-10 06:00:51 +01:00
// for methods inside a controller.
2017-12-04 04:08:05 +01:00
func getPathParamsForInput ( params [ ] macro . TemplateParam , funcIn ... reflect . Type ) ( values [ ] reflect . Value ) {
if len ( funcIn ) == 0 || len ( params ) == 0 {
return
}
2017-12-16 05:38:28 +01:00
consumedParams := make ( map [ int ] bool , 0 )
for _ , in := range funcIn {
for j , p := range params {
if _ , consumed := consumedParams [ j ] ; consumed {
continue
}
paramType := p . Type
paramName := p . Name
// fmt.Printf("%s input arg type vs %s param type\n", in.Kind().String(), p.Type.Kind().String())
if paramType . Assignable ( in . Kind ( ) ) {
consumedParams [ j ] = true
2017-12-16 16:57:20 +01:00
// fmt.Printf("param.go: bind path param func for paramName = '%s' and paramType = '%s'\n", paramName, paramType.String())
2017-12-16 05:38:28 +01:00
values = append ( values , makeFuncParamGetter ( paramType , paramName ) )
}
2017-12-10 06:00:51 +01:00
}
}
2017-12-04 04:08:05 +01:00
2017-12-10 06:00:51 +01:00
return
}
2017-12-04 04:08:05 +01:00
2017-12-10 06:00:51 +01:00
func makeFuncParamGetter ( paramType ast . ParamType , paramName string ) reflect . Value {
var fn interface { }
2017-12-04 04:08:05 +01:00
2017-12-10 06:00:51 +01:00
switch paramType {
case ast . ParamTypeInt :
fn = func ( ctx context . Context ) int {
v , _ := ctx . Params ( ) . GetInt ( paramName )
return v
}
case ast . ParamTypeLong :
fn = func ( ctx context . Context ) int64 {
v , _ := ctx . Params ( ) . GetInt64 ( paramName )
return v
}
case ast . ParamTypeBoolean :
fn = func ( ctx context . Context ) bool {
v , _ := ctx . Params ( ) . GetBool ( paramName )
return v
}
default :
// string, path...
fn = func ( ctx context . Context ) string {
return ctx . Params ( ) . Get ( paramName )
2017-12-04 04:08:05 +01:00
}
}
2017-12-10 06:00:51 +01:00
return reflect . ValueOf ( fn )
2017-12-04 04:08:05 +01:00
}
2017-12-10 06:00:51 +01:00
// for raw handlers, independent of a controller.
2017-12-04 04:08:05 +01:00
// PathParams is the context's named path parameters, see `PathParamsBinder` too.
type PathParams = context . RequestParams
// PathParamsBinder is the binder which will bind the `PathParams` type value to the specific
// handler's input argument, see `PathParams` as well.
func PathParamsBinder ( ctx context . Context ) PathParams {
return * ctx . Params ( )
}
// PathParam describes a named path parameter, it's the result of the PathParamBinder and the expected
// handler func's input argument's type, see `PathParamBinder` too.
type PathParam struct {
memstore . Entry
Empty bool
}
// PathParamBinder is the binder which binds a handler func's input argument to a named path parameter
// based on its name, see `PathParam` as well.
func PathParamBinder ( name string ) func ( ctx context . Context ) PathParam {
return func ( ctx context . Context ) PathParam {
e , found := ctx . Params ( ) . GetEntry ( name )
if ! found {
// useless check here but it doesn't hurt,
// useful only when white-box tests run.
if ctx . Application ( ) != nil {
ctx . Application ( ) . Logger ( ) . Warnf ( ctx . HandlerName ( ) + ": expected parameter name '%s' to be described in the route's path in order to be received by the `ParamBinder`, please fix it.\n The main handler will not be executed for your own protection." , name )
}
ctx . StopExecution ( )
return PathParam {
Empty : true ,
}
}
return PathParam { e , false }
}
}