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

QueryStringBindable.unbind(): Do-do-do URLEncode for all queryString keys! #10370

Merged
merged 3 commits into from
Feb 9, 2021

Conversation

helllamer
Copy link
Contributor

@helllamer helllamer commented Jul 1, 2020

Fixes #10369 - Let's DO URLEncode.encode() for all queryString keys in QSB.unbind().
Unify unbind() behaviour over all query-string binders.

Currently, different binders handle qs-keys differently (look at res3):

$ sbt console
import play.api.mvc.QueryStringBindable

scala> QueryStringBindable.bindableChar.unbind( "items[1]", '1' )
val res1: String = items[1]=1

scala> QueryStringBindable.bindableInt.unbind( "items[1]", 1 )
val res2: String = items[1]=1

scala> QueryStringBindable.bindableString.unbind( "items[1]", "1" )
val res3: String = items%5B1%5D=1

scala> QueryStringBindable.bindableDouble.unbind( "items[1]", 1 )
val res4: String = items[1]=1.0

Special characters like [, ] and others MUST be Form-URL-encoded according to RFC.
Added documentation about applying URLEncode for handy-implemented unbinders.
Added tests for several common types of QueryStringBindables.

Pull Request Checklist

Helpful things

Fixes

Fixes #10369

@helllamer helllamer changed the title Binders.bindableString.unbind(): Do not URLEncode qs-keys. QueryStringBindable.unbind(): Do-do-do URLEncode for all queryString keys! Jul 1, 2020
@helllamer
Copy link
Contributor Author

helllamer commented Jul 1, 2020

PR has been rewritten from scratch.
Now, all qs-binders using URLEncode.encode() against all queryString keys.
Tests extended.
Documentation extended.

@helllamer helllamer force-pushed the master branch 7 times, most recently from 8fea400 to e2a1171 Compare July 1, 2020 17:33
@@ -309,8 +319,7 @@ object QueryStringBindable {

// Use an option here in case users call index(null) in the routes -- see #818
def unbind(key: String, value: String) =
URLEncoder.encode(Option(key).getOrElse(""), "utf-8") + "=" + URLEncoder
.encode(Option(value).getOrElse(""), "utf-8")
_urlEncode(key) + "=" + Option(value).fold("")(_urlEncode)
Copy link
Member

Choose a reason for hiding this comment

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

Why Option dropped for key? 🤔 He is no longer needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Possibly, it never needed.
Option(key).getOrElse() added year ago in #9403 (diff) during fixing URLEncode for values.

  • In Binders.scala there are no Option(key) for any other binders (Char, Long, Int, UUID, etc).
  • There are zero tests for such behavior, where parsed queryString contains null keys with String-only values.
  • Generated Router.scala can't pass nulls as parameter names.
  • null as keys in scala Map[String,_] must always throw NPE. It indicates serious problem in somewhere outer logic.

Copy link
Contributor Author

@helllamer helllamer Jul 1, 2020

Choose a reason for hiding this comment

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

@ihostage Этот Option(key) появился, т.к. код поддержки URLEncode просто скопипастили из value-кода в той же строке. Для value действительно нужен Option(), о чём в комменте там выше написано.

Copy link
Member

Choose a reason for hiding this comment

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

Ok 👌

@helllamer
Copy link
Contributor Author

@mkurz @ihostage I don't understand, is reviews completed ok? Is it time to remove status:block-merge flag?

@ihostage
Copy link
Member

@helllamer Sorry, I'm not a maintainer and can't edit PR 🤷‍♂️

@mkurz
Copy link
Member

mkurz commented Jul 21, 2020

Sorry, I am too busy these days... Maybe @ignasi35 and/or @renatocaval can review?

Added docs for safety implementing own custom QSBs.
Tests for several other QSB implementations.
Fixes playframework#10369
@mkurz
Copy link
Member

mkurz commented Feb 8, 2021

@helllamer I had an intense look again at this pull request and it looks good to me. Actually I think it's a necessary fix and want to include it in the next Play 2.8.8 release. However I would like to push some small fixes to your patch (documentation wording and one more test).
Could you please give me access to your branch by selecting "Allow edits by maintainers" at the right side of the pull request?
Thanks!

image

@helllamer
Copy link
Contributor Author

@mkurz Glad to hear you.
I've added you with WRITE access to suggestio:master branch on github.
Because i cannot find such checkbox, possibly due to using of master branch name.

@mkurz
Copy link
Member

mkurz commented Feb 8, 2021

@Mergifyio backport 2.8.x

@mergify
Copy link
Contributor

mergify bot commented Feb 8, 2021

Command backport 2.8.x: pending

Waiting for the pull request to get merged

@mkurz
Copy link
Member

mkurz commented Feb 8, 2021

@helllamer Thanks, I pushed two commits. Let's see what Travis says.

@mergify
Copy link
Contributor

mergify bot commented Feb 9, 2021

Command backport 2.8.x: success

Backports have been created

mergify bot added a commit that referenced this pull request Feb 9, 2021
QueryStringBindable.unbind(): Do-do-do URLEncode for all queryString keys! (bp #10370)
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.

QueryStringBindable.bindableString.unbind() produces URL-encoded keys, other binders - don't
3 participants