mirror of
https://github.com/jimeh/casecmp.git
synced 2026-02-19 02:16:40 +00:00
162 lines
4.5 KiB
Go
162 lines
4.5 KiB
Go
// Copyright 2016 Qiang Xue. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package routing
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// Route represents a URL path pattern that can be used to match requested URLs.
|
|
type Route struct {
|
|
group *RouteGroup
|
|
name, path string
|
|
template string
|
|
}
|
|
|
|
// newRoute creates a new Route with the given route path and route group.
|
|
func newRoute(path string, group *RouteGroup) *Route {
|
|
path = group.prefix + path
|
|
name := path
|
|
|
|
// an asterisk at the end matches any number of characters
|
|
if strings.HasSuffix(path, "*") {
|
|
path = path[:len(path)-1] + "<:.*>"
|
|
}
|
|
|
|
route := &Route{
|
|
group: group,
|
|
name: name,
|
|
path: path,
|
|
template: buildURLTemplate(path),
|
|
}
|
|
group.router.routes[name] = route
|
|
|
|
return route
|
|
}
|
|
|
|
// Name sets the name of the route.
|
|
// This method will update the registration of the route in the router as well.
|
|
func (r *Route) Name(name string) *Route {
|
|
r.name = name
|
|
r.group.router.routes[name] = r
|
|
return r
|
|
}
|
|
|
|
// Get adds the route to the router using the GET HTTP method.
|
|
func (r *Route) Get(handlers ...Handler) *Route {
|
|
return r.add("GET", handlers)
|
|
}
|
|
|
|
// Post adds the route to the router using the POST HTTP method.
|
|
func (r *Route) Post(handlers ...Handler) *Route {
|
|
return r.add("POST", handlers)
|
|
}
|
|
|
|
// Put adds the route to the router using the PUT HTTP method.
|
|
func (r *Route) Put(handlers ...Handler) *Route {
|
|
return r.add("PUT", handlers)
|
|
}
|
|
|
|
// Patch adds the route to the router using the PATCH HTTP method.
|
|
func (r *Route) Patch(handlers ...Handler) *Route {
|
|
return r.add("PATCH", handlers)
|
|
}
|
|
|
|
// Delete adds the route to the router using the DELETE HTTP method.
|
|
func (r *Route) Delete(handlers ...Handler) *Route {
|
|
return r.add("DELETE", handlers)
|
|
}
|
|
|
|
// Connect adds the route to the router using the CONNECT HTTP method.
|
|
func (r *Route) Connect(handlers ...Handler) *Route {
|
|
return r.add("CONNECT", handlers)
|
|
}
|
|
|
|
// Head adds the route to the router using the HEAD HTTP method.
|
|
func (r *Route) Head(handlers ...Handler) *Route {
|
|
return r.add("HEAD", handlers)
|
|
}
|
|
|
|
// Options adds the route to the router using the OPTIONS HTTP method.
|
|
func (r *Route) Options(handlers ...Handler) *Route {
|
|
return r.add("OPTIONS", handlers)
|
|
}
|
|
|
|
// Trace adds the route to the router using the TRACE HTTP method.
|
|
func (r *Route) Trace(handlers ...Handler) *Route {
|
|
return r.add("TRACE", handlers)
|
|
}
|
|
|
|
// To adds the route to the router with the given HTTP methods and handlers.
|
|
// Multiple HTTP methods should be separated by commas (without any surrounding spaces).
|
|
func (r *Route) To(methods string, handlers ...Handler) *Route {
|
|
for _, method := range strings.Split(methods, ",") {
|
|
r.add(method, handlers)
|
|
}
|
|
return r
|
|
}
|
|
|
|
// URL creates a URL using the current route and the given parameters.
|
|
// The parameters should be given in the sequence of name1, value1, name2, value2, and so on.
|
|
// If a parameter in the route is not provided a value, the parameter token will remain in the resulting URL.
|
|
// The method will perform URL encoding for all given parameter values.
|
|
func (r *Route) URL(pairs ...interface{}) (s string) {
|
|
s = r.template
|
|
for i := 0; i < len(pairs); i++ {
|
|
name := fmt.Sprintf("<%v>", pairs[i])
|
|
value := ""
|
|
if i < len(pairs)-1 {
|
|
value = url.QueryEscape(fmt.Sprint(pairs[i+1]))
|
|
}
|
|
s = strings.Replace(s, name, value, -1)
|
|
}
|
|
return
|
|
}
|
|
|
|
// add registers the route, the specified HTTP method and the handlers to the router.
|
|
// The handlers will be combined with the handlers of the route group.
|
|
func (r *Route) add(method string, handlers []Handler) *Route {
|
|
hh := combineHandlers(r.group.handlers, handlers)
|
|
r.group.router.add(method, r.path, hh)
|
|
return r
|
|
}
|
|
|
|
// buildURLTemplate converts a route pattern into a URL template by removing regular expressions in parameter tokens.
|
|
func buildURLTemplate(path string) string {
|
|
template, start, end := "", -1, -1
|
|
for i := 0; i < len(path); i++ {
|
|
if path[i] == '<' && start < 0 {
|
|
start = i
|
|
} else if path[i] == '>' && start >= 0 {
|
|
name := path[start+1 : i]
|
|
for j := start + 1; j < i; j++ {
|
|
if path[j] == ':' {
|
|
name = path[start+1 : j]
|
|
break
|
|
}
|
|
}
|
|
template += path[end+1:start] + "<" + name + ">"
|
|
end = i
|
|
start = -1
|
|
}
|
|
}
|
|
if end < 0 {
|
|
template = path
|
|
} else if end < len(path)-1 {
|
|
template += path[end+1:]
|
|
}
|
|
return template
|
|
}
|
|
|
|
// combineHandlers merges two lists of handlers into a new list.
|
|
func combineHandlers(h1 []Handler, h2 []Handler) []Handler {
|
|
hh := make([]Handler, len(h1)+len(h2))
|
|
copy(hh, h1)
|
|
copy(hh[len(h1):], h2)
|
|
return hh
|
|
}
|