Skip to content

Commit

Permalink
- Fix routing (rx in groups)
Browse files Browse the repository at this point in the history
  • Loading branch information
legion-zver committed May 20, 2018
1 parent 26ae63a commit 573fad8
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 88 deletions.
9 changes: 6 additions & 3 deletions just.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (
)

const (
Version = "v0.0.11"
Version = "v0.1.12"
DebugEnvName = "JUST_DEBUG_MODE"
)

Expand Down Expand Up @@ -205,7 +205,6 @@ func (app *application) handleHttpRequest(w http.ResponseWriter, c *Context) {

func (app *application) handleRouter(router *Router, httpMethod, path string, c *Context) (IResponse, bool) {
if router != nil {

// Поиск роута
if router.routes != nil && len(router.routes) > 0 {
if routes, ok := router.routes[httpMethod]; ok && len(routes) > 0 {
Expand All @@ -219,7 +218,11 @@ func (app *application) handleRouter(router *Router, httpMethod, path string, c
// Поиск следующего роутера
if router.groups != nil && len(router.groups) > 0 {
for relativePath, r := range router.groups {
if strings.Index(path, joinPaths(router.basePath, relativePath)) >= 0 {
if strings.Index(relativePath, "{") >= 0 && r.rxPath != nil {
if _, ok := r.CheckPath(path); ok {
return app.handleRouter(r, httpMethod, path, c)
}
} else if strings.Index(path, joinPaths(router.basePath, relativePath)) >= 0 {
return app.handleRouter(r, httpMethod, path, c)
}
}
Expand Down
172 changes: 87 additions & 85 deletions routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,88 +85,88 @@ func connectHandlersByRouter(r *Router, handlers []HandlerFunc) []HandlerFunc {
return handlers
}

func regularityBasePath(httpMethod, basePath string, supportEndSlash bool) (rxPath *regexp.Regexp, paramNames []string) {
if strings.Index(basePath, "{") >= 0 {
params := rxPathFindParams.FindAllStringSubmatch(basePath, -1)
if len(params) > 0 {
// Формируем полные рекомендации и по ним строим пути
paramNames = make([]string, len(params))
regExpPattern := basePath
for i, param := range params {
if len(param) > 0 {
if len(param) > 1 {
// Анализ параметра
if pos := strings.Index(param[1], ":"); pos > 0 {
paramNames[i] = strings.TrimSpace(param[1][0:pos])
if req := strings.TrimSpace(param[1][pos+1:]); len(req) > 1 {
// Анализ рекомендаций параметра
findPattern := true
switch req {
case "p", "path":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamPath, 1)
case "hex":
regExpPattern = strings.Replace(regExpPattern, param[0], patternHex, 1)
case "rid":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamRID, 1)
case "uuid":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamUUID, 1)
case "i", "int", "integer":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamInteger, 1)
case "f", "number", "float":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamFloat, 1)
case "b", "bool", "boolean":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamBoolean, 1)
case "f.e", "file.ext":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamFileExt, 1)
default:
{
findPattern = false
if begin, end := strings.Index(req, "("), strings.LastIndex(req, ")"); begin > 0 && end > begin {
if t := strings.TrimSpace(req[:begin]); len(t) > 0 {
if findPattern = t == "regexp" || t == "enum"; findPattern && len(strings.TrimSpace(req[begin+1:end])) > 0 {
switch t {
case "rgx", "regexp":
regExpPattern = strings.Replace(regExpPattern, param[0], strings.TrimSpace(req[begin:]), 1)
case "e", "enum":
regExpPattern = strings.Replace(regExpPattern, param[0], "("+strings.Join(strings.FieldsFunc(req[begin+1:end], func(c rune) bool {
return !unicode.IsLetter(c) && !unicode.IsNumber(c)
}), "|")+")", 1)
}
}
}
func regularityBasePath(basePath string, exactly bool, supportEndSlash bool) (rxPath *regexp.Regexp, paramNames []string) {
if strings.Index(basePath, "{") < 0 {
return
}
params := rxPathFindParams.FindAllStringSubmatch(basePath, -1)
if len(params) < 1 {
return
}
paramNames = make([]string, len(params))
regExpPattern := basePath
for i, param := range params {
if len(param) == 0 {
continue
}
if len(param) > 1 {
// Анализ параметра
if pos := strings.Index(param[1], ":"); pos > 0 {
paramNames[i] = strings.TrimSpace(param[1][0:pos])
if req := strings.TrimSpace(param[1][pos+1:]); len(req) > 1 {
// Анализ рекомендаций параметра
findPattern := true
switch req {
case "p", "path":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamPath, 1)
case "hex":
regExpPattern = strings.Replace(regExpPattern, param[0], patternHex, 1)
case "rid":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamRID, 1)
case "uuid":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamUUID, 1)
case "i", "int", "integer":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamInteger, 1)
case "f", "number", "float":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamFloat, 1)
case "b", "bool", "boolean":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamBoolean, 1)
case "f.e", "file.ext":
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamFileExt, 1)
default:
{
findPattern = false
if begin, end := strings.Index(req, "("), strings.LastIndex(req, ")"); begin > 0 && end > begin {
if t := strings.TrimSpace(req[:begin]); len(t) > 0 {
if findPattern = t == "regexp" || t == "enum"; findPattern && len(strings.TrimSpace(req[begin+1:end])) > 0 {
switch t {
case "rgx", "regexp":
regExpPattern = strings.Replace(regExpPattern, param[0], strings.TrimSpace(req[begin:]), 1)
case "e", "enum":
regExpPattern = strings.Replace(regExpPattern, param[0], "("+strings.Join(strings.FieldsFunc(req[begin+1:end], func(c rune) bool {
return !unicode.IsLetter(c) && !unicode.IsNumber(c)
}), "|")+")", 1)
}
}
}
if findPattern {
continue
}
}
} else {
paramNames[i] = strings.TrimSpace(param[1])
}
} else {
paramNames[i] = strings.TrimSpace(param[0])
}
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamString, 1)
if findPattern {
continue
}
}
}
var err error
if IsDebug() {
fmt.Println("[DEBUG] Registration", httpMethod, "route regexp:", regExpPattern, paramNames)
}
var end string
if supportEndSlash {
end = "(\\/)?$"
} else {
end = "$"
}
rxPath, err = regexp.Compile("^" + regExpPattern + end)
if err != nil {
panic(err)
paramNames[i] = strings.TrimSpace(param[1])
}
} else {
paramNames[i] = strings.TrimSpace(param[0])
}
} else if IsDebug() {
fmt.Println("[DEBUG] Registration", httpMethod, "route:", basePath)
regExpPattern = strings.Replace(regExpPattern, param[0], patternParamString, 1)
}
var (
err error
end string
)
if supportEndSlash {
end = "(\\/)?"
}
if exactly {
end += "$"
}
rxPath, err = regexp.Compile("^" + regExpPattern + end)
if err != nil {
panic(err)
}
return
}
Expand All @@ -178,18 +178,14 @@ func (r *Router) handle(httpMethod string, relativePath string, handlers []Handl
if _, ok := r.routes[httpMethod]; !ok {
r.routes[httpMethod] = make([]IRoute, 0)
}
var (
basePath string
rxPath *regexp.Regexp
routeParamNames []string
)
if len(relativePath) < 1 || relativePath == "/" {
rxPath = r.rxPath
basePath = r.basePath
routeParamNames = r.routeParamNames
} else {
basePath = joinPaths(r.basePath, strings.TrimRight(relativePath, "/"))
rxPath, routeParamNames = regularityBasePath(httpMethod, basePath, false)
basePath := joinPaths(r.basePath, strings.TrimRight(relativePath, "/"))
rxPath, routeParamNames := regularityBasePath(basePath, true, true)
if IsDebug() {
if rxPath != nil {
fmt.Println("[DEBUG] Registration", httpMethod, "route regexp:", rxPath.String(), routeParamNames)
} else {
fmt.Println("[DEBUG] Registration", httpMethod, "plain route:", basePath)
}
}
r.routes[httpMethod] = append(r.routes[httpMethod], &Router{
basePath: basePath,
Expand Down Expand Up @@ -219,8 +215,14 @@ func (r *Router) Group(relativePath string, handlers ...HandlerFunc) IRouter {
panic(fmt.Errorf("the group cannot be empty"))
return nil
}
var (
rxPath *regexp.Regexp
routeParamNames []string
)
basePath := joinPaths(r.basePath, strings.TrimRight(relativePath, "/"))
rxPath, routeParamNames := regularityBasePath("GROUP", basePath, true)
if strings.Index(basePath, "{") >= 0 {
rxPath, routeParamNames = regularityBasePath(basePath, false, true)
}
group := &Router{
basePath: basePath,
rxPath: rxPath,
Expand Down

0 comments on commit 573fad8

Please sign in to comment.