From f7395c6262d0762780fb926a1547a58a4aaa7d09 Mon Sep 17 00:00:00 2001 From: Jordi Martin Date: Sun, 26 Feb 2023 23:30:58 +0100 Subject: [PATCH] Fixed the router allow url that contains uri --- config/urn.yaml | 10 +++++++ go.mod | 1 - go.sum | 2 -- pkg/match/request.go | 9 +++--- pkg/route/route.go | 65 +++++++++++++++++++++++++++++++++++++++++ pkg/route/route_test.go | 45 ++++++++++++++++++++++++++++ pkg/vars/request.go | 6 ++-- 7 files changed, 127 insertions(+), 11 deletions(-) create mode 100644 config/urn.yaml create mode 100644 pkg/route/route.go create mode 100644 pkg/route/route_test.go diff --git a/config/urn.yaml b/config/urn.yaml new file mode 100644 index 0000000..6b3ced4 --- /dev/null +++ b/config/urn.yaml @@ -0,0 +1,10 @@ +--- +request: + method: GET + path: /api/v1/notes/urn:organization:notebook:eu:note:123 +response: + statusCode: 200 + headers: + Content-Type: + - "application/json" + body: "It works" \ No newline at end of file diff --git a/go.mod b/go.mod index 7c7fe65..7a2de0e 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/jmartin82/mmock/v3 go 1.14 require ( - github.com/azer/url-router v0.0.0-20140924232216-1a0aa252538c github.com/basgys/goxml2json v1.1.0 github.com/bitly/go-simplejson v0.5.0 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect diff --git a/go.sum b/go.sum index 74e89a5..53658bc 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,6 @@ github.com/Masterminds/glide v0.13.2/go.mod h1:STyF5vcenH/rUqTEv+/hBXlSTo7KYwg2oc2f4tzPWic= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/vcs v1.13.0/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= -github.com/azer/url-router v0.0.0-20140924232216-1a0aa252538c h1:vpYPra7G75NhuxN28VqQhTepM8a6c201AsJWdRaINqY= -github.com/azer/url-router v0.0.0-20140924232216-1a0aa252538c/go.mod h1:YT0FE3RD8ecPJBNkCdpeEAdZXPZgD2CqcRtpwuzjt9M= github.com/basgys/goxml2json v1.1.0 h1:4ln5i4rseYfXNd86lGEB+Vi652IsIXIvggKM/BhUKVw= github.com/basgys/goxml2json v1.1.0/go.mod h1:wH7a5Np/Q4QoECFIU8zTQlZwZkrilY0itPfecMw41Dw= github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= diff --git a/pkg/match/request.go b/pkg/match/request.go index cafb00f..d3c2e4b 100644 --- a/pkg/match/request.go +++ b/pkg/match/request.go @@ -7,8 +7,7 @@ import ( "github.com/jmartin82/mmock/v3/pkg/match/payload" "github.com/jmartin82/mmock/v3/pkg/mock" - - urlmatcher "github.com/azer/url-router" + "github.com/jmartin82/mmock/v3/pkg/route" "github.com/ryanuber/go-glob" ) @@ -132,14 +131,14 @@ func (mm Request) matchScenarioState(scenario *mock.Scenario) bool { return false } -//Matcher checks if the received request matches with some specific mock request config. +// Matcher checks if the received request matches with some specific mock request config. type Matcher interface { Match(req *mock.Request, mock *mock.Definition, scenarioAware bool) (bool, error) } func (mm Request) Match(req *mock.Request, mock *mock.Definition, scenarioAware bool) (bool, error) { - routes := urlmatcher.New(mock.Request.Path) + route := route.NewRoute(mock.Request.Path) if !mm.matchOnEqualsOrIfEmptyOrGlob(req.Host, mock.Request.Host) { return false, fmt.Errorf("Host not match. Actual: %s, Expected: %s", req.Host, mock.Request.Host) @@ -153,7 +152,7 @@ func (mm Request) Match(req *mock.Request, mock *mock.Definition, scenarioAware return false, fmt.Errorf("Fragment not match. Actual: %s, Expected: %s", req.Fragment, mock.Request.Fragment) } - if !glob.Glob(mock.Request.Path, req.Path) && routes.Match(req.Path) == nil { + if !glob.Glob(mock.Request.Path, req.Path) && route.Match(req.Path) == nil { return false, fmt.Errorf("Path not match. Actual: %s, Expected: %s", req.Path, mock.Request.Path) } diff --git a/pkg/route/route.go b/pkg/route/route.go new file mode 100644 index 0000000..6fded91 --- /dev/null +++ b/pkg/route/route.go @@ -0,0 +1,65 @@ +package route + +import ( + "fmt" + "regexp" + "strings" +) + +type Route struct { + Keys []string + Regex *regexp.Regexp + Pattern string +} + +type Match struct { + Params Params + Pattern string +} + +type Params map[string]string + +func (route *Route) Params(url string) Params { + match := route.Regex.FindAllStringSubmatch(url, -1)[0][1:] + result := make(Params) + + for i := range match { + if len(route.Keys) <= i { + break + } + + result[route.Keys[i]] = match[i] + } + + return result +} +func (route *Route) Match(url string) *Match { + if route.Regex == nil || !route.Regex.MatchString(url) { + return nil + } + return &Match{route.Params(url), route.Pattern} +} + +func NewRoute(pattern string) *Route { + regex, keys := pathToRegex(pattern) + return &Route{keys, regex, pattern} +} + +func pathToRegex(path string) (*regexp.Regexp, []string) { + pattern, _ := regexp.Compile("\\/:([A-Za-z0-9]+)") + matches := pattern.FindAllStringSubmatch(path, -1) + keys := []string{} + + for i := range matches { + keys = append(keys, matches[i][1]) + } + + str := fmt.Sprintf("^%s\\/?$", strings.Replace(path, "/", "\\/", -1)) + + str = pattern.ReplaceAllString(str, "/([^\\/]+)") + str = strings.Replace(str, ".", "\\.", -1) + + regex, _ := regexp.Compile(str) + + return regex, keys +} diff --git a/pkg/route/route_test.go b/pkg/route/route_test.go new file mode 100644 index 0000000..f586674 --- /dev/null +++ b/pkg/route/route_test.go @@ -0,0 +1,45 @@ +package route + +import ( + "fmt" + "testing" +) + +func TestMatching(t *testing.T) { + + route := NewRoute("/user/:name") + equal(t, route.Match("/user/azer").Pattern, "/user/:name") + + route = NewRoute("/fruits/:fruit") + equal(t, route.Match("/fruits/watermelon").Pattern, "/fruits/:fruit") + + route = NewRoute("/fruits/:fruit/:page") + equal(t, route.Match("/fruits/cherry/452").Pattern, "/fruits/:fruit/:page") + + route = NewRoute("/api/urn:note:123") + equal(t, route.Match("/api/urn:note:123").Pattern, "/api/urn:note:123") + + route = NewRoute("/api/:userid.json") + equal(t, route.Match("/api/99.json").Pattern, "/api/:userid.json") + + route = NewRoute("/") + equal(t, route.Match("/").Pattern, "/") +} + +func TestParams(t *testing.T) { + route := NewRoute("/user/:name") + equal(t, route.Match("/user/azer").Params["name"], "azer") + + route = NewRoute("/fruits/:fruit") + equal(t, route.Match("/fruits/watermelon").Params["fruit"], "watermelon") + + route = NewRoute("/fruits/:fruit/:page") + equal(t, route.Match("/fruits/cherry/452").Params["fruit"], "cherry") + equal(t, route.Match("/fruits/cherry/452").Params["page"], "452") +} + +func equal(t *testing.T, a string, b string) { + if a != b { + t.Error(fmt.Sprintf("%s and %s aren't equal", a, b)) + } +} diff --git a/pkg/vars/request.go b/pkg/vars/request.go index ad6e38d..fddc60f 100644 --- a/pkg/vars/request.go +++ b/pkg/vars/request.go @@ -9,8 +9,8 @@ import ( "strings" "github.com/jmartin82/mmock/v3/pkg/mock" + "github.com/jmartin82/mmock/v3/pkg/route" - urlmatcher "github.com/azer/url-router" xj "github.com/basgys/goxml2json" "github.com/tidwall/gjson" ) @@ -115,8 +115,8 @@ func (rp Request) getUrl() (string, bool) { func (rp Request) getPathParam(name string) (string, bool) { - routes := urlmatcher.New(rp.Mock.Request.Path) - mparm := routes.Match(rp.Request.Path) + route := route.NewRoute(rp.Mock.Request.Path) + mparm := route.Match(rp.Request.Path) value, f := mparm.Params[name] if !f {