aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/go-zoo/bone
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/go-zoo/bone')
-rw-r--r--vendor/github.com/go-zoo/bone/LICENSE22
-rw-r--r--vendor/github.com/go-zoo/bone/README.md81
-rw-r--r--vendor/github.com/go-zoo/bone/bone.go74
-rw-r--r--vendor/github.com/go-zoo/bone/helper.go169
-rw-r--r--vendor/github.com/go-zoo/bone/helper_15.go45
-rw-r--r--vendor/github.com/go-zoo/bone/helper_17.go39
-rw-r--r--vendor/github.com/go-zoo/bone/mux.go137
-rw-r--r--vendor/github.com/go-zoo/bone/route.go245
8 files changed, 812 insertions, 0 deletions
diff --git a/vendor/github.com/go-zoo/bone/LICENSE b/vendor/github.com/go-zoo/bone/LICENSE
new file mode 100644
index 000000000..652583b76
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 CodingFerret
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, Subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or Substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/go-zoo/bone/README.md b/vendor/github.com/go-zoo/bone/README.md
new file mode 100644
index 000000000..29ea5f6de
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/README.md
@@ -0,0 +1,81 @@
+bone [![GoDoc](https://godoc.org/github.com/squiidz/bone?status.png)](http://godoc.org/github.com/go-zoo/bone) [![Build Status](https://travis-ci.org/go-zoo/bone.svg)](https://travis-ci.org/go-zoo/bone) [![Go Report Card](https://goreportcard.com/badge/go-zoo/bone)](https://goreportcard.com/report/go-zoo/bone) [![Sourcegraph](https://sourcegraph.com/github.com/go-zoo/bone/-/badge.svg)](https://sourcegraph.com/github.com/go-zoo/bone?badge)
+=======
+
+## What is bone ?
+
+Bone is a lightweight and lightning fast HTTP Multiplexer for Golang. It support :
+
+- URL Parameters
+- REGEX Parameters
+- Wildcard routes
+- Router Prefix
+- Sub Router, `mux.SubRoute()`, support most standard router (bone, gorilla/mux, httpRouter etc...)
+- Http method declaration
+- Support for `http.Handler` and `http.HandlerFunc`
+- Custom NotFound handler
+- Respect the Go standard `http.Handler` interface
+
+![alt tag](https://c2.staticflickr.com/2/1070/540747396_5542b42cca_z.jpg)
+
+## Speed
+
+```
+- BenchmarkBoneMux 10000000 118 ns/op
+- BenchmarkZeusMux 100000 144 ns/op
+- BenchmarkHttpRouterMux 10000000 134 ns/op
+- BenchmarkNetHttpMux 3000000 580 ns/op
+- BenchmarkGorillaMux 300000 3333 ns/op
+- BenchmarkGorillaPatMux 1000000 1889 ns/op
+```
+
+ These test are just for fun, all these router are great and really efficient.
+ Bone do not pretend to be the fastest router for every job.
+
+## Example
+
+``` go
+
+package main
+
+import(
+ "net/http"
+
+ "github.com/go-zoo/bone"
+)
+
+func main () {
+ mux := bone.New()
+
+ // mux.Get, Post, etc ... takes http.Handler
+ mux.Get("/home/:id", http.HandlerFunc(HomeHandler))
+ mux.Get("/profil/:id/:var", http.HandlerFunc(ProfilHandler))
+ mux.Post("/data", http.HandlerFunc(DataHandler))
+
+ // Support REGEX Route params
+ mux.Get("/index/#id^[0-9]$", http.HandlerFunc(IndexHandler))
+
+ // Handle take http.Handler
+ mux.Handle("/", http.HandlerFunc(RootHandler))
+
+ // GetFunc, PostFunc etc ... takes http.HandlerFunc
+ mux.GetFunc("/test", Handler)
+
+ http.ListenAndServe(":8080", mux)
+}
+
+func Handler(rw http.ResponseWriter, req *http.Request) {
+ // Get the value of the "id" parameters.
+ val := bone.GetValue(req, "id")
+
+ rw.Write([]byte(val))
+}
+
+```
+
+## Blog Posts
+- http://www.peterbe.com/plog/my-favorite-go-multiplexer
+- https://harshladha.xyz/my-first-library-in-go-language-hasty-791b8e2b9e69
+
+## Libs
+- Errors dump for Go : [Trash](https://github.com/go-zoo/trash)
+- Middleware Chaining module : [Claw](https://github.com/go-zoo/claw)
diff --git a/vendor/github.com/go-zoo/bone/bone.go b/vendor/github.com/go-zoo/bone/bone.go
new file mode 100644
index 000000000..d00a0b083
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/bone.go
@@ -0,0 +1,74 @@
+/********************************
+*** Multiplexer for Go ***
+*** Bone is under MIT license ***
+*** Code by CodingFerret ***
+*** github.com/go-zoo ***
+*********************************/
+
+package bone
+
+import (
+ "net/http"
+ "strings"
+)
+
+// Mux have routes and a notFound handler
+// Route: all the registred route
+// notFound: 404 handler, default http.NotFound if not provided
+type Mux struct {
+ Routes map[string][]*Route
+ prefix string
+ notFound http.Handler
+ Serve func(rw http.ResponseWriter, req *http.Request)
+ CaseSensitive bool
+}
+
+var (
+ static = "static"
+ method = []string{"GET", "POST", "PUT", "DELETE", "HEAD", "PATCH", "OPTIONS"}
+)
+
+type adapter func(*Mux) *Mux
+
+// New create a pointer to a Mux instance
+func New(adapters ...adapter) *Mux {
+ m := &Mux{Routes: make(map[string][]*Route), Serve: nil, CaseSensitive: true}
+ for _, adap := range adapters {
+ adap(m)
+ }
+ if m.Serve == nil {
+ m.Serve = m.DefaultServe
+ }
+ return m
+}
+
+// Prefix set a default prefix for all routes registred on the router
+func (m *Mux) Prefix(p string) *Mux {
+ m.prefix = strings.TrimSuffix(p, "/")
+ return m
+}
+
+// DefaultServe is the default http request handler
+func (m *Mux) DefaultServe(rw http.ResponseWriter, req *http.Request) {
+ // Check if a route match
+ if !m.parse(rw, req) {
+ // Check if it's a static ressource
+ if !m.staticRoute(rw, req) {
+ // Check if the request path doesn't end with /
+ if !m.validate(rw, req) {
+ // Check if same route exists for another HTTP method
+ if !m.otherMethods(rw, req) {
+ m.HandleNotFound(rw, req)
+ }
+ }
+ }
+ }
+}
+
+// ServeHTTP pass the request to the serve method of Mux
+func (m *Mux) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ if !m.CaseSensitive {
+ req.URL.Path = strings.ToLower(req.URL.Path)
+ }
+ m.Serve(rw, req)
+}
diff --git a/vendor/github.com/go-zoo/bone/helper.go b/vendor/github.com/go-zoo/bone/helper.go
new file mode 100644
index 000000000..bd7b45e95
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/helper.go
@@ -0,0 +1,169 @@
+/********************************
+*** Multiplexer for Go ***
+*** Bone is under MIT license ***
+*** Code by CodingFerret ***
+*** github.com/go-zoo ***
+*********************************/
+
+package bone
+
+import (
+ "net/http"
+ "net/url"
+ "strings"
+)
+
+func (m *Mux) ListenAndServe(port string) error {
+ return http.ListenAndServe(port, m)
+}
+
+func (m *Mux) parse(rw http.ResponseWriter, req *http.Request) bool {
+ for _, r := range m.Routes[req.Method] {
+ ok := r.parse(rw, req)
+ if ok {
+ return true
+ }
+ }
+ // If no HEAD method, default to GET
+ if req.Method == "HEAD" {
+ for _, r := range m.Routes["GET"] {
+ ok := r.parse(rw, req)
+ if ok {
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// StaticRoute check if the request path is for Static route
+func (m *Mux) staticRoute(rw http.ResponseWriter, req *http.Request) bool {
+ for _, s := range m.Routes[static] {
+ if len(req.URL.Path) >= s.Size {
+ if req.URL.Path[:s.Size] == s.Path {
+ s.Handler.ServeHTTP(rw, req)
+ return true
+ }
+ }
+ }
+ return false
+}
+
+// HandleNotFound handle when a request does not match a registered handler.
+func (m *Mux) HandleNotFound(rw http.ResponseWriter, req *http.Request) {
+ if m.notFound != nil {
+ m.notFound.ServeHTTP(rw, req)
+ } else {
+ http.NotFound(rw, req)
+ }
+}
+
+// Check if the path don't end with a /
+func (m *Mux) validate(rw http.ResponseWriter, req *http.Request) bool {
+ plen := len(req.URL.Path)
+ if plen > 1 && req.URL.Path[plen-1:] == "/" {
+ cleanURL(&req.URL.Path)
+ rw.Header().Set("Location", req.URL.String())
+ rw.WriteHeader(http.StatusFound)
+ return true
+ }
+ // Retry to find a route that match
+ return m.parse(rw, req)
+}
+
+func valid(path string) bool {
+ plen := len(path)
+ if plen > 1 && path[plen-1:] == "/" {
+ return false
+ }
+ return true
+}
+
+// Clean url path
+func cleanURL(url *string) {
+ ulen := len((*url))
+ if ulen > 1 {
+ if (*url)[ulen-1:] == "/" {
+ *url = (*url)[:ulen-1]
+ cleanURL(url)
+ }
+ }
+}
+
+// GetValue return the key value, of the current *http.Request
+func GetValue(req *http.Request, key string) string {
+ return GetAllValues(req)[key]
+}
+
+// GetRequestRoute returns the route of given Request
+func (m *Mux) GetRequestRoute(req *http.Request) string {
+ cleanURL(&req.URL.Path)
+ for _, r := range m.Routes[req.Method] {
+ if r.Atts != 0 {
+ if r.Atts&SUB != 0 {
+ return r.Handler.(*Mux).GetRequestRoute(req)
+ }
+ if r.Match(req) {
+ return r.Path
+ }
+ }
+ if req.URL.Path == r.Path {
+ return r.Path
+ }
+ }
+
+ for _, s := range m.Routes[static] {
+ if len(req.URL.Path) >= s.Size {
+ if req.URL.Path[:s.Size] == s.Path {
+ return s.Path
+ }
+ }
+ }
+
+ return "NotFound"
+}
+
+// GetQuery return the key value, of the current *http.Request query
+func GetQuery(req *http.Request, key string) []string {
+ if ok, value := extractQueries(req); ok {
+ return value[key]
+ }
+ return nil
+}
+
+// GetAllQueries return all queries of the current *http.Request
+func GetAllQueries(req *http.Request) map[string][]string {
+ if ok, values := extractQueries(req); ok {
+ return values
+ }
+ return nil
+}
+
+func extractQueries(req *http.Request) (bool, map[string][]string) {
+ if q, err := url.ParseQuery(req.URL.RawQuery); err == nil {
+ var queries = make(map[string][]string)
+ for k, v := range q {
+ for _, item := range v {
+ values := strings.Split(item, ",")
+ queries[k] = append(queries[k], values...)
+ }
+ }
+ return true, queries
+ }
+ return false, nil
+}
+
+func (m *Mux) otherMethods(rw http.ResponseWriter, req *http.Request) bool {
+ for _, met := range method {
+ if met != req.Method {
+ for _, r := range m.Routes[met] {
+ ok := r.exists(rw, req)
+ if ok {
+ rw.WriteHeader(http.StatusMethodNotAllowed)
+ return true
+ }
+ }
+ }
+ }
+ return false
+}
diff --git a/vendor/github.com/go-zoo/bone/helper_15.go b/vendor/github.com/go-zoo/bone/helper_15.go
new file mode 100644
index 000000000..068ce18e0
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/helper_15.go
@@ -0,0 +1,45 @@
+// +build !go1.7
+
+/********************************
+*** Multiplexer for Go ***
+*** Bone is under MIT license ***
+*** Code by CodingFerret ***
+*** github.com/go-zoo ***
+*********************************/
+
+package bone
+
+import (
+ "net/http"
+ "sync"
+)
+
+var globalVars = struct {
+ sync.RWMutex
+ v map[*http.Request]map[string]string
+}{v: make(map[*http.Request]map[string]string)}
+
+// GetAllValues return the req PARAMs
+func GetAllValues(req *http.Request) map[string]string {
+ globalVars.RLock()
+ values := globalVars.v[req]
+ globalVars.RUnlock()
+ return values
+}
+
+// serveMatchedRequest is an extension point for Route which allows us to conditionally compile for
+// go1.7 and <go1.7
+func (r *Route) serveMatchedRequest(rw http.ResponseWriter, req *http.Request, vars map[string]string) {
+ globalVars.Lock()
+ globalVars.v[req] = vars
+ globalVars.Unlock()
+
+ // Regardless if ServeHTTP panics (and potentially recovers) we can make sure to not leak
+ // memory in globalVars for this request
+ defer func() {
+ globalVars.Lock()
+ delete(globalVars.v, req)
+ globalVars.Unlock()
+ }()
+ r.Handler.ServeHTTP(rw, req)
+}
diff --git a/vendor/github.com/go-zoo/bone/helper_17.go b/vendor/github.com/go-zoo/bone/helper_17.go
new file mode 100644
index 000000000..2e41ea4be
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/helper_17.go
@@ -0,0 +1,39 @@
+// +build go1.7
+
+/********************************
+*** Multiplexer for Go ***
+*** Bone is under MIT license ***
+*** Code by CodingFerret ***
+*** github.com/go-zoo ***
+*********************************/
+
+package bone
+
+import (
+ "context"
+ "net/http"
+)
+
+// contextKeyType is a private struct that is used for storing bone values in net.Context
+type contextKeyType struct{}
+
+// contextKey is the key that is used to store bone values in the net.Context for each request
+var contextKey = contextKeyType{}
+
+// GetAllValues return the req PARAMs
+func GetAllValues(req *http.Request) map[string]string {
+ values, ok := req.Context().Value(contextKey).(map[string]string)
+ if ok {
+ return values
+ }
+
+ return map[string]string{}
+}
+
+// serveMatchedRequest is an extension point for Route which allows us to conditionally compile for
+// go1.7 and <go1.7
+func (r *Route) serveMatchedRequest(rw http.ResponseWriter, req *http.Request, vars map[string]string) {
+ ctx := context.WithValue(req.Context(), contextKey, vars)
+ newReq := req.WithContext(ctx)
+ r.Handler.ServeHTTP(rw, newReq)
+}
diff --git a/vendor/github.com/go-zoo/bone/mux.go b/vendor/github.com/go-zoo/bone/mux.go
new file mode 100644
index 000000000..0ec29a338
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/mux.go
@@ -0,0 +1,137 @@
+/********************************
+*** Multiplexer for Go ***
+*** Bone is under MIT license ***
+*** Code by CodingFerret ***
+*** github.com/go-zoo ***
+*********************************/
+
+package bone
+
+import "net/http"
+
+// Router is the same as a http.Handler
+type Router interface {
+ ServeHTTP(http.ResponseWriter, *http.Request)
+}
+
+// Register the route in the router
+func (m *Mux) Register(method string, path string, handler http.Handler) *Route {
+ return m.register(method, path, handler)
+}
+
+// GetFunc add a new route to the Mux with the Get method
+func (m *Mux) GetFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("GET", path, handler)
+}
+
+// PostFunc add a new route to the Mux with the Post method
+func (m *Mux) PostFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("POST", path, handler)
+}
+
+// PutFunc add a new route to the Mux with the Put method
+func (m *Mux) PutFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("PUT", path, handler)
+}
+
+// DeleteFunc add a new route to the Mux with the Delete method
+func (m *Mux) DeleteFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("DELETE", path, handler)
+}
+
+// HeadFunc add a new route to the Mux with the Head method
+func (m *Mux) HeadFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("HEAD", path, handler)
+}
+
+// PatchFunc add a new route to the Mux with the Patch method
+func (m *Mux) PatchFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("PATCH", path, handler)
+}
+
+// OptionsFunc add a new route to the Mux with the Options method
+func (m *Mux) OptionsFunc(path string, handler http.HandlerFunc) *Route {
+ return m.register("OPTIONS", path, handler)
+}
+
+// NotFoundFunc the mux custom 404 handler
+func (m *Mux) NotFoundFunc(handler http.HandlerFunc) {
+ m.notFound = handler
+}
+
+// Handle add a new route to the Mux without a HTTP method
+func (m *Mux) Handle(path string, handler http.Handler) {
+ for _, mt := range method {
+ m.register(mt, path, handler)
+ }
+}
+
+// HandleFunc is use to pass a func(http.ResponseWriter, *Http.Request) instead of http.Handler
+func (m *Mux) HandleFunc(path string, handler http.HandlerFunc) {
+ m.Handle(path, handler)
+}
+
+// Get add a new route to the Mux with the Get method
+func (m *Mux) Get(path string, handler http.Handler) *Route {
+ return m.register("GET", path, handler)
+}
+
+// Post add a new route to the Mux with the Post method
+func (m *Mux) Post(path string, handler http.Handler) *Route {
+ return m.register("POST", path, handler)
+}
+
+// Put add a new route to the Mux with the Put method
+func (m *Mux) Put(path string, handler http.Handler) *Route {
+ return m.register("PUT", path, handler)
+}
+
+// Delete add a new route to the Mux with the Delete method
+func (m *Mux) Delete(path string, handler http.Handler) *Route {
+ return m.register("DELETE", path, handler)
+}
+
+// Head add a new route to the Mux with the Head method
+func (m *Mux) Head(path string, handler http.Handler) *Route {
+ return m.register("HEAD", path, handler)
+}
+
+// Patch add a new route to the Mux with the Patch method
+func (m *Mux) Patch(path string, handler http.Handler) *Route {
+ return m.register("PATCH", path, handler)
+}
+
+// Options add a new route to the Mux with the Options method
+func (m *Mux) Options(path string, handler http.Handler) *Route {
+ return m.register("OPTIONS", path, handler)
+}
+
+// NotFound the mux custom 404 handler
+func (m *Mux) NotFound(handler http.Handler) {
+ m.notFound = handler
+}
+
+// Register the new route in the router with the provided method and handler
+func (m *Mux) register(method string, path string, handler http.Handler) *Route {
+ r := NewRoute(m.prefix+path, handler)
+ r.Method = method
+ if valid(path) {
+ m.Routes[method] = append(m.Routes[method], r)
+ return r
+ }
+ m.Routes[static] = append(m.Routes[static], r)
+ return r
+}
+
+// SubRoute register a router as a SubRouter of bone
+func (m *Mux) SubRoute(path string, router Router) *Route {
+ r := NewRoute(m.prefix+path, router)
+ if valid(path) {
+ r.Atts += SUB
+ for _, mt := range method {
+ m.Routes[mt] = append(m.Routes[mt], r)
+ }
+ return r
+ }
+ return nil
+}
diff --git a/vendor/github.com/go-zoo/bone/route.go b/vendor/github.com/go-zoo/bone/route.go
new file mode 100644
index 000000000..7f6c1b1d0
--- /dev/null
+++ b/vendor/github.com/go-zoo/bone/route.go
@@ -0,0 +1,245 @@
+/********************************
+*** Multiplexer for Go ***
+*** Bone is under MIT license ***
+*** Code by CodingFerret ***
+*** github.com/go-zoo ***
+*********************************/
+
+package bone
+
+import (
+ "net/http"
+ "regexp"
+ "strings"
+)
+
+const (
+ //PARAM value store in Atts if the route have parameters
+ PARAM = 2
+ //SUB value store in Atts if the route is a sub router
+ SUB = 4
+ //WC value store in Atts if the route have wildcard
+ WC = 8
+ //REGEX value store in Atts if the route contains regex
+ REGEX = 16
+)
+
+// Route content the required information for a valid route
+// Path: is the Route URL
+// Size: is the length of the path
+// Token: is the value of each part of the path, split by /
+// Pattern: is content information about the route, if it's have a route variable
+// handler: is the handler who handle this route
+// Method: define HTTP method on the route
+type Route struct {
+ Path string
+ Method string
+ Size int
+ Atts int
+ wildPos int
+ Token Token
+ Pattern map[int]string
+ Compile map[int]*regexp.Regexp
+ Tag map[int]string
+ Handler http.Handler
+}
+
+// Token content all value of a spliting route path
+// Tokens: string value of each token
+// size: number of token
+type Token struct {
+ raw []int
+ Tokens []string
+ Size int
+}
+
+// NewRoute return a pointer to a Route instance and call save() on it
+func NewRoute(url string, h http.Handler) *Route {
+ r := &Route{Path: url, Handler: h}
+ r.save()
+ return r
+}
+
+// Save, set automatically the the Route.Size and Route.Pattern value
+func (r *Route) save() {
+ r.Size = len(r.Path)
+ r.Token.Tokens = strings.Split(r.Path, "/")
+ for i, s := range r.Token.Tokens {
+ if len(s) >= 1 {
+ switch s[:1] {
+ case ":":
+ if r.Pattern == nil {
+ r.Pattern = make(map[int]string)
+ }
+ r.Pattern[i] = s[1:]
+ r.Atts |= PARAM
+ case "#":
+ if r.Compile == nil {
+ r.Compile = make(map[int]*regexp.Regexp)
+ r.Tag = make(map[int]string)
+ }
+ tmp := strings.Split(s, "^")
+ r.Tag[i] = tmp[0][1:]
+ r.Compile[i] = regexp.MustCompile("^" + tmp[1][:len(tmp[1])-1])
+ r.Atts |= REGEX
+ case "*":
+ r.wildPos = i
+ r.Atts |= WC
+ default:
+ r.Token.raw = append(r.Token.raw, i)
+ }
+ }
+ r.Token.Size++
+ }
+}
+
+// Match check if the request match the route Pattern
+func (r *Route) Match(req *http.Request) bool {
+ ok, _ := r.matchAndParse(req)
+ return ok
+}
+
+// matchAndParse check if the request matches the route Pattern and returns a map of the parsed
+// variables if it matches
+func (r *Route) matchAndParse(req *http.Request) (bool, map[string]string) {
+ ss := strings.Split(req.URL.EscapedPath(), "/")
+ if r.matchRawTokens(&ss) {
+ if len(ss) == r.Token.Size || r.Atts&WC != 0 {
+ totalSize := len(r.Pattern)
+ if r.Atts&REGEX != 0 {
+ totalSize += len(r.Compile)
+ }
+
+ vars := make(map[string]string, totalSize)
+ for k, v := range r.Pattern {
+ vars[v] = ss[k]
+ }
+
+ if r.Atts&REGEX != 0 {
+ for k, v := range r.Compile {
+ if !v.MatchString(ss[k]) {
+ return false, nil
+ }
+ vars[r.Tag[k]] = ss[k]
+ }
+ }
+
+ return true, vars
+ }
+ }
+
+ return false, nil
+}
+
+func (r *Route) parse(rw http.ResponseWriter, req *http.Request) bool {
+ if r.Atts != 0 {
+ if r.Atts&SUB != 0 {
+ if len(req.URL.Path) >= r.Size {
+ if req.URL.Path[:r.Size] == r.Path {
+ req.URL.Path = req.URL.Path[r.Size:]
+ r.Handler.ServeHTTP(rw, req)
+ return true
+ }
+ }
+ }
+
+ if ok, vars := r.matchAndParse(req); ok {
+ r.serveMatchedRequest(rw, req, vars)
+ return true
+ }
+ }
+ if req.URL.Path == r.Path {
+ r.Handler.ServeHTTP(rw, req)
+ return true
+ }
+ return false
+}
+
+func (r *Route) matchRawTokens(ss *[]string) bool {
+ if len(*ss) >= r.Token.Size {
+ for i, v := range r.Token.raw {
+ if (*ss)[v] != r.Token.Tokens[v] {
+ if r.Atts&WC != 0 && r.wildPos == i {
+ return true
+ }
+ return false
+ }
+ }
+ return true
+ }
+ return false
+}
+
+func (r *Route) exists(rw http.ResponseWriter, req *http.Request) bool {
+ if r.Atts != 0 {
+ if r.Atts&SUB != 0 {
+ if len(req.URL.Path) >= r.Size {
+ if req.URL.Path[:r.Size] == r.Path {
+ return true
+ }
+ }
+ }
+
+ if ok, _ := r.matchAndParse(req); ok {
+ return true
+ }
+ }
+ if req.URL.Path == r.Path {
+ return true
+ }
+ return false
+}
+
+// Get set the route method to Get
+func (r *Route) Get() *Route {
+ r.Method = "GET"
+ return r
+}
+
+// Post set the route method to Post
+func (r *Route) Post() *Route {
+ r.Method = "POST"
+ return r
+}
+
+// Put set the route method to Put
+func (r *Route) Put() *Route {
+ r.Method = "PUT"
+ return r
+}
+
+// Delete set the route method to Delete
+func (r *Route) Delete() *Route {
+ r.Method = "DELETE"
+ return r
+}
+
+// Head set the route method to Head
+func (r *Route) Head() *Route {
+ r.Method = "HEAD"
+ return r
+}
+
+// Patch set the route method to Patch
+func (r *Route) Patch() *Route {
+ r.Method = "PATCH"
+ return r
+}
+
+// Options set the route method to Options
+func (r *Route) Options() *Route {
+ r.Method = "OPTIONS"
+ return r
+}
+
+func (r *Route) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
+ if r.Method != "" {
+ if req.Method == r.Method {
+ r.Handler.ServeHTTP(rw, req)
+ return
+ }
+ http.NotFound(rw, req)
+ return
+ }
+ r.Handler.ServeHTTP(rw, req)
+}