diff --git a/README.md b/README.md index 1183f7e1..a6f6972d 100644 --- a/README.md +++ b/README.md @@ -644,7 +644,7 @@ func main() { // Register validation for 'User' // NOTE: only have to register a non-pointer type for 'User', validator - // interanlly dereferences during it's type checks. + // internally dereferences during it's type checks. validate.RegisterStructValidation(UserStructLevelValidation, User{}) app := iris.New() diff --git a/_examples/http_request/read-json-struct-validation/main.go b/_examples/http_request/read-json-struct-validation/main.go index f7beedc0..16dab511 100644 --- a/_examples/http_request/read-json-struct-validation/main.go +++ b/_examples/http_request/read-json-struct-validation/main.go @@ -36,7 +36,7 @@ func main() { // Register validation for 'User' // NOTE: only have to register a non-pointer type for 'User', validator - // interanlly dereferences during it's type checks. + // internally dereferences during it's type checks. validate.RegisterStructValidation(UserStructLevelValidation, User{}) app := iris.New() diff --git a/context/request_params.go b/context/request_params.go index fc1b47c8..7757308b 100644 --- a/context/request_params.go +++ b/context/request_params.go @@ -90,6 +90,18 @@ func (r RequestParams) GetIntUnslashed(key string) (int, bool) { } var ( + // ParamResolvers is the global param resolution for a parameter type for a specific go std or custom type. + // + // Key is the specific type, which should be unique. + // The value is a function which accepts the parameter index + // and it should return the value as the parameter type evaluator expects it. + // i.e [reflect.TypeOf("string")] = func(paramIndex int) interface{} { + // return func(ctx Context) { + // return ctx.Params().GetEntryAt(paramIndex).ValueRaw.() + // } + // } + // + // Read https://github.com/kataras/iris/tree/master/_examples/routing/macros for more details. ParamResolvers = map[reflect.Type]func(paramIndex int) interface{}{ reflect.TypeOf(""): func(paramIndex int) interface{} { return func(ctx Context) string { diff --git a/macro/macro.go b/macro/macro.go index 2e461ad2..8a656e2c 100644 --- a/macro/macro.go +++ b/macro/macro.go @@ -9,15 +9,12 @@ import ( "unicode" ) -// 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 BinderFunc func(paramValue string) interface{} - type ( + // ParamEvaluator is the signature for param type evaluator. + // It accepts the param's value as string and returns + // the value (which its type is used for the input argument of the parameter functions, if any) + // and a true value for passed, otherwise nil and false shoudl be returned. ParamEvaluator func(paramValue string) (interface{}, bool) - // FuncEvaluator interface{} // i.e func(paramValue int) bool ) var goodEvaluatorFuncs = []reflect.Type{ @@ -275,18 +272,25 @@ func NewMacro(indent, alias string, master, trailing bool, evaluator ParamEvalua } } +// Indent returns the name of the parameter type. func (m *Macro) Indent() string { return m.indent } +// Alias returns the alias of the parameter type, if any. func (m *Macro) Alias() string { return m.alias } +// Master returns true if that macro's parameter type is the +// default one if not :type is followed by a parameter type inside the route path. func (m *Macro) Master() bool { return m.master } +// Trailing returns true if that macro's parameter type +// is wildcard and can accept one or more path segments as one parameter value. +// A wildcard should be registered in the last path segment only. func (m *Macro) Trailing() bool { return m.trailing } diff --git a/macro/macros.go b/macro/macros.go index 12a5cf21..4c6f6416 100644 --- a/macro/macros.go +++ b/macro/macros.go @@ -402,6 +402,9 @@ var ( // Should be living in the latest path segment of a route path. Path = NewMacro("path", "", false, true, nil) + // Defaults contains the defaults macro and parameters types for the router. + // + // Read https://github.com/kataras/iris/tree/master/_examples/routing/macros for more details. Defaults = &Macros{ String, Int, @@ -420,8 +423,18 @@ var ( } ) +// Macros is just a type of a slice of *Macro +// which is responsible to register and search for macros based on the indent(parameter type). type Macros []*Macro +// Register registers a custom Macro. +// The "indent" should not be empty and should be unique, it is the parameter type's name, i.e "string". +// The "alias" is optionally and it should be unique, it is the alias of the parameter type. +// "isMaster" and "isTrailing" is for default parameter type and wildcard respectfully. +// The "evaluator" is the function that is converted to an Iris handler which is executed every time +// before the main chain of a route's handlers that contains this macro of the specific parameter type. +// +// Read https://github.com/kataras/iris/tree/master/_examples/routing/macros for more details. func (ms *Macros) Register(indent, alias string, isMaster, isTrailing bool, evaluator ParamEvaluator) *Macro { macro := NewMacro(indent, alias, isMaster, isTrailing, evaluator) if ms.register(macro) { @@ -460,6 +473,7 @@ func (ms *Macros) register(macro *Macro) bool { return true } +// Unregister removes a macro and its parameter type from the list. func (ms *Macros) Unregister(indent string) bool { cp := *ms @@ -477,6 +491,7 @@ func (ms *Macros) Unregister(indent string) bool { return false } +// Lookup returns the responsible macro for a parameter type, it can return nil. func (ms *Macros) Lookup(pt ast.ParamType) *Macro { if m := ms.Get(pt.Indent()); m != nil { return m @@ -491,6 +506,7 @@ func (ms *Macros) Lookup(pt ast.ParamType) *Macro { return nil } +// Get returns the responsible macro for a parameter type, it can return nil. func (ms *Macros) Get(indentOrAlias string) *Macro { if indentOrAlias == "" { return nil @@ -509,6 +525,8 @@ func (ms *Macros) Get(indentOrAlias string) *Macro { return nil } +// GetMaster returns the default macro and its parameter type, +// by default it will return the `String` macro which is responsible for the "string" parameter type. func (ms *Macros) GetMaster() *Macro { for _, m := range *ms { if m.Master() { @@ -519,6 +537,8 @@ func (ms *Macros) GetMaster() *Macro { return nil } +// GetTrailings returns the macros that have support for wildcards parameter types. +// By default it will return the `Path` macro which is responsible for the "path" parameter type. func (ms *Macros) GetTrailings() (macros []*Macro) { for _, m := range *ms { if m.Trailing() { diff --git a/macro/template.go b/macro/template.go index cd83d9c7..8e766cb5 100644 --- a/macro/template.go +++ b/macro/template.go @@ -54,14 +54,23 @@ func (p TemplateParam) preComputed() TemplateParam { return p } +// CanEval returns true if this "p" TemplateParam should be evaluated in serve time. +// It is computed before server ran and it is used to determinate if a route needs to build a macro handler (middleware). func (p *TemplateParam) CanEval() bool { return p.canEval } -// paramChanger is the same form of context's Params().Set +// Eval is the most critical part of the TEmplateParam. +// It is responsible to return "passed:true" or "not passed:false" +// if the "paramValue" is the correct type of the registered parameter type +// and all functions, if any, are passed. +// "paramChanger" is the same form of context's Params().Set // we could accept a memstore.Store or even context.RequestParams // but this form has been chosed in order to test easier and fully decoupled from a request when necessary. -func (p *TemplateParam) Eval(paramValue string, paramChanger memstore.ValueSetter) bool { +// +// It is called from the converted macro handler (middleware) +// from the higher-level component of "kataras/iris/macro/handler#MakeHandler". +func (p *TemplateParam) Eval(paramValue string, paramSetter memstore.ValueSetter) bool { if p.TypeEvaluator == nil { for _, fn := range p.stringInFuncs { if !fn(paramValue) { @@ -87,7 +96,7 @@ func (p *TemplateParam) Eval(paramValue string, paramChanger memstore.ValueSette } } - paramChanger.Set(p.Name, newValue) + paramSetter.Set(p.Name, newValue) return true }