Skip to content

Commit

Permalink
Merge pull request #57 from ceriath/master
Browse files Browse the repository at this point in the history
fix route matching issues
  • Loading branch information
vardius authored Jan 1, 2024
2 parents 22b8d79 + b544f4b commit 94183f7
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 70 deletions.
10 changes: 5 additions & 5 deletions doc.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
/*
Package gorouter provide request router with middleware
Router
# Router
The router determines how to handle http request.
GoRouter uses a routing tree. Once one branch of the tree matches, only routes inside that branch are considered,
not any routes after that branch. When instantiating router, the root node of tree is created.
Route types
# Route types
- Static `/hello` (will match requests matching given route)
- Named `/{name}` (will match requests matching given route scheme)
- Regexp `/{name:[a-z]+}` (will match requests matching given route scheme and its regexp)
Wildcards
# Wildcards
The values of *named parameter* or *regexp parameters* are accessible via *request context*
`params, ok := context.Parameters(req.Context())`.
You can get the value of a parameter either by its index in the slice, or by using the `params.Value(name)` method:
`:name` or `/{name:[a-z]+}` can be retrieved by `params.Value("name")`.
Defining Routes
# Defining Routes
A full route definition contain up to three parts:
Expand All @@ -35,7 +35,7 @@ and can contain named wildcard placeholders *(e.g. {placeholder})* to match dyna
Take the following example:
import "github.com/vardius/gorouter/v4/context"
import "github.com/ceriath/gorouter/v4/context"
router.GET("/hello/{name:r([a-z]+)go}", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
params, _ := context.Parameters(r.Context())
Expand Down
4 changes: 2 additions & 2 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

"github.com/valyala/fasthttp"

"github.com/vardius/gorouter/v4"
"github.com/vardius/gorouter/v4/context"
"github.com/ceriath/gorouter/v4"
"github.com/ceriath/gorouter/v4/context"
)

func handleNetHTTPRequest(method, path string, handler http.Handler) {
Expand Down
43 changes: 29 additions & 14 deletions fasthttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,26 @@ package gorouter
import (
"strings"

pathutils "github.com/vardius/gorouter/v4/path"
pathutils "github.com/ceriath/gorouter/v4/path"

"github.com/valyala/fasthttp"

"github.com/vardius/gorouter/v4/middleware"
"github.com/vardius/gorouter/v4/mux"
"github.com/ceriath/gorouter/v4/middleware"
"github.com/ceriath/gorouter/v4/mux"
)

var allFasthttpMethods = []string{
fasthttp.MethodGet,
fasthttp.MethodHead,
fasthttp.MethodPost,
fasthttp.MethodPut,
fasthttp.MethodPatch,
fasthttp.MethodDelete,
fasthttp.MethodConnect,
fasthttp.MethodOptions,
fasthttp.MethodTrace,
}

// NewFastHTTPRouter creates new Router instance, returns pointer
func NewFastHTTPRouter(fs ...FastHTTPMiddlewareFunc) FastHTTPRouter {
globalMiddleware := transformFastHTTPMiddlewareFunc(fs...)
Expand Down Expand Up @@ -86,6 +98,19 @@ func (r *fastHTTPRouter) USE(method, path string, fs ...FastHTTPMiddlewareFunc)
r.middlewareCounter += uint(len(m))
}

func (r *fastHTTPRouter) USEANY(path string, fs ...FastHTTPMiddlewareFunc) {
m := transformFastHTTPMiddlewareFunc(fs...)
for i, mf := range m {
m[i] = middleware.WithPriority(mf, r.middlewareCounter)
}

for _, method := range allFasthttpMethods {
r.tree = r.tree.WithMiddleware(method+path, m, 0)
}

r.middlewareCounter += uint(len(m))
}

func (r *fastHTTPRouter) Handle(method, path string, h fasthttp.RequestHandler) {
route := newRoute(h)

Expand All @@ -100,17 +125,7 @@ func (r *fastHTTPRouter) Mount(path string, h fasthttp.RequestHandler) {
h(ctx)
}))

for _, method := range []string{
fasthttp.MethodGet,
fasthttp.MethodHead,
fasthttp.MethodPost,
fasthttp.MethodPut,
fasthttp.MethodPatch,
fasthttp.MethodDelete,
fasthttp.MethodConnect,
fasthttp.MethodOptions,
fasthttp.MethodTrace,
} {
for _, method := range allFasthttpMethods {
r.tree = r.tree.WithSubrouter(method+path, route, 0)
}
}
Expand Down
2 changes: 1 addition & 1 deletion fasthttp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

"github.com/valyala/fasthttp"

"github.com/vardius/gorouter/v4/context"
"github.com/ceriath/gorouter/v4/context"
)

func buildFastHTTPRequestContext(method, path string) *fasthttp.RequestCtx {
Expand Down
11 changes: 7 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
module github.com/vardius/gorouter/v4
module github.com/ceriath/gorouter/v4

go 1.15
go 1.20

require github.com/valyala/fasthttp v1.50.0

require (
github.com/klauspost/compress v1.10.11 // indirect
github.com/valyala/fasthttp v1.16.0
github.com/andybalholm/brotli v1.0.6 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
)
21 changes: 6 additions & 15 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/klauspost/compress v1.10.7 h1:7rix8v8GpI3ZBb0nSozFRgbtXKv+hOe+qfEpZqybrAg=
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.10.11 h1:K9z59aO18Aywg2b/WSgBaUX99mHy2BES18Cr5lBKZHk=
github.com/klauspost/compress v1.10.11/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.16.0 h1:9zAqOYLl8Tuy3E5R6ckzGDJ1g8+pw15oQp2iL9Jl6gQ=
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M=
github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
15 changes: 8 additions & 7 deletions mux/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package mux
import (
"regexp"

"github.com/vardius/gorouter/v4/context"
"github.com/vardius/gorouter/v4/middleware"
pathutils "github.com/vardius/gorouter/v4/path"
"github.com/ceriath/gorouter/v4/context"
"github.com/ceriath/gorouter/v4/middleware"
pathutils "github.com/ceriath/gorouter/v4/path"
)

// NewNode provides new mux Node
Expand Down Expand Up @@ -99,11 +99,12 @@ func (n *staticNode) MatchRoute(path string) (Route, context.Params) {
pathLength := len(path)

if pathLength >= nameLength && n.name == path[:nameLength] {
if nameLength+1 >= pathLength || n.skipSubPath {
if nameLength == pathLength || n.skipSubPath {
return n.route, make(context.Params, n.maxParamsSize)
}

return n.children.MatchRoute(path[nameLength+1:]) // +1 because we wan to skip slash as well
if path[nameLength:nameLength+1] == "/" { // skip slashes only
return n.children.MatchRoute(path[nameLength+1:]) // +1 because we wan to skip slash as well
}
}

return nil, nil
Expand All @@ -114,7 +115,7 @@ func (n *staticNode) MatchMiddleware(path string) middleware.Collection {
pathLength := len(path)

if pathLength >= nameLength && n.name == path[:nameLength] {
if nameLength+1 >= pathLength || n.skipSubPath {
if nameLength == pathLength || n.skipSubPath {
return n.middleware
}

Expand Down
6 changes: 3 additions & 3 deletions mux/tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import (
"sort"
"strings"

"github.com/vardius/gorouter/v4/context"
"github.com/vardius/gorouter/v4/middleware"
pathutils "github.com/vardius/gorouter/v4/path"
"github.com/ceriath/gorouter/v4/context"
"github.com/ceriath/gorouter/v4/middleware"
pathutils "github.com/ceriath/gorouter/v4/path"
)

// NewTree provides new empty Tree
Expand Down
45 changes: 30 additions & 15 deletions nethttp.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,24 @@ import (
"net/url"
"strings"

"github.com/vardius/gorouter/v4/context"
"github.com/vardius/gorouter/v4/middleware"
"github.com/vardius/gorouter/v4/mux"
pathutils "github.com/vardius/gorouter/v4/path"
"github.com/ceriath/gorouter/v4/context"
"github.com/ceriath/gorouter/v4/middleware"
"github.com/ceriath/gorouter/v4/mux"
pathutils "github.com/ceriath/gorouter/v4/path"
)

var allNethttpMethods = []string{
http.MethodGet,
http.MethodHead,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
http.MethodConnect,
http.MethodOptions,
http.MethodTrace,
}

// New creates new net/http Router instance, returns pointer
func New(fs ...MiddlewareFunc) Router {
globalMiddleware := transformMiddlewareFunc(fs...)
Expand Down Expand Up @@ -85,6 +97,19 @@ func (r *router) USE(method, path string, fs ...MiddlewareFunc) {
r.middlewareCounter += uint(len(m))
}

func (r *router) USEANY(path string, fs ...MiddlewareFunc) {
m := transformMiddlewareFunc(fs...)
for i, mf := range m {
m[i] = middleware.WithPriority(mf, r.middlewareCounter)
}

for _, method := range allNethttpMethods {
r.tree = r.tree.WithMiddleware(method+path, m, 0)
}

r.middlewareCounter += uint(len(m))
}

func (r *router) Handle(method, path string, h http.Handler) {
route := newRoute(h)

Expand All @@ -97,17 +122,7 @@ func (r *router) Mount(path string, h http.Handler) {
h.ServeHTTP(w, pathRewrite(r))
}))

for _, method := range []string{
http.MethodGet,
http.MethodHead,
http.MethodPost,
http.MethodPut,
http.MethodPatch,
http.MethodDelete,
http.MethodConnect,
http.MethodOptions,
http.MethodTrace,
} {
for _, method := range allNethttpMethods {
r.tree = r.tree.WithSubrouter(method+path, route, 0)
}
}
Expand Down
2 changes: 1 addition & 1 deletion nethttp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"strings"
"testing"

"github.com/vardius/gorouter/v4/context"
"github.com/ceriath/gorouter/v4/context"
)

func TestInterface(t *testing.T) {
Expand Down
4 changes: 2 additions & 2 deletions route_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import (
"net/http/httptest"
"testing"

"github.com/vardius/gorouter/v4/context"
"github.com/vardius/gorouter/v4/middleware"
"github.com/ceriath/gorouter/v4/context"
"github.com/ceriath/gorouter/v4/middleware"
)

func TestRouter(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions router.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ type Router interface {
// to whole router branch under given method and patter
USE(method, pattern string, fs ...MiddlewareFunc)

// USEANY adds middleware functions ([]MiddlewareFunc)
// to whole router branch for all methods and patter
USEANY(pattern string, fs ...MiddlewareFunc)

// Handle adds http.Handler as router handler
// under given method and patter
Handle(method, pattern string, handler http.Handler)
Expand Down Expand Up @@ -127,6 +131,10 @@ type FastHTTPRouter interface {
// to whole router branch under given method and patter
USE(method, pattern string, fs ...FastHTTPMiddlewareFunc)

// USEANY adds middleware functions ([]MiddlewareFunc)
// to whole router branch for all methods and patter
USEANY(pattern string, fs ...FastHTTPMiddlewareFunc)

// Handle adds fasthttp.RequestHandler as router handler
// under given method and patter
Handle(method, pattern string, handler fasthttp.RequestHandler)
Expand Down
2 changes: 1 addition & 1 deletion tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package gorouter
import (
"net/http"

"github.com/vardius/gorouter/v4/mux"
"github.com/ceriath/gorouter/v4/mux"
)

func allowed(t mux.Tree, method, path string) (allow string) {
Expand Down

0 comments on commit 94183f7

Please sign in to comment.