|
- package capstan
-
- import (
- "strings"
- )
-
- // ParseRoute processes the specified route, processes it, and returns a
- // routeProps struct describing the route using go-chi syntax.
- //
- // Route parsing is somewhat analogous to go-chi but uses a different syntax. In
- // particular, route variables are delineated by "<" and ">" rather than "{" and
- // "}" as per go-chi. Further, besides regex types, Capstan routes also define
- // string, float, float32, float64, int, int32, and int64 types. Route syntax
- // is:
- //
- // String:
- //
- // /<varname:string>
- //
- // Integer types:
- //
- // /<varname:int32>
- //
- // Regular expressions:
- //
- // /<varname:regex>
- func (r *Router) ParseRoute(route string) *routeProps {
- props := &routeProps{
- params: make(map[string]string),
- }
-
- if route == "" {
- route = "/"
- }
-
- if route == "/" {
- props.route = "/"
- props.baseRoute = "/"
- props.slashIsDefault = true
- props.optionalSlash = true
- return props
- }
-
- if route[len(route)-1:] == "/" {
- props.mandatorySlash = true
- } else if strings.HasSuffix(route, "?") {
- props.optionalSlash = true
- if len(route) >= 2 && route[len(route)-2:] == "/?" {
- props.slashIsDefault = true
- }
- route = route[:len(route)-1]
- } else if strings.HasSuffix(route, "!") {
- props.mandatoryNoSlash = true
- if len(route) >= 2 && route[len(route)-2:] != "/!" {
- route = route[:len(route)-1] + "/"
- } else {
- route = route[:len(route)-1]
- }
- } else if strings.HasSuffix(route, "+") {
- props.mandatorySlash = true
- // Accept routes with just a + suffix, e.g. "/route+".
- if len(route) >= 2 && route[len(route)-2:] != "/+" {
- route = route[:len(route)-1] + "/"
- } else {
- route = route[:len(route)-1]
- }
- } else {
- props.optionalSlash = true
- }
-
- open := 0
- param := ""
- paramType := ""
- colon := false
- base := true
- for _, c := range route {
- if open == 0 && c == '/' {
- props.route += string(c)
- if base {
- props.baseRoute += string(c)
- }
- continue
- }
-
- if c == '<' {
- base = false
- open++
- if open == 1 {
- props.route += "{"
- continue
- }
- } else if c == '>' {
- open--
- if open == 0 {
- props.params[param] = paramType
- switch paramType {
- case "string":
- case "float":
- case "float32":
- case "float64":
- case "int":
- case "int32":
- case "int64":
- case "integer":
- default:
- // Most likely a regex type.
- props.route += ":" + paramType
- }
- props.route += "}"
-
- colon = false
- param = ""
- paramType = ""
- continue
- }
- } else {
- if open == 0 && c != '?' {
- props.route += string(c)
- }
- }
-
- if open == 1 && c == ':' {
- colon = true
- continue
- }
-
- if open == 1 {
- if !colon {
- param += string(c)
- props.route += string(c)
- } else {
- paramType += string(c)
- }
- }
-
- if open > 1 {
- paramType += string(c)
- }
-
- if base {
- props.baseRoute += string(c)
- }
- }
-
- if open >= 1 {
- // TODO: Handle error.
- }
-
- return props
- }
|