mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
Conversion once at macros and their functions, internal changes required
Former-commit-id: 7b778cccfb7c0e30ca5e8106017ada065993aba5
This commit is contained in:
parent
dc3c38b189
commit
d6d27b2605
|
@ -114,7 +114,7 @@ func main() {
|
|||
| Param Type | Go Type | Validation | Retrieve Helper |
|
||||
| -----------------|------|-------------|------|
|
||||
| `:string` | string | anything | `Params().Get` |
|
||||
| `:number` | uint, uint8, uint16, uint32, uint64, int, int8, int32, int64 | positive or negative number, any number of digits | `Params().GetInt/Int64`...|
|
||||
| `:int` | uint, uint8, uint16, uint32, uint64, int, int8, int32, int64 | positive or negative number, depends on the arch | `Params().GetInt`...|
|
||||
| `:int64` | int64 | -9223372036854775808 to 9223372036854775807 | `Params().GetInt64` |
|
||||
| `:uint8` | uint8 | 0 to 255 | `Params().GetUint8` |
|
||||
| `:uint64` | uint64 | 0 to 18446744073709551615 | `Params().GetUint64` |
|
||||
|
@ -127,7 +127,7 @@ func main() {
|
|||
|
||||
```go
|
||||
app.Get("/users/{id:uint64}", func(ctx iris.Context){
|
||||
id, _ := ctx.Params().GetUint64("id")
|
||||
id := ctx.Params().GetUint64Default("id", 0)
|
||||
// [...]
|
||||
})
|
||||
```
|
||||
|
@ -226,7 +226,7 @@ func main() {
|
|||
// but will not match /users/-1 because uint should be bigger than zero
|
||||
// neither /users or /users/.
|
||||
app.Get("/users/{id:uint64}", func(ctx iris.Context) {
|
||||
id, _ := ctx.Params().GetUint64("id")
|
||||
id := ctx.Params().GetUint64Default("id", 0)
|
||||
ctx.Writef("User with ID: %d", id)
|
||||
})
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package main
|
|||
|
||||
import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
)
|
||||
|
@ -122,17 +121,12 @@ func main() {
|
|||
// Let's register our first macro attached to uint64 macro type.
|
||||
// "min" = the function
|
||||
// "minValue" = the argument of the function
|
||||
// func(string) bool = the macro's path parameter evaluator, this executes in serve time when
|
||||
// func(uint64) bool = our func's evaluator, this executes in serve time when
|
||||
// a user requests a path which contains the :uint64 macro parameter type with the min(...) macro parameter function.
|
||||
app.Macros().Uint64.RegisterFunc("min", func(minValue uint64) func(string) bool {
|
||||
// do anything before serve here [...]
|
||||
// at this case we don't need to do anything
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= minValue
|
||||
app.Macros().Get("uint64").RegisterFunc("min", func(minValue uint64) func(uint64) bool {
|
||||
// type of "paramValue" should match the type of the internal macro's evaluator function, which in this case is "uint64".
|
||||
return func(paramValue uint64) bool {
|
||||
return paramValue >= minValue
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -142,14 +136,14 @@ func main() {
|
|||
app.Get("/profile/{id:uint64 min(20)}", func(ctx iris.Context) {
|
||||
// second parameter is the error but it will always nil because we use macros,
|
||||
// the validaton already happened.
|
||||
id, _ := ctx.Params().GetInt("id")
|
||||
id := ctx.Params().GetUint64Default("id", 0)
|
||||
ctx.Writef("Hello id: %d", id)
|
||||
})
|
||||
|
||||
// to change the error code per route's macro evaluator:
|
||||
app.Get("/profile/{id:uint64 min(1)}/friends/{friendid:uint64 min(1) else 504}", func(ctx iris.Context) {
|
||||
id, _ := ctx.Params().GetInt("id") // or GetUint64.
|
||||
friendid, _ := ctx.Params().GetInt("friendid")
|
||||
id := ctx.Params().GetUint64Default("id", 0)
|
||||
friendid := ctx.Params().GetUint64Default("friendid", 0)
|
||||
ctx.Writef("Hello id: %d looking for friend id: ", id, friendid)
|
||||
}) // this will throw e 504 error code instead of 404 if all route's macros not passed.
|
||||
|
||||
|
@ -169,7 +163,7 @@ func main() {
|
|||
}
|
||||
|
||||
// MatchString is a type of func(string) bool, so we use it as it is.
|
||||
app.Macros().String.RegisterFunc("coordinate", latLonRegex.MatchString)
|
||||
app.Macros().Get("string").RegisterFunc("coordinate", latLonRegex.MatchString)
|
||||
|
||||
app.Get("/coordinates/{lat:string coordinate() else 502}/{lon:string coordinate() else 502}", func(ctx iris.Context) {
|
||||
ctx.Writef("Lat: %s | Lon: %s", ctx.Params().Get("lat"), ctx.Params().Get("lon"))
|
||||
|
@ -178,7 +172,7 @@ func main() {
|
|||
//
|
||||
|
||||
// Another one is by using a custom body.
|
||||
app.Macros().String.RegisterFunc("range", func(minLength, maxLength int) func(string) bool {
|
||||
app.Macros().Get("string").RegisterFunc("range", func(minLength, maxLength int) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return len(paramValue) >= minLength && len(paramValue) <= maxLength
|
||||
}
|
||||
|
@ -193,7 +187,7 @@ func main() {
|
|||
//
|
||||
|
||||
// Register your custom macro function which accepts a slice of strings `[...,...]`.
|
||||
app.Macros().String.RegisterFunc("has", func(validNames []string) func(string) bool {
|
||||
app.Macros().Get("string").RegisterFunc("has", func(validNames []string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
for _, validName := range validNames {
|
||||
if validName == paramValue {
|
||||
|
|
|
@ -16,37 +16,49 @@ func main() {
|
|||
app.Logger().SetLevel("debug")
|
||||
|
||||
// Let's see how we can register a custom macro such as ":uint32" or ":small" for its alias (optionally) for Uint32 types.
|
||||
app.Macros().Register("uint32", "small", false, false, func(paramValue string) bool {
|
||||
_, err := strconv.ParseUint(paramValue, 10, 32)
|
||||
return err == nil
|
||||
}).
|
||||
RegisterFunc("min", func(min uint32) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 32)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// app.Macros().Register("uint32", "small", false, false, func(paramValue string) bool {
|
||||
// _, err := strconv.ParseUint(paramValue, 10, 32)
|
||||
// return err == nil
|
||||
// }).
|
||||
// RegisterFunc("min", func(min uint32) func(string) bool {
|
||||
// return func(paramValue string) bool {
|
||||
// n, err := strconv.ParseUint(paramValue, 10, 32)
|
||||
// if err != nil {
|
||||
// return false
|
||||
// }
|
||||
|
||||
return uint32(n) >= min
|
||||
}
|
||||
})
|
||||
// return uint32(n) >= min
|
||||
// }
|
||||
// })
|
||||
|
||||
/* TODO:
|
||||
somehow define one-time how the parameter should be parsed to a particular type (go std or custom)
|
||||
tip: we can change the original value from string to X using the entry's.ValueRaw
|
||||
^ Done 27 sep 2018.
|
||||
*/
|
||||
|
||||
app.Macros().Register("uint32", "small", false, false, func(paramValue string) (interface{}, bool) {
|
||||
v, err := strconv.ParseUint(paramValue, 10, 32)
|
||||
return uint32(v), err == nil
|
||||
}).
|
||||
RegisterFunc("min", func(min uint32) func(uint32) bool {
|
||||
return func(paramValue uint32) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
})
|
||||
|
||||
// optionally, only when mvc or hero features are used for this custom macro/parameter type.
|
||||
context.ParamResolvers[reflect.Uint32] = func(paramIndex int) interface{} {
|
||||
// return func(store memstore.Store) uint32 {
|
||||
// param, _ := store.GetEntryAt(paramIndex)
|
||||
/* both works but second is faster, we omit the duplication of the type conversion over and over as of 27 Sep of 2018 (this patch)*/
|
||||
// return func(ctx context.Context) uint32 {
|
||||
// param := ctx.Params().GetEntryAt(paramIndex)
|
||||
// paramValueAsUint32, _ := strconv.ParseUint(param.String(), 10, 32)
|
||||
// return uint32(paramValueAsUint32)
|
||||
// }
|
||||
return func(ctx context.Context) uint32 {
|
||||
param := ctx.Params().GetEntryAt(paramIndex)
|
||||
paramValueAsUint32, _ := strconv.ParseUint(param.String(), 10, 32)
|
||||
return uint32(paramValueAsUint32)
|
||||
}
|
||||
return ctx.Params().GetEntryAt(paramIndex).ValueRaw.(uint32)
|
||||
} /* TODO: find a way to automative it based on the macro's first return value type, if thats the case then we must not return nil even if not found,
|
||||
we must return a value i.e 0 for int for its interface{} */
|
||||
}
|
||||
//
|
||||
|
||||
|
@ -54,11 +66,11 @@ func main() {
|
|||
return fmt.Sprintf("Value of the parameter is: %d\n", paramValue)
|
||||
}))
|
||||
|
||||
app.Get("test_uint64/{myparam:uint64}", handler)
|
||||
app.Get("test_uint64/{myparam:uint64 min(5)}", func(ctx context.Context) {
|
||||
// works: ctx.Writef("Value of the parameter is: %s\n", ctx.Params().Get("myparam"))
|
||||
// but better and faster because the macro converts the string to uint64 automatically:
|
||||
ctx.Writef("Value of the parameter is: %d\n", ctx.Params().GetUint64Default("myparam", 0))
|
||||
})
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
func handler(ctx context.Context) {
|
||||
ctx.Writef("Value of the parameter is: %s\n", ctx.Params().Get("myparam"))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package context
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -33,7 +34,7 @@ func (r *RequestParams) GetEntry(key string) memstore.Entry {
|
|||
// by the key-value params.
|
||||
func (r *RequestParams) Visit(visitor func(key string, value string)) {
|
||||
r.Store.Visit(func(k string, v interface{}) {
|
||||
visitor(k, v.(string)) // always string here.
|
||||
visitor(k, fmt.Sprintf("%v", v)) // always string here.
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package memstore
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -67,11 +68,19 @@ func (e Entry) GetByKindOrNil(k reflect.Kind) interface{} {
|
|||
// If not found returns "def".
|
||||
func (e Entry) StringDefault(def string) string {
|
||||
v := e.ValueRaw
|
||||
if v == nil {
|
||||
return def
|
||||
}
|
||||
|
||||
if vString, ok := v.(string); ok {
|
||||
return vString
|
||||
}
|
||||
|
||||
val := fmt.Sprintf("%v", v)
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
|
||||
return def
|
||||
}
|
||||
|
||||
|
@ -105,6 +114,20 @@ func (e Entry) IntDefault(def int) (int, error) {
|
|||
return val, nil
|
||||
case int:
|
||||
return vv, nil
|
||||
case int8:
|
||||
return int(vv), nil
|
||||
case int32:
|
||||
return int(vv), nil
|
||||
case int64:
|
||||
return int(vv), nil
|
||||
case uint:
|
||||
return int(vv), nil
|
||||
case uint8:
|
||||
return int(vv), nil
|
||||
case uint32:
|
||||
return int(vv), nil
|
||||
case uint64:
|
||||
return int(vv), nil
|
||||
}
|
||||
|
||||
return def, errFindParse.Format("int", e.Key)
|
||||
|
@ -123,6 +146,10 @@ func (e Entry) Int64Default(def int64) (int64, error) {
|
|||
return strconv.ParseInt(vv, 10, 64)
|
||||
case int64:
|
||||
return vv, nil
|
||||
case int32:
|
||||
return int64(vv), nil
|
||||
case int8:
|
||||
return int64(vv), nil
|
||||
case int:
|
||||
return int64(vv), nil
|
||||
}
|
||||
|
@ -151,6 +178,12 @@ func (e Entry) Float64Default(def float64) (float64, error) {
|
|||
return vv, nil
|
||||
case int:
|
||||
return float64(vv), nil
|
||||
case int64:
|
||||
return float64(vv), nil
|
||||
case uint:
|
||||
return float64(vv), nil
|
||||
case uint64:
|
||||
return float64(vv), nil
|
||||
}
|
||||
|
||||
return def, errFindParse.Format("float64", e.Key)
|
||||
|
|
|
@ -3,6 +3,7 @@ package router
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris/context"
|
||||
|
@ -83,24 +84,37 @@ func convertTmplToHandler(tmpl *macro.Template) context.Handler {
|
|||
return func(ctx context.Context) {
|
||||
for _, p := range tmpl.Params {
|
||||
paramValue := ctx.Params().Get(p.Name)
|
||||
// first, check for type evaluator
|
||||
if !p.TypeEvaluator(paramValue) {
|
||||
if p.TypeEvaluator == nil {
|
||||
// allow.
|
||||
ctx.Next()
|
||||
return
|
||||
}
|
||||
|
||||
// first, check for type evaluator.
|
||||
newValue, passed := p.TypeEvaluator(paramValue)
|
||||
if !passed {
|
||||
ctx.StatusCode(p.ErrCode)
|
||||
ctx.StopExecution()
|
||||
return
|
||||
}
|
||||
|
||||
if len(p.Funcs) > 0 {
|
||||
paramIn := []reflect.Value{reflect.ValueOf(newValue)}
|
||||
// then check for all of its functions
|
||||
for _, evalFunc := range p.Funcs {
|
||||
if !evalFunc(paramValue) {
|
||||
// or make it as func(interface{}) bool and pass directly the "newValue"
|
||||
// but that would not be as easy for end-developer, so keep that "slower":
|
||||
if !evalFunc.Call(paramIn)[0].Interface().(bool) { // i.e func(paramValue int) bool
|
||||
ctx.StatusCode(p.ErrCode)
|
||||
ctx.StopExecution()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// if all passed, just continue
|
||||
|
||||
ctx.Params().Store.Set(p.Name, newValue)
|
||||
}
|
||||
// if all passed, just continue.
|
||||
ctx.Next()
|
||||
}
|
||||
}(*tmpl)
|
||||
|
|
|
@ -12,14 +12,51 @@ import (
|
|||
// EvaluatorFunc is the signature for both param types and param funcs.
|
||||
// It should accepts the param's value as string
|
||||
// and return true if validated otherwise false.
|
||||
type EvaluatorFunc func(paramValue string) bool
|
||||
// type EvaluatorFunc func(paramValue string) bool
|
||||
// type BinderFunc func(paramValue string) interface{}
|
||||
|
||||
// NewEvaluatorFromRegexp accepts a regexp "expr" expression
|
||||
// and returns an EvaluatorFunc based on that regexp.
|
||||
// the regexp is compiled before return.
|
||||
type (
|
||||
ParamEvaluator func(paramValue string) (interface{}, bool)
|
||||
// FuncEvaluator interface{} // i.e func(paramValue int) bool
|
||||
)
|
||||
|
||||
var goodEvaluatorFuncs = []reflect.Type{
|
||||
reflect.TypeOf(func(string) (interface{}, bool) { return nil, false }),
|
||||
reflect.TypeOf(ParamEvaluator(func(string) (interface{}, bool) { return nil, false })),
|
||||
}
|
||||
|
||||
func goodParamFunc(typ reflect.Type) bool {
|
||||
if typ.Kind() == reflect.Func { // it should be a func which returns a func (see below check).
|
||||
if typ.NumOut() == 1 {
|
||||
typOut := typ.Out(0)
|
||||
if typOut.Kind() != reflect.Func {
|
||||
return false
|
||||
}
|
||||
|
||||
if typOut.NumOut() == 2 { // if it's a type of EvaluatorFunc, used for param evaluator.
|
||||
for _, fType := range goodEvaluatorFuncs {
|
||||
if typOut == fType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if typOut.NumIn() == 1 && typOut.NumOut() == 1 { // if it's a type of func(paramValue [int,string...]) bool, used for param funcs.
|
||||
return typOut.Out(0).Kind() == reflect.Bool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Regexp accepts a regexp "expr" expression
|
||||
// and returns its MatchString.
|
||||
// The regexp is compiled before return.
|
||||
//
|
||||
// Returns a not-nil error on regexp compile failure.
|
||||
func NewEvaluatorFromRegexp(expr string) (EvaluatorFunc, error) {
|
||||
func Regexp(expr string) (func(string) bool, error) {
|
||||
if expr == "" {
|
||||
return nil, fmt.Errorf("empty regex expression")
|
||||
}
|
||||
|
@ -37,36 +74,16 @@ func NewEvaluatorFromRegexp(expr string) (EvaluatorFunc, error) {
|
|||
return r.MatchString, nil
|
||||
}
|
||||
|
||||
// MustNewEvaluatorFromRegexp same as NewEvaluatorFromRegexp
|
||||
// MustRegexp same as Regexp
|
||||
// but it panics on the "expr" parse failure.
|
||||
func MustNewEvaluatorFromRegexp(expr string) EvaluatorFunc {
|
||||
r, err := NewEvaluatorFromRegexp(expr)
|
||||
func MustRegexp(expr string) func(string) bool {
|
||||
r, err := Regexp(expr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var (
|
||||
goodParamFuncReturnType = reflect.TypeOf(func(string) bool { return false })
|
||||
goodParamFuncReturnType2 = reflect.TypeOf(EvaluatorFunc(func(string) bool { return false }))
|
||||
)
|
||||
|
||||
func goodParamFunc(typ reflect.Type) bool {
|
||||
// should be a func
|
||||
// which returns a func(string) bool
|
||||
if typ.Kind() == reflect.Func {
|
||||
if typ.NumOut() == 1 {
|
||||
typOut := typ.Out(0)
|
||||
if typOut == goodParamFuncReturnType || typOut == goodParamFuncReturnType2 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// goodParamFuncName reports whether the function name is a valid identifier.
|
||||
func goodParamFuncName(name string) bool {
|
||||
if name == "" {
|
||||
|
@ -85,7 +102,7 @@ func goodParamFuncName(name string) bool {
|
|||
|
||||
// the convertBuilderFunc return value is generating at boot time.
|
||||
// convertFunc converts an interface to a valid full param function.
|
||||
func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
|
||||
func convertBuilderFunc(fn interface{}) ParamFuncBuilder {
|
||||
|
||||
typFn := reflect.TypeOf(fn)
|
||||
if !goodParamFunc(typFn) {
|
||||
|
@ -94,7 +111,7 @@ func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
|
|||
|
||||
numFields := typFn.NumIn()
|
||||
|
||||
return func(args []string) EvaluatorFunc {
|
||||
return func(args []string) reflect.Value {
|
||||
if len(args) != numFields {
|
||||
// no variadics support, for now.
|
||||
panic("args should be the same len as numFields")
|
||||
|
@ -179,24 +196,25 @@ func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
|
|||
|
||||
argValue := reflect.ValueOf(val)
|
||||
if expected, got := field.Kind(), argValue.Kind(); expected != got {
|
||||
panic(fmt.Sprintf("fields should have the same type: [%d] expected %s but got %s", i, expected, got))
|
||||
panic(fmt.Sprintf("func's input arguments should have the same type: [%d] expected %s but got %s", i, expected, got))
|
||||
}
|
||||
|
||||
argValues = append(argValues, argValue)
|
||||
}
|
||||
|
||||
evalFn := reflect.ValueOf(fn).Call(argValues)[0].Interface()
|
||||
evalFn := reflect.ValueOf(fn).Call(argValues)[0]
|
||||
|
||||
var evaluator EvaluatorFunc
|
||||
// check for typed and not typed
|
||||
if _v, ok := evalFn.(EvaluatorFunc); ok {
|
||||
evaluator = _v
|
||||
} else if _v, ok = evalFn.(func(string) bool); ok {
|
||||
evaluator = _v
|
||||
}
|
||||
return func(paramValue string) bool {
|
||||
return evaluator(paramValue)
|
||||
}
|
||||
// var evaluator EvaluatorFunc
|
||||
// // check for typed and not typed
|
||||
// if _v, ok := evalFn.(EvaluatorFunc); ok {
|
||||
// evaluator = _v
|
||||
// } else if _v, ok = evalFn.(func(string) bool); ok {
|
||||
// evaluator = _v
|
||||
// }
|
||||
// return func(paramValue interface{}) bool {
|
||||
// return evaluator(paramValue)
|
||||
// }
|
||||
return evalFn
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -218,16 +236,16 @@ type (
|
|||
master bool
|
||||
trailing bool
|
||||
|
||||
Evaluator EvaluatorFunc
|
||||
Evaluator ParamEvaluator
|
||||
funcs []ParamFunc
|
||||
}
|
||||
|
||||
// ParamEvaluatorBuilder is a func
|
||||
// ParamFuncBuilder is a func
|
||||
// which accepts a param function's arguments (values)
|
||||
// and returns an EvaluatorFunc, its job
|
||||
// and returns a function as value, its job
|
||||
// is to make the macros to be registered
|
||||
// by user at the most generic possible way.
|
||||
ParamEvaluatorBuilder func([]string) EvaluatorFunc
|
||||
ParamFuncBuilder func([]string) reflect.Value // the func
|
||||
|
||||
// ParamFunc represents the parsed
|
||||
// parameter function, it holds
|
||||
|
@ -236,13 +254,13 @@ type (
|
|||
// the evaluator func.
|
||||
ParamFunc struct {
|
||||
Name string
|
||||
Func ParamEvaluatorBuilder
|
||||
Func ParamFuncBuilder
|
||||
}
|
||||
)
|
||||
|
||||
// NewMacro creates and returns a Macro that can be used as a registry for
|
||||
// a new customized parameter type and its functions.
|
||||
func NewMacro(indent, alias string, master, trailing bool, evaluator EvaluatorFunc) *Macro {
|
||||
func NewMacro(indent, alias string, master, trailing bool, evaluator ParamEvaluator) *Macro {
|
||||
return &Macro{
|
||||
indent: indent,
|
||||
alias: alias,
|
||||
|
@ -287,7 +305,7 @@ func (m *Macro) RegisterFunc(funcName string, fn interface{}) *Macro {
|
|||
return m
|
||||
}
|
||||
|
||||
func (m *Macro) registerFunc(funcName string, fullFn ParamEvaluatorBuilder) {
|
||||
func (m *Macro) registerFunc(funcName string, fullFn ParamFuncBuilder) {
|
||||
if !goodParamFuncName(funcName) {
|
||||
return
|
||||
}
|
||||
|
@ -305,7 +323,7 @@ func (m *Macro) registerFunc(funcName string, fullFn ParamEvaluatorBuilder) {
|
|||
})
|
||||
}
|
||||
|
||||
func (m *Macro) getFunc(funcName string) ParamEvaluatorBuilder {
|
||||
func (m *Macro) getFunc(funcName string) ParamFuncBuilder {
|
||||
for _, fn := range m.funcs {
|
||||
if fn.Name == funcName {
|
||||
if fn.Func == nil {
|
||||
|
|
|
@ -2,6 +2,7 @@ package macro
|
|||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -64,9 +65,25 @@ func TestGoodParamFuncName(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testEvaluatorRaw(t *testing.T, macroEvaluator *Macro, input string, pass bool, i int) {
|
||||
if got := macroEvaluator.Evaluator(input); pass != got {
|
||||
t.Fatalf("%s - tests[%d] - expecting %v but got %v", t.Name(), i, pass, got)
|
||||
func testEvaluatorRaw(t *testing.T, macroEvaluator *Macro, input string, expectedType reflect.Kind, pass bool, i int) {
|
||||
if macroEvaluator.Evaluator == nil && pass {
|
||||
return // if not evaluator defined then it should allow everything.
|
||||
}
|
||||
value, passed := macroEvaluator.Evaluator(input)
|
||||
if pass != passed {
|
||||
t.Fatalf("%s - tests[%d] - expecting[pass] %v but got %v", t.Name(), i, pass, passed)
|
||||
}
|
||||
|
||||
if !passed {
|
||||
return
|
||||
}
|
||||
|
||||
if value == nil && expectedType != reflect.Invalid {
|
||||
t.Fatalf("%s - tests[%d] - expecting[value] to not be nil", t.Name(), i)
|
||||
}
|
||||
|
||||
if v := reflect.ValueOf(value); v.Kind() != expectedType {
|
||||
t.Fatalf("%s - tests[%d] - expecting[value.Kind] %v but got %v", t.Name(), i, expectedType, v.Kind())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,11 +101,13 @@ func TestStringEvaluatorRaw(t *testing.T) {
|
|||
} // 0
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, String, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, String, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNumberEvaluatorRaw(t *testing.T) {
|
||||
func TestIntEvaluatorRaw(t *testing.T) {
|
||||
x64 := strconv.IntSize == 64
|
||||
|
||||
tests := []struct {
|
||||
pass bool
|
||||
input string
|
||||
|
@ -96,9 +115,9 @@ func TestNumberEvaluatorRaw(t *testing.T) {
|
|||
{false, "astring"}, // 0
|
||||
{false, "astringwith_numb3rS_and_symbol$"}, // 1
|
||||
{true, "32321"}, // 2
|
||||
{true, "18446744073709551615"}, // 3
|
||||
{true, "-18446744073709551615"}, // 4
|
||||
{true, "-18446744073709553213213213213213121615"}, // 5
|
||||
{x64, "9223372036854775807" /*max int64*/}, // 3
|
||||
{x64, "-9223372036854775808" /*min int64 */}, // 4
|
||||
{false, "-18446744073709553213213213213213121615"}, // 5
|
||||
{false, "42 18446744073709551615"}, // 6
|
||||
{false, "--42"}, // 7
|
||||
{false, "+42"}, // 8
|
||||
|
@ -107,7 +126,7 @@ func TestNumberEvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Number, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Int, tt.input, reflect.Int, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,7 +151,7 @@ func TestInt64EvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Int64, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Int64, tt.input, reflect.Int64, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,7 +180,7 @@ func TestUint8EvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Uint8, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Uint8, tt.input, reflect.Uint8, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -186,7 +205,7 @@ func TestUint64EvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Uint64, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Uint64, tt.input, reflect.Uint64, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +222,7 @@ func TestAlphabeticalEvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Alphabetical, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Alphabetical, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +239,7 @@ func TestFileEvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, File, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, File, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -238,7 +257,7 @@ func TestPathEvaluatorRaw(t *testing.T) {
|
|||
}
|
||||
|
||||
for i, tt := range pathTests {
|
||||
testEvaluatorRaw(t, Path, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Path, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -270,8 +289,7 @@ func TestConvertBuilderFunc(t *testing.T) {
|
|||
}
|
||||
|
||||
evalFunc := convertBuilderFunc(fn)
|
||||
|
||||
if !evalFunc([]string{"1", "[name1,name2]"})("ok") {
|
||||
if !evalFunc([]string{"1", "[name1,name2]"}).Call([]reflect.Value{reflect.ValueOf("ok")})[0].Interface().(bool) {
|
||||
t.Fatalf("failed, it should fail already")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,233 +10,205 @@ import (
|
|||
var (
|
||||
// String type
|
||||
// Allows anything (single path segment, as everything except the `Path`).
|
||||
String = NewMacro("string", "", true, false, func(string) bool { return true }).
|
||||
RegisterFunc("regexp", func(expr string) EvaluatorFunc {
|
||||
return MustNewEvaluatorFromRegexp(expr)
|
||||
String = NewMacro("string", "", true, false, nil). // if nil allows everything.
|
||||
RegisterFunc("regexp", func(expr string) func(string) bool {
|
||||
return MustRegexp(expr)
|
||||
}).
|
||||
// checks if param value starts with the 'prefix' arg
|
||||
RegisterFunc("prefix", func(prefix string) EvaluatorFunc {
|
||||
RegisterFunc("prefix", func(prefix string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return strings.HasPrefix(paramValue, prefix)
|
||||
}
|
||||
}).
|
||||
// checks if param value ends with the 'suffix' arg
|
||||
RegisterFunc("suffix", func(suffix string) EvaluatorFunc {
|
||||
RegisterFunc("suffix", func(suffix string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return strings.HasSuffix(paramValue, suffix)
|
||||
}
|
||||
}).
|
||||
// checks if param value contains the 's' arg
|
||||
RegisterFunc("contains", func(s string) EvaluatorFunc {
|
||||
RegisterFunc("contains", func(s string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return strings.Contains(paramValue, s)
|
||||
}
|
||||
}).
|
||||
// checks if param value's length is at least 'min'
|
||||
RegisterFunc("min", func(min int) EvaluatorFunc {
|
||||
RegisterFunc("min", func(min int) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return len(paramValue) >= min
|
||||
}
|
||||
}).
|
||||
// checks if param value's length is not bigger than 'max'
|
||||
RegisterFunc("max", func(max int) EvaluatorFunc {
|
||||
RegisterFunc("max", func(max int) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return max >= len(paramValue)
|
||||
}
|
||||
})
|
||||
|
||||
simpleNumberEvalutator = MustNewEvaluatorFromRegexp("^-?[0-9]+$")
|
||||
// Number or int type
|
||||
// both positive and negative numbers, any number of digits.
|
||||
Number = NewMacro("number", "int", false, false, simpleNumberEvalutator).
|
||||
simpleNumberEval = MustRegexp("^-?[0-9]+$")
|
||||
// Int or int type
|
||||
// both positive and negative numbers, actual value can be min-max int64 or min-max int32 depends on the arch.
|
||||
Int = NewMacro("int", "number", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !simpleNumberEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
v, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return v, true
|
||||
}).
|
||||
// checks if the param value's int representation is
|
||||
// bigger or equal than 'min'
|
||||
RegisterFunc("min", func(min int) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= min
|
||||
RegisterFunc("min", func(min int) func(int) bool {
|
||||
return func(paramValue int) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max int) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n <= max
|
||||
RegisterFunc("max", func(max int) func(int) bool {
|
||||
return func(paramValue int) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max int) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n < min || n > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max int) func(int) bool {
|
||||
return func(paramValue int) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
// Int64 as int64 type
|
||||
// -9223372036854775808 to 9223372036854775807.
|
||||
Int64 = NewMacro("int64", "long", false, false, func(paramValue string) bool {
|
||||
if !simpleNumberEvalutator(paramValue) {
|
||||
return false
|
||||
Int64 = NewMacro("int64", "long", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !simpleNumberEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
_, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
// if err == strconv.ErrRange...
|
||||
return err == nil
|
||||
v, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil { // if err == strconv.ErrRange...
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
}).
|
||||
// checks if the param value's int64 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min int64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= min
|
||||
RegisterFunc("min", func(min int64) func(int64) bool {
|
||||
return func(paramValue int64) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int64 representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max int64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n <= max
|
||||
RegisterFunc("max", func(max int64) func(int64) bool {
|
||||
return func(paramValue int64) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int64 representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max int64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n < min || n > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max int64) func(int64) bool {
|
||||
return func(paramValue int64) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
uint8Eval = MustRegexp("^([0-9]|[1-8][0-9]|9[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
|
||||
// Uint8 as uint8 type
|
||||
// 0 to 255.
|
||||
Uint8 = NewMacro("uint8", "", false, false, MustNewEvaluatorFromRegexp("^([0-9]|[1-8][0-9]|9[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")).
|
||||
// checks if the param value's uint8 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min uint8) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
Uint8 = NewMacro("uint8", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !uint8Eval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return uint8(n) >= min
|
||||
v, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return uint8(v), true
|
||||
}).
|
||||
// checks if the param value's uint8 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min uint8) func(uint8) bool {
|
||||
return func(paramValue uint8) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint8 representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max uint8) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return uint8(n) <= max
|
||||
RegisterFunc("max", func(max uint8) func(uint8) bool {
|
||||
return func(paramValue uint8) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint8 representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max uint8) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if v := uint8(n); v < min || v > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max uint8) func(uint8) bool {
|
||||
return func(paramValue uint8) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
// Uint64 as uint64 type
|
||||
// 0 to 18446744073709551615.
|
||||
Uint64 = NewMacro("uint64", "", false, false, func(paramValue string) bool {
|
||||
if !simpleNumberEvalutator(paramValue) {
|
||||
return false
|
||||
Uint64 = NewMacro("uint64", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !simpleNumberEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
_, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
return err == nil
|
||||
v, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
}).
|
||||
// checks if the param value's uint64 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min uint64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= min
|
||||
RegisterFunc("min", func(min uint64) func(uint64) bool {
|
||||
return func(paramValue uint64) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint64 representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max uint64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n <= max
|
||||
RegisterFunc("max", func(max uint64) func(uint64) bool {
|
||||
return func(paramValue uint64) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint64 representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max uint64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n < min || n > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max uint64) func(uint64) bool {
|
||||
return func(paramValue uint64) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
// Bool or boolean as bool type
|
||||
// a string which is "1" or "t" or "T" or "TRUE" or "true" or "True"
|
||||
// or "0" or "f" or "F" or "FALSE" or "false" or "False".
|
||||
Bool = NewMacro("bool", "boolean", false, false, func(paramValue string) bool {
|
||||
Bool = NewMacro("bool", "boolean", false, false, func(paramValue string) (interface{}, bool) {
|
||||
// a simple if statement is faster than regex ^(true|false|True|False|t|0|f|FALSE|TRUE)$
|
||||
// in this case.
|
||||
_, err := strconv.ParseBool(paramValue)
|
||||
return err == nil
|
||||
v, err := strconv.ParseBool(paramValue)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
})
|
||||
|
||||
alphabeticalEval = MustRegexp("^[a-zA-Z ]+$")
|
||||
// Alphabetical letter type
|
||||
// letters only (upper or lowercase)
|
||||
Alphabetical = NewMacro("alphabetical", "", false, false, MustNewEvaluatorFromRegexp("^[a-zA-Z ]+$"))
|
||||
Alphabetical = NewMacro("alphabetical", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !alphabeticalEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
return paramValue, true
|
||||
})
|
||||
|
||||
fileEval = MustRegexp("^[a-zA-Z0-9_.-]*$")
|
||||
// File type
|
||||
// letters (upper or lowercase)
|
||||
// numbers (0-9)
|
||||
|
@ -244,7 +216,12 @@ var (
|
|||
// dash (-)
|
||||
// point (.)
|
||||
// no spaces! or other character
|
||||
File = NewMacro("file", "", false, false, MustNewEvaluatorFromRegexp("^[a-zA-Z0-9_.-]*$"))
|
||||
File = NewMacro("file", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !fileEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
return paramValue, true
|
||||
})
|
||||
// Path type
|
||||
// anything, should be the last part
|
||||
//
|
||||
|
@ -252,11 +229,11 @@ var (
|
|||
// types because I want to give the opportunity to the user
|
||||
// to organise the macro functions based on wildcard or single dynamic named path parameter.
|
||||
// Should be living in the latest path segment of a route path.
|
||||
Path = NewMacro("path", "", false, true, func(string) bool { return true })
|
||||
Path = NewMacro("path", "", false, true, nil)
|
||||
|
||||
Defaults = &Macros{
|
||||
String,
|
||||
Number,
|
||||
Int,
|
||||
Int64,
|
||||
Uint8,
|
||||
Uint64,
|
||||
|
@ -268,7 +245,7 @@ var (
|
|||
|
||||
type Macros []*Macro
|
||||
|
||||
func (ms *Macros) Register(indent, alias string, isMaster, isTrailing bool, evaluator EvaluatorFunc) *Macro {
|
||||
func (ms *Macros) Register(indent, alias string, isMaster, isTrailing bool, evaluator ParamEvaluator) *Macro {
|
||||
macro := NewMacro(indent, alias, isMaster, isTrailing, evaluator)
|
||||
if ms.register(macro) {
|
||||
return macro
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package macro
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/kataras/iris/core/router/macro/interpreter/ast"
|
||||
"github.com/kataras/iris/core/router/macro/interpreter/parser"
|
||||
)
|
||||
|
@ -27,8 +29,8 @@ type TemplateParam struct {
|
|||
Name string `json:"name"`
|
||||
Index int `json:"index"`
|
||||
ErrCode int `json:"errCode"`
|
||||
TypeEvaluator EvaluatorFunc `json:"-"`
|
||||
Funcs []EvaluatorFunc `json:"-"`
|
||||
TypeEvaluator ParamEvaluator `json:"-"`
|
||||
Funcs []reflect.Value `json:"-"`
|
||||
}
|
||||
|
||||
// Parse takes a full route path and a macro map (macro map contains the macro types with their registered param functions)
|
||||
|
@ -74,7 +76,7 @@ func Parse(src string, macros Macros) (*Template, error) {
|
|||
}
|
||||
|
||||
evalFn := tmplFn(paramfn.Args)
|
||||
if evalFn == nil {
|
||||
if evalFn.IsNil() || !evalFn.IsValid() || evalFn.Kind() != reflect.Func {
|
||||
continue
|
||||
}
|
||||
tmplParam.Funcs = append(tmplParam.Funcs, evalFn)
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"runtime"
|
||||
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/core/memstore"
|
||||
"github.com/kataras/iris/hero/di"
|
||||
|
||||
"github.com/kataras/golog"
|
||||
|
@ -14,7 +13,6 @@ import (
|
|||
|
||||
var (
|
||||
contextTyp = reflect.TypeOf((*context.Context)(nil)).Elem()
|
||||
memstoreTyp = reflect.TypeOf(memstore.Store{})
|
||||
)
|
||||
|
||||
// IsContext returns true if the "inTyp" is a type of Context.
|
||||
|
@ -22,14 +20,6 @@ func IsContext(inTyp reflect.Type) bool {
|
|||
return inTyp.Implements(contextTyp)
|
||||
}
|
||||
|
||||
// IsExpectingStore returns true if the "inTyp" is a type of memstore.Store.
|
||||
func IsExpectingStore(inTyp reflect.Type) bool {
|
||||
print("di/handler.go: " + inTyp.String() + " vs " + memstoreTyp.String() + " : ")
|
||||
println(inTyp == memstoreTyp)
|
||||
|
||||
return inTyp == memstoreTyp
|
||||
}
|
||||
|
||||
// checks if "handler" is context.Handler: func(context.Context).
|
||||
func isContextHandler(handler interface{}) (context.Handler, bool) {
|
||||
h, is := handler.(context.Handler)
|
||||
|
|
Loading…
Reference in New Issue
Block a user