From 84a107d9abc12440569b220aaf290ec827a8b34d Mon Sep 17 00:00:00 2001 From: Rohan Date: Fri, 1 Dec 2023 17:20:18 +0000 Subject: [PATCH 1/7] Add router endpoint pattern method onto the Typhon Request --- request.go | 18 +++++++++++++++++- request_test.go | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/request.go b/request.go index 91b40244..3ebbe003 100644 --- a/request.go +++ b/request.go @@ -183,7 +183,7 @@ func (r *Request) BodyBytes(consume bool) ([]byte, error) { // Send round-trips the request via the default Client. It does not block, instead returning a ResponseFuture // representing the asynchronous operation to produce the response. It is equivalent to: // -// r.SendVia(Client) +// r.SendVia(Client) func (r Request) Send() *ResponseFuture { return Send(r) } @@ -213,6 +213,22 @@ func (r Request) ResponseWithCode(body interface{}, statusCode int) Response { return rsp } +// RouterEndpointPattern finds the router pattern that matches the request. This is only callable while the request +// is being served. +func (r Request) RouterEndpointPattern() string { + if router := RouterForRequest(r); router != nil { + if pathPattern := router.Pattern(r); pathPattern != "" { + return pathPattern + } + } + return "" +} + +// RequestMethod returns the HTTP method of the request +func (r Request) RequestMethod() string { + return r.Method +} + func (r Request) String() string { if r.URL == nil { return "Request(Unknown)" diff --git a/request_test.go b/request_test.go index bd1cc00d..591b22b4 100644 --- a/request_test.go +++ b/request_test.go @@ -7,6 +7,7 @@ import ( "encoding/json" "io/ioutil" "math" + "net/http" "strings" "testing" @@ -223,6 +224,27 @@ func TestRequestSetMetadata(t *testing.T) { assert.Equal(t, []string{"data"}, req.Request.Header["meta"]) } +func TestRouterEndpointPattern(t *testing.T) { + req := NewRequest(context.Background(), http.MethodGet, "/foo/some-url-identifier", nil) + assert.Equal(t, "", req.RouterEndpointPattern()) // should be empty if request has not been served by a router + + router := Router{} + routerEndpointPattern := "/foo/:id" + router.GET(routerEndpointPattern, func(req Request) Response { + // as we are currently serving the request, we should be able to get the router endpoint pattern + assert.Equal(t, routerEndpointPattern, req.RouterEndpointPattern()) + return req.Response(nil) + }) + + rsp := req.SendVia(router.Serve()).Response() + require.NoError(t, rsp.Error) // check we didn't get a "route not found" error +} + +func TestRequestMethod(t *testing.T) { + req := NewRequest(context.Background(), http.MethodGet, "", nil) + assert.Equal(t, http.MethodGet, req.RequestMethod()) +} + func jsonStreamMarshal(v interface{}) ([]byte, error) { var buffer bytes.Buffer writer := bufio.NewWriter(&buffer) From e9f92133a5f39119d9e01414d2c52f06f3fa6579 Mon Sep 17 00:00:00 2001 From: Rohan Date: Fri, 1 Dec 2023 18:17:43 +0000 Subject: [PATCH 2/7] Rename function and store path pattern inside context --- request.go | 12 +++--------- request_test.go | 4 ++-- router.go | 43 +++++++++++++++++++++++++++++++------------ 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/request.go b/request.go index 3ebbe003..c01d2ebe 100644 --- a/request.go +++ b/request.go @@ -213,15 +213,9 @@ func (r Request) ResponseWithCode(body interface{}, statusCode int) Response { return rsp } -// RouterEndpointPattern finds the router pattern that matches the request. This is only callable while the request -// is being served. -func (r Request) RouterEndpointPattern() string { - if router := RouterForRequest(r); router != nil { - if pathPattern := router.Pattern(r); pathPattern != "" { - return pathPattern - } - } - return "" +// RequestPathPattern finds the router entry pattern that matches the request +func (r Request) RequestPathPattern() string { + return routerEntryPathPatternForRequest(r) } // RequestMethod returns the HTTP method of the request diff --git a/request_test.go b/request_test.go index 591b22b4..e83ca296 100644 --- a/request_test.go +++ b/request_test.go @@ -226,13 +226,13 @@ func TestRequestSetMetadata(t *testing.T) { func TestRouterEndpointPattern(t *testing.T) { req := NewRequest(context.Background(), http.MethodGet, "/foo/some-url-identifier", nil) - assert.Equal(t, "", req.RouterEndpointPattern()) // should be empty if request has not been served by a router + assert.Equal(t, "", req.RequestPathPattern()) // should be empty if request has not been served by a router router := Router{} routerEndpointPattern := "/foo/:id" router.GET(routerEndpointPattern, func(req Request) Response { // as we are currently serving the request, we should be able to get the router endpoint pattern - assert.Equal(t, routerEndpointPattern, req.RouterEndpointPattern()) + assert.Equal(t, routerEndpointPattern, req.RequestPathPattern()) return req.Response(nil) }) diff --git a/router.go b/router.go index ff3e3f3e..7746076f 100644 --- a/router.go +++ b/router.go @@ -13,10 +13,12 @@ import ( // directly means we'd get a collision with any other package that does the same. // https://play.golang.org/p/MxhRiL37R-9 type routerContextKeyType struct{} +type routerPathContextKeyType struct{} var ( - routerContextKey = routerContextKeyType{} - routerComponentsRe = regexp.MustCompile(`(?:^|/)(\*\w*|:\w+)`) + routerContextKey = routerContextKeyType{} + routerPathContextKey = routerPathContextKeyType{} + routerComponentsRe = regexp.MustCompile(`(?:^|/)(\*\w*|:\w+)`) ) type routerEntry struct { @@ -44,6 +46,13 @@ func RouterForRequest(r Request) *Router { return nil } +func routerEntryPathPatternForRequest(r Request) string { + if v := r.Context.Value(routerPathContextKey); v != nil { + return v.(string) + } + return "" +} + func (r *Router) compile(pattern string) *regexp.Regexp { re, pos := ``, 0 for _, m := range routerComponentsRe.FindAllStringSubmatchIndex(pattern, -1) { @@ -116,7 +125,7 @@ func (r Router) Lookup(method, path string) (Service, string, map[string]string, // Serve returns a Service which will route inbound requests to the enclosed routes. func (r Router) Serve() Service { return func(req Request) Response { - svc, _, ok := r.lookup(req.Method, req.URL.Path, nil) + svc, pathPattern, ok := r.lookup(req.Method, req.URL.Path, nil) if !ok { txt := fmt.Sprintf("No handler for %s %s", req.Method, req.URL.Path) rsp := NewResponse(req) @@ -124,6 +133,7 @@ func (r Router) Serve() Service { return rsp } req.Context = context.WithValue(req.Context, routerContextKey, &r) + req.Context = context.WithValue(req.Context, routerPathContextKey, pathPattern) rsp := svc(req) if rsp.Request == nil { rsp.Request = &req @@ -147,37 +157,46 @@ func (r Router) Params(req Request) map[string]string { // Sugar // GET is shorthand for: -// r.Register("GET", pattern, svc) +// +// r.Register("GET", pattern, svc) func (r *Router) GET(pattern string, svc Service) { r.Register("GET", pattern, svc) } // CONNECT is shorthand for: -// r.Register("CONNECT", pattern, svc) +// +// r.Register("CONNECT", pattern, svc) func (r *Router) CONNECT(pattern string, svc Service) { r.Register("CONNECT", pattern, svc) } // DELETE is shorthand for: -// r.Register("DELETE", pattern, svc) +// +// r.Register("DELETE", pattern, svc) func (r *Router) DELETE(pattern string, svc Service) { r.Register("DELETE", pattern, svc) } // HEAD is shorthand for: -// r.Register("HEAD", pattern, svc) +// +// r.Register("HEAD", pattern, svc) func (r *Router) HEAD(pattern string, svc Service) { r.Register("HEAD", pattern, svc) } // OPTIONS is shorthand for: -// r.Register("OPTIONS", pattern, svc) +// +// r.Register("OPTIONS", pattern, svc) func (r *Router) OPTIONS(pattern string, svc Service) { r.Register("OPTIONS", pattern, svc) } // PATCH is shorthand for: -// r.Register("PATCH", pattern, svc) +// +// r.Register("PATCH", pattern, svc) func (r *Router) PATCH(pattern string, svc Service) { r.Register("PATCH", pattern, svc) } // POST is shorthand for: -// r.Register("POST", pattern, svc) +// +// r.Register("POST", pattern, svc) func (r *Router) POST(pattern string, svc Service) { r.Register("POST", pattern, svc) } // PUT is shorthand for: -// r.Register("PUT", pattern, svc) +// +// r.Register("PUT", pattern, svc) func (r *Router) PUT(pattern string, svc Service) { r.Register("PUT", pattern, svc) } // TRACE is shorthand for: -// r.Register("TRACE", pattern, svc) +// +// r.Register("TRACE", pattern, svc) func (r *Router) TRACE(pattern string, svc Service) { r.Register("TRACE", pattern, svc) } From 776b548ecde383e72f8e5771335436d4fc25ac32 Mon Sep 17 00:00:00 2001 From: Rohan Date: Mon, 4 Dec 2023 09:40:59 +0000 Subject: [PATCH 3/7] Rename variable (PR feedback) --- router.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/router.go b/router.go index 7746076f..b3bc2367 100644 --- a/router.go +++ b/router.go @@ -13,12 +13,12 @@ import ( // directly means we'd get a collision with any other package that does the same. // https://play.golang.org/p/MxhRiL37R-9 type routerContextKeyType struct{} -type routerPathContextKeyType struct{} +type routerRequestPatternContextKeyType struct{} var ( - routerContextKey = routerContextKeyType{} - routerPathContextKey = routerPathContextKeyType{} - routerComponentsRe = regexp.MustCompile(`(?:^|/)(\*\w*|:\w+)`) + routerContextKey = routerContextKeyType{} + routerRequestPatternContextKey = routerRequestPatternContextKeyType{} + routerComponentsRe = regexp.MustCompile(`(?:^|/)(\*\w*|:\w+)`) ) type routerEntry struct { @@ -47,7 +47,7 @@ func RouterForRequest(r Request) *Router { } func routerEntryPathPatternForRequest(r Request) string { - if v := r.Context.Value(routerPathContextKey); v != nil { + if v := r.Context.Value(routerRequestPatternContextKey); v != nil { return v.(string) } return "" @@ -133,7 +133,7 @@ func (r Router) Serve() Service { return rsp } req.Context = context.WithValue(req.Context, routerContextKey, &r) - req.Context = context.WithValue(req.Context, routerPathContextKey, pathPattern) + req.Context = context.WithValue(req.Context, routerRequestPatternContextKey, pathPattern) rsp := svc(req) if rsp.Request == nil { rsp.Request = &req From a9761522d87012087f4b171de04c63a139dd0b67 Mon Sep 17 00:00:00 2001 From: Rohan Date: Mon, 4 Dec 2023 09:43:10 +0000 Subject: [PATCH 4/7] undo autoformat --- router.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/router.go b/router.go index b3bc2367..5862a875 100644 --- a/router.go +++ b/router.go @@ -157,46 +157,36 @@ func (r Router) Params(req Request) map[string]string { // Sugar // GET is shorthand for: -// // r.Register("GET", pattern, svc) func (r *Router) GET(pattern string, svc Service) { r.Register("GET", pattern, svc) } // CONNECT is shorthand for: -// // r.Register("CONNECT", pattern, svc) func (r *Router) CONNECT(pattern string, svc Service) { r.Register("CONNECT", pattern, svc) } // DELETE is shorthand for: -// // r.Register("DELETE", pattern, svc) func (r *Router) DELETE(pattern string, svc Service) { r.Register("DELETE", pattern, svc) } // HEAD is shorthand for: -// // r.Register("HEAD", pattern, svc) func (r *Router) HEAD(pattern string, svc Service) { r.Register("HEAD", pattern, svc) } // OPTIONS is shorthand for: -// // r.Register("OPTIONS", pattern, svc) func (r *Router) OPTIONS(pattern string, svc Service) { r.Register("OPTIONS", pattern, svc) } // PATCH is shorthand for: -// // r.Register("PATCH", pattern, svc) func (r *Router) PATCH(pattern string, svc Service) { r.Register("PATCH", pattern, svc) } // POST is shorthand for: -// // r.Register("POST", pattern, svc) func (r *Router) POST(pattern string, svc Service) { r.Register("POST", pattern, svc) } // PUT is shorthand for: -// -// r.Register("PUT", pattern, svc) func (r *Router) PUT(pattern string, svc Service) { r.Register("PUT", pattern, svc) } // TRACE is shorthand for: -// // r.Register("TRACE", pattern, svc) func (r *Router) TRACE(pattern string, svc Service) { r.Register("TRACE", pattern, svc) } From e4c8c20a3866b89b63d94c6401ff529b216baee1 Mon Sep 17 00:00:00 2001 From: Rohan Date: Mon, 4 Dec 2023 09:45:36 +0000 Subject: [PATCH 5/7] Undo autoformat --- router.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/router.go b/router.go index 5862a875..b3bc2367 100644 --- a/router.go +++ b/router.go @@ -157,36 +157,46 @@ func (r Router) Params(req Request) map[string]string { // Sugar // GET is shorthand for: +// // r.Register("GET", pattern, svc) func (r *Router) GET(pattern string, svc Service) { r.Register("GET", pattern, svc) } // CONNECT is shorthand for: +// // r.Register("CONNECT", pattern, svc) func (r *Router) CONNECT(pattern string, svc Service) { r.Register("CONNECT", pattern, svc) } // DELETE is shorthand for: +// // r.Register("DELETE", pattern, svc) func (r *Router) DELETE(pattern string, svc Service) { r.Register("DELETE", pattern, svc) } // HEAD is shorthand for: +// // r.Register("HEAD", pattern, svc) func (r *Router) HEAD(pattern string, svc Service) { r.Register("HEAD", pattern, svc) } // OPTIONS is shorthand for: +// // r.Register("OPTIONS", pattern, svc) func (r *Router) OPTIONS(pattern string, svc Service) { r.Register("OPTIONS", pattern, svc) } // PATCH is shorthand for: +// // r.Register("PATCH", pattern, svc) func (r *Router) PATCH(pattern string, svc Service) { r.Register("PATCH", pattern, svc) } // POST is shorthand for: +// // r.Register("POST", pattern, svc) func (r *Router) POST(pattern string, svc Service) { r.Register("POST", pattern, svc) } // PUT is shorthand for: +// +// r.Register("PUT", pattern, svc) func (r *Router) PUT(pattern string, svc Service) { r.Register("PUT", pattern, svc) } // TRACE is shorthand for: +// // r.Register("TRACE", pattern, svc) func (r *Router) TRACE(pattern string, svc Service) { r.Register("TRACE", pattern, svc) } From 744181347f73aceeb51ff33760481dd88ec614d9 Mon Sep 17 00:00:00 2001 From: Rohan Date: Mon, 4 Dec 2023 09:46:42 +0000 Subject: [PATCH 6/7] Undo autoformat --- router.go | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/router.go b/router.go index b3bc2367..75e08ea8 100644 --- a/router.go +++ b/router.go @@ -157,46 +157,37 @@ func (r Router) Params(req Request) map[string]string { // Sugar // GET is shorthand for: -// -// r.Register("GET", pattern, svc) +// r.Register("GET", pattern, svc) func (r *Router) GET(pattern string, svc Service) { r.Register("GET", pattern, svc) } // CONNECT is shorthand for: -// -// r.Register("CONNECT", pattern, svc) +// r.Register("CONNECT", pattern, svc) func (r *Router) CONNECT(pattern string, svc Service) { r.Register("CONNECT", pattern, svc) } // DELETE is shorthand for: -// -// r.Register("DELETE", pattern, svc) +// r.Register("DELETE", pattern, svc) func (r *Router) DELETE(pattern string, svc Service) { r.Register("DELETE", pattern, svc) } // HEAD is shorthand for: -// -// r.Register("HEAD", pattern, svc) +// r.Register("HEAD", pattern, svc) func (r *Router) HEAD(pattern string, svc Service) { r.Register("HEAD", pattern, svc) } // OPTIONS is shorthand for: -// -// r.Register("OPTIONS", pattern, svc) +// r.Register("OPTIONS", pattern, svc) func (r *Router) OPTIONS(pattern string, svc Service) { r.Register("OPTIONS", pattern, svc) } // PATCH is shorthand for: -// -// r.Register("PATCH", pattern, svc) +// r.Register("PATCH", pattern, svc) func (r *Router) PATCH(pattern string, svc Service) { r.Register("PATCH", pattern, svc) } // POST is shorthand for: -// -// r.Register("POST", pattern, svc) +// r.Register("POST", pattern, svc) func (r *Router) POST(pattern string, svc Service) { r.Register("POST", pattern, svc) } // PUT is shorthand for: -// -// r.Register("PUT", pattern, svc) +// r.Register("PUT", pattern, svc) func (r *Router) PUT(pattern string, svc Service) { r.Register("PUT", pattern, svc) } // TRACE is shorthand for: -// -// r.Register("TRACE", pattern, svc) +// r.Register("TRACE", pattern, svc) func (r *Router) TRACE(pattern string, svc Service) { r.Register("TRACE", pattern, svc) } From fc0f84099391b5239090ae39d95cff44a2930683 Mon Sep 17 00:00:00 2001 From: Rohan Date: Mon, 4 Dec 2023 10:35:58 +0000 Subject: [PATCH 7/7] Rename function (PR feedback) --- request.go | 2 +- router.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/request.go b/request.go index c01d2ebe..c8553b6c 100644 --- a/request.go +++ b/request.go @@ -215,7 +215,7 @@ func (r Request) ResponseWithCode(body interface{}, statusCode int) Response { // RequestPathPattern finds the router entry pattern that matches the request func (r Request) RequestPathPattern() string { - return routerEntryPathPatternForRequest(r) + return routerPathPatternForRequest(r) } // RequestMethod returns the HTTP method of the request diff --git a/router.go b/router.go index 75e08ea8..4a576e35 100644 --- a/router.go +++ b/router.go @@ -46,7 +46,7 @@ func RouterForRequest(r Request) *Router { return nil } -func routerEntryPathPatternForRequest(r Request) string { +func routerPathPatternForRequest(r Request) string { if v := r.Context.Value(routerRequestPatternContextKey); v != nil { return v.(string) }