Repository: phoenixframework/phoenix

Issue #5156: Route resolution issues in 1.7.0-rc.0
Created: 2022-12-06T22:26:38Z
Environment

Elixir version (elixir -v): Elixir 1.14.2 (compiled with Erlang/OTP 25)
Phoenix version (mix deps): 1.7.0-rc.0
Operating system: macOS 12.6.1 (Intel)

We're building an API using Phoenix and are in the process of upgrading to 1.7 on a branch to see if we hit any weird bugs. It appears we've hit one.
We're seeing this issue in multiple environments, not just macOS.
I bumped Elixir to Elixir 1.13.4 (compiled with Erlang/OTP 24) and the results were the same.
Consider the following routes:
GET     /resources/:id                             MyApp.ResourcesController :show
POST    /resources/:resources_id/related-resources MyApp.RelatedResourcesController :create
GET     /resources/:id/:relationship_name          MyApp.ResourcesController :related

With our current setup, if there's a contextual create, it's handled by the related resource's controller, but the parent resource just handles index routes for all its child resources so we don't have to explicitly create new routes every time we add read-only relationships.
Expected behavior
In 1.6.12

POST /resources/1/related-resources routes to MyApp.RelatedResourcesController.create
GET /resources/1/related-resources routes to MyApp.ResourcesController.related

Actual behavior
In 1.17.0-rc.0

POST /resources/1/related-resources routes to MyApp.RelatedResourcesController.create
GET /resources/1/related-resources results in Phoenix.Router.NoRouteError

If I flip the route order:
GET     /resources/:id                             MyApp.ResourcesController :show
GET     /resources/:id/:relationship_name          MyApp.ResourcesController :related
POST    /resources/:resources_id/related-resources MyApp.RelatedResourcesController :create


POST /resources/1/related-resources results in Phoenix.Router.NoRouteError
GET /resources/1/related-resources routes to MyApp.ResourcesController.related

It appears now that if a route matches the route pattern first without the proper verb, it fails, even though another verb/pattern might match down the line (which is the current behavior in 1.6).
If I explicitly add the route, it works:
GET     /resources/:id                             MyApp.ResourcesController :show
POST    /resources/:resources_id/related-resources MyApp.RelatedResourcesController :create
GET     /resources/:resources_id/related-resources MyApp.ResourcesController :related

Even if the parameter name changes, it still works fine. So, this also works:
GET     /resources/:id                             MyApp.ResourcesController :show
POST    /resources/:resources_id/related-resources MyApp.RelatedResourcesController :create
GET     /resources/:id/related-resources           MyApp.ResourcesController :related

Since this expected behavior worked in 1.6, I'm guessing it's expected to work in 1.7. (I'm hoping that's the case!)
Please let me know if you need me to put together a better example or provide anymore information.

Duplicate issue #5210: get/post with dynamic paths return no route found error [1.7.0-rc.1]
Created: 2023-01-11T18:48:25Z
Environment

Elixir version (elixir -v): Elixir 1.14.0 (compiled with Erlang/OTP 25)
Phoenix version (mix deps): Phoenix 1.7.0-rc.1
Operating system: macOS Monterey, Version 12.6

Note
Posting this as an issue first without a replication because it seems like a pretty major issue. I can create a new app with a demo of this behavior if need be.
Also, I want to give recognition to @charlottemoche and @coladarci for helping discover this with me.
Expected behavior
Routes with dynamic paths segments are found regardless of order and method in router.ex.
The following should be able to work without issue:
scope "/", AppWeb do
  get "/foo/:bar/:baz", SomeController, :show 
  post "/foo/:bar/post", SomeController, :post
end

Actual behavior
In router.ex, a route is declared in the following way:
scope "/", AppWeb do
  get "/foo/:bar/:baz", SomeController, :show 
  post "/foo/:bar/post", SomeController, :post
end

When running mix phx.routes, both routes are displayed as expected. However, when trying to submit a post request to /foo/:bar/post, the application returns the following error:
 ** (Phoenix.Router.NoRouteError) no route found for POST /foo/variable/post (AppWeb.Router)
By switching the order of the requests, to post declared before get, the application works as expected.
This leads me to believe that somewhere in Phoenix the get "/foo/:bar/:baz" is taking precedence because it has a dynamic third part of the path that is matching, resulting in the post request never matching. So, the application is aware the route exists, but the application is never able to find it.

Closing comment (2023-01-11T18:50:20Z): Dup of #5156 thanks!