mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
26c315cdb1
Former-commit-id: 6cca675303187f10377a7a713b2e7b3cdf16fd18
137 lines
3.9 KiB
Go
137 lines
3.9 KiB
Go
// Copyright 2017 Gerasimos Maropoulos, ΓΜ. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package router
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/kataras/iris/context"
|
|
"github.com/kataras/iris/core/router/macro"
|
|
)
|
|
|
|
// Route contains the information about a registered Route.
|
|
// If any of the following fields are changed then the
|
|
// caller should Refresh the router.
|
|
type Route struct {
|
|
Name string // "userRoute"
|
|
Method string // "GET"
|
|
Subdomain string // "admin."
|
|
tmpl *macro.Template // Tmpl().Src: "/api/user/{id:int}"
|
|
Path string // "/api/user/:id"
|
|
Handlers context.Handlers
|
|
// FormattedPath all dynamic named parameters (if any) replaced with %v,
|
|
// used by Application to validate param values of a Route based on its name.
|
|
FormattedPath string
|
|
}
|
|
|
|
// NewRoute returns a new route based on its method,
|
|
// subdomain, the path (unparsed or original),
|
|
// handlers and the macro container which all routes should share.
|
|
// It parses the path based on the "macros",
|
|
// handlers are being changed to validate the macros at serve time, if needed.
|
|
func NewRoute(method, subdomain, unparsedPath string,
|
|
handlers context.Handlers, macros *macro.MacroMap) (*Route, error) {
|
|
|
|
tmpl, err := macro.Parse(unparsedPath, macros)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
path, handlers, err := compileRoutePathAndHandlers(handlers, tmpl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
path = cleanPath(path) // maybe unnecessary here but who cares in this moment
|
|
defaultName := method + subdomain + path
|
|
|
|
formattedPath := formatPath(path)
|
|
|
|
route := &Route{
|
|
Name: defaultName,
|
|
Method: method,
|
|
Subdomain: subdomain,
|
|
tmpl: tmpl,
|
|
Path: path,
|
|
Handlers: handlers,
|
|
FormattedPath: formattedPath,
|
|
}
|
|
return route, nil
|
|
}
|
|
|
|
// Tmpl returns the path template, i
|
|
// it contains the parsed template
|
|
// for the route's path.
|
|
// May contain zero named parameters.
|
|
//
|
|
// Developer can get his registered path
|
|
// via Tmpl().Src, Route.Path is the path
|
|
// converted to match the underline router's specs.
|
|
func (r Route) Tmpl() macro.Template {
|
|
return *r.tmpl
|
|
}
|
|
|
|
// IsOnline returns true if the route is marked as "online" (state).
|
|
func (r Route) IsOnline() bool {
|
|
return r.Method != MethodNone
|
|
}
|
|
|
|
// formats the parsed to the underline httprouter's path syntax.
|
|
// path = "/api/users/:id"
|
|
// return "/api/users/%v"
|
|
//
|
|
// path = "/files/*file"
|
|
// return /files/%v
|
|
//
|
|
// path = "/:username/messages/:messageid"
|
|
// return "/%v/messages/%v"
|
|
// we don't care about performance here, it's prelisten.
|
|
func formatPath(path string) string {
|
|
if strings.Contains(path, ParamStart) || strings.Contains(path, WildcardParamStart) {
|
|
var (
|
|
startRune = ParamStart[0]
|
|
wildcardStartRune = WildcardParamStart[0]
|
|
)
|
|
|
|
var formattedParts []string
|
|
parts := strings.Split(path, "/")
|
|
for _, part := range parts {
|
|
if len(part) == 0 {
|
|
continue
|
|
}
|
|
if part[0] == startRune || part[0] == wildcardStartRune {
|
|
// is param or wildcard param
|
|
part = "%v"
|
|
}
|
|
formattedParts = append(formattedParts, part)
|
|
}
|
|
|
|
return "/" + strings.Join(formattedParts, "/")
|
|
}
|
|
// the whole path is static just return it
|
|
return path
|
|
}
|
|
|
|
// ResolvePath returns the formatted path's %v replaced with the args.
|
|
func (r Route) ResolvePath(args ...string) string {
|
|
rpath, formattedPath := r.Path, r.FormattedPath
|
|
if rpath == formattedPath {
|
|
// static, no need to pass args
|
|
return rpath
|
|
}
|
|
// check if we have /*, if yes then join all arguments to one as path and pass that as parameter
|
|
if rpath[len(rpath)-1] == WildcardParamStart[0] {
|
|
parameter := strings.Join(args, "/")
|
|
return fmt.Sprintf(formattedPath, parameter)
|
|
}
|
|
// else return the formattedPath with its args,
|
|
// the order matters.
|
|
for _, s := range args {
|
|
formattedPath = strings.Replace(formattedPath, "%v", s, 1)
|
|
}
|
|
return formattedPath
|
|
}
|