diff options
author | Franck Cuny <franck@lumberjaph.net> | 2013-04-25 20:01:23 -0700 |
---|---|---|
committer | Franck Cuny <franck@lumberjaph.net> | 2013-04-26 07:41:24 -0700 |
commit | f1d0b1f2ce7a90b80079c8e0e2ef4642d36ec941 (patch) | |
tree | 85dd4aaa279abc49d0f6268c4bfc099aa18dc967 /route.go | |
parent | Add build status (diff) | |
download | path-router-f1d0b1f2ce7a90b80079c8e0e2ef4642d36ec941.tar.gz |
Add Validations for URL parameters.
By adding validations, it's possible to create without ambiguity routes like "/user/:id" and "/user/:name", where the validation for the name will check that it's an number, and name is a string. A validation is not required for every key. However, you can't specify a validation for a key that does not exist in the URL. The validation use Regexp for now, and the user has to create the regexp with the function MustCompile. Some utility functions are added to easily gain information about a component, validator, etc. This will be extended more soon.
Diffstat (limited to 'route.go')
-rw-r--r-- | route.go | 77 |
1 files changed, 67 insertions, 10 deletions
diff --git a/route.go b/route.go index b724a04..9eab0ab 100644 --- a/route.go +++ b/route.go @@ -17,6 +17,7 @@ type Route struct { optionalNamedComponents map[string]bool length int lengthWithoutOptional int + Validations map[string]*regexp.Regexp } type Match struct { @@ -31,11 +32,19 @@ var componentsIsOptional = regexp.MustCompile("^\\?:") var namedComponentsRegex = regexp.MustCompile("^:(.*)$") var convertComponent = regexp.MustCompile("^\\??:(.*)$") +// XXX explain this function func (self *Route) convertComponentName(name string) string { newName := convertComponent.FindStringSubmatch(name) + if len(newName) == 0 { + return name + } return newName[1] } +func (self *Route) ValidateFor(key string, component string) bool { + return self.Validations[key].MatchString(component) +} + func (self *Route) Match(method string, components []string) *Match { if self.Method != method { @@ -48,15 +57,35 @@ func (self *Route) Match(method string, components []string) *Match { mapping := map[string]string{} - for i, c := range self.components { - if componentsIsOptional.MatchString(c) { - break - } - p := components[i] + currentComponentsLength := len(components) - if componentIsVariable.MatchString(c) == true { - mapping[self.convertComponentName(c)] = p - } else { +L: + for i, c := range self.components { + convertedName := self.convertComponentName(c) + + switch { + case self.IsOptionalUrlParameter(convertedName) == true: + if i < currentComponentsLength && self.HasValidationFor(convertedName) { + p := components[i] + if self.ValidateFor(convertedName, p) == true { + break L + } + } else { + break L + } + case self.IsRequiredUrlParameter(convertedName) == true: + p := components[i] + if self.HasValidationFor(convertedName) { + if self.ValidateFor(convertedName, p) == true { + mapping[convertedName] = p + } else { + return nil + } + } else { + mapping[convertedName] = p + } + default: + p := components[i] if p != c { return nil } @@ -85,6 +114,34 @@ func (self *Route) init() { self.length = len(self.components) self.getNamedComponents() + + for k, _ := range self.Validations { + if self.IsUrlParameter(k) == false { + panic(k + " is missing") + } + } +} + +func (self *Route) IsUrlParameter(component string) bool { + if self.IsRequiredUrlParameter(component) == false && self.IsOptionalUrlParameter(component) == false { + return false + } + return true +} + +func (self *Route) IsRequiredUrlParameter(component string) bool { + return self.requiredNamedComponents[component] +} + +func (self *Route) IsOptionalUrlParameter(component string) bool { + return self.optionalNamedComponents[component] +} + +func (self *Route) HasValidationFor(component string) bool { + if self.Validations[component] != nil { + return true + } + return false } func (self *Route) getNamedComponents() { @@ -93,9 +150,9 @@ func (self *Route) getNamedComponents() { for _, c := range self.components { if namedComponentsRegex.MatchString(c) == true { - self.requiredNamedComponents[c] = true + self.requiredNamedComponents[self.convertComponentName(c)] = true } else if componentsIsOptional.MatchString(c) == true { - self.optionalNamedComponents[c] = true + self.optionalNamedComponents[self.convertComponentName(c)] = true } } self.lengthWithoutOptional = self.length - len(self.optionalNamedComponents) |