File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -911,6 +911,16 @@ func (r *DefaultRouter) Route(c *Context) HandlerFunc {
911911 } else if currentNode .methods .notFoundHandler != nil {
912912 matchedRouteMethod = currentNode .methods .notFoundHandler
913913 break
914+ } else if currentNode .paramChild != nil && currentNode .anyChild == nil &&
915+ currentNode .parent != nil && currentNode .parent .paramChild != nil {
916+ // Path exactly matches this static node. Prefer this over backtracking to a param route
917+ // that would match the last segment (e.g. POST /VerifiedCallerId/Verification should not
918+ // match GET /VerifiedCallerId/:phone_number). Only when parent has paramChild (backtrack
919+ // would match) - otherwise we'd return 405 for paths that should be 404 (e.g. /a3 with route /a3/:id).
920+ if previousBestMatchNode == nil {
921+ previousBestMatchNode = currentNode .paramChild
922+ }
923+ break
914924 }
915925 }
916926
Original file line number Diff line number Diff line change @@ -1514,6 +1514,25 @@ func TestRouterMatchAnyPrefixIssue(t *testing.T) {
15141514 }
15151515}
15161516
1517+ // TestRouterRoutePreferExactPathOverParam tests issue #2547: POST to path without param
1518+ // should return 405 with Allow: POST (from the more specific route), not 405 from
1519+ // the param route that would capture the last segment.
1520+ func TestRouterRoutePreferExactPathOverParam (t * testing.T ) {
1521+ e := New ()
1522+ e .GET ("/VerifiedCallerId/:phone_number" , handlerFunc )
1523+ e .POST ("/VerifiedCallerId/Verification/:verification_uuid" , handlerFunc )
1524+
1525+ req := httptest .NewRequest (http .MethodPost , "/VerifiedCallerId/Verification/" , nil )
1526+ rec := httptest .NewRecorder ()
1527+ c := e .NewContext (req , rec )
1528+ handler := e .router .Route (c )
1529+
1530+ err := handler (c )
1531+ assert .ErrorIs (t , err , ErrMethodNotAllowed )
1532+ assert .Contains (t , rec .Header ().Get ("Allow" ), "POST" )
1533+ assert .NotContains (t , rec .Header ().Get ("Allow" ), "GET" )
1534+ }
1535+
15171536// TestRouterMatchAnySlash shall verify finding the best route
15181537// for any routes with trailing slash requests
15191538func TestRouterMatchAnySlash (t * testing.T ) {
You can’t perform that action at this time.
0 commit comments