Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make reverse routes always use the first matching route #3052

Merged
merged 1 commit into from Jun 24, 2014

Conversation

gmethvin
Copy link
Member

Fixes #3050. The previous way of removing the extra routes would prioritize the last matching route as opposed to the first one. Now it should work the same as in 2.2, but without the warning.

@cchantep
Copy link
Member

LGTM

@jroper
Copy link
Member

jroper commented Jun 24, 2014

No! This will create a conflict with what I'm working on!! sigh

jroper added a commit that referenced this pull request Jun 24, 2014
Make reverse routes always use the first matching route
@jroper jroper merged commit 0eac22e into playframework:master Jun 24, 2014
@gmethvin gmethvin deleted the routes_priority branch June 24, 2014 02:12
@jroper
Copy link
Member

jroper commented Jun 24, 2014

Backported to 2.3.x b0388f9

@jroper
Copy link
Member

jroper commented Jun 25, 2014

I think this might have caused some problems. In playframework.com, we have the following routes:

GET      /documentation/latest                                      controllers.Documentation.latest(page = "Home")
GET      /documentation/latest/:page                                controllers.Documentation.latest(page)

Now this is generating this:

def latest(page:String): Call = {
   (page: @unchecked) match {
// @LINE:42
case (page)  =>
  import ReverseRouteContext.empty
  Call("GET", _prefix + { _defaultPrefix } + "documentation/latest/" + implicitly[PathBindable[String]].unbind("page", dynamicString(page)))

// @LINE:41
case (page) if page == "Home" =>
  implicit val _rrc = new ReverseRouteContext(Map(("page", "Home")))
  Call("GET", _prefix + { _defaultPrefix } + "documentation/latest")

   }
}

As you can see, the ordering there is reversed, and I get an unreachable code warning.

@@ -1005,7 +1002,7 @@ object RoutesCompiler {
""".stripMargin.format(markers, parameters, parametersConstraints, reverseRouteContext, call)

(parameters -> parametersConstraints) -> result
}: _*).values
}.groupBy(_._1).map(_._2.head._2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think the problem is here - groupBy returns a Map, so the order of the routes is lost. The right duplicate is selected, but the order of non duplicates is now random by hash code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, now it makes sense why we were using a ListMap. I think it would've been easier to just reverse the list before creating the ListMap.

I'll submit a PR to fix.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've just cut 2.3.1, found this in a smoke test. I don't think it's a big enough regression to warrant immediately cutting a new release - it just means that at random, the a less specific route might be chosen, resulting in a cosmetically different URL - the URL produced will still cause the same action to be invoked. What do you think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or another way of looking at it, we've replaced one very minor reverse routes priority bug with another very minor reverse routes priority bug.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The functionality is the same but the warning is a bit annoying/confusing, even if the behavior is correct.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would definitely appreciate a release for this fix, since the cosmetic difference in the generated URL can be problematic. In our case it adds a trailing slash to a very common URL in our application because it is using the more specific version of the route (i.e. /a/b/c) to generate the less specific version (i.e. /a/b), which results in /a/b/.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, well we have 3 fixes already, we'll cut 2.3.2 next week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Route priority wrong in reverse routing
4 participants