-
Notifications
You must be signed in to change notification settings - Fork 30.3k
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
querystring, url: repeated '&' in a paramsString will be skipped #10967
Conversation
7d22fc5
to
0701371
Compare
I believe the consensus was to freeze the querystring module, and put all new work onto @jasnell, can you weigh in on this? |
@TimothyGu I don't recall that. Perhaps you're thinking about the |
Regardless of any previous planning, I am not sure this PR (or any PRs that change the behavior of this module) is the way to go.
|
I wouldn't describe it as consensus. In my opinion significant changes to the the existing |
I think this looks more like a bugfix, albeit a breaking one...I doubt anyone would rely on the behavior of parsing In fact you can't even reserialize to the original string with this bug. No error would be thrown if you only use the Node.js built-in module, but it could be a problem when it ends up in the hand of other modules in other languages. > qs.parse('a=1&&b=1')
{ a: '1', '': '', b: '1' }
> qs.stringify(qs.parse('a=1&&b=1'))
'a=1&=&b=1' FWIW, in Python: >>> parse_qs('a=1&&b=2')
{'a': ['1'], 'b': ['2']} PHP: php > $foo = array();
php > parse_str('a=1&&b=2', $foo);
php > var_dump($foo);
array(2) {
["a"]=>
string(1) "1"
["b"]=>
string(1) "2"
} Ruby: 2.3.1 :003 > CGI.parse("a=1&&b=2")
=> {"a"=>["1"], "b"=>["2"]} |
Regarding @TimothyGu 's concerns I think 1 might not be that significant seeing what other languages behaves. 2 would be more possible, but I can't think of a reason for relying on an empty key (if it's just for custom searialization), though some people could rely on an empty value, maybe changing |
I've tested the above case @joyeecheung mentioned, and it seems to work fine in this branch
About
|
lib/querystring.js
Outdated
else | ||
obj[key] = [curValue, value]; | ||
|
||
if (key.length > 0 || value.length > 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just key.length > 0
? Empty values are not that uncommon (e.g. qs.parse('b=&x=1')
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just took a look at the spec and this bit of code, I think the current way is the best :D. The only one that needs to be ignored is &&
, otherwise it doesn't match what the spec needs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for following up the code and the spec hardly!
I agree that it's a bugfix. Parsing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Almost there
test/parallel/test-querystring.js
Outdated
@@ -51,6 +51,8 @@ const qsTestCases = [ | |||
__defineGetter__: 'baz' }], | |||
// See: https://github.com/joyent/node/issues/3058 | |||
['foo&bar=baz', 'foo=&bar=baz', { foo: '', bar: 'baz' }], | |||
['&&foo=bar&&', 'foo=bar', { foo: 'bar' }], | |||
['&&&&', '', {}], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be helpful to also test the following cases:
`a=b&c&d=e`
`a=b&c=&d=e`
`a=b&=c&d=e`
`a=b&=&c=d`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right! Adding the cases that the key or the value is empty sounds useful for revealing the current behaviour. I've added them :)
New CI since the test was updated: https://ci.nodejs.org/job/node-test-pull-request/6032/ |
216afd3
to
840bb2f
Compare
Some of the nice performance improvements in |
test/parallel/test-querystring.js
Outdated
['a=b&c&d=e', 'a=b&c=&d=e', { a: 'b', c: '', d: 'e' }], | ||
['a=b&c=&d=e', 'a=b&c=&d=e', { a: 'b', c: '', d: 'e' }], | ||
['a=b&=c&d=e', 'a=b&=c&d=e', { a: 'b', '': 'c', d: 'e' }], | ||
['a=b&=&c=d', 'a=b&c=d', { a: 'b', c: 'd' }], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be parsed as { '': '', a: 'b', c: 'd' }
. Try new URLSearchParams('&=&').get('')
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow I didn't know that, thanks! Then I will try to support the case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I've updated! The logic was changed to simple one :)
bfe41b6
to
7b6c578
Compare
666b945
to
f81201a
Compare
I made improvements in performance again, and now it seems to be better than my last update.
|
@watilde That benchmark output looks truncated (the benchmark/compare.js script by default performs more runs than that). Having the output piped to |
@mscdex That's right indeed! Then I just tried it, and here is the result: |
Aborted CI, only |
Landed in 4e259b2 |
Should this be marked as semver-major? |
I was hoping to look at this this weekend before this landed... |
oy.. my apologies @mscdex... if you indicated that in the thread and I missed it, I do apologize. |
if this ends up not being acceptable to you @mscdex, then we should be able to do a quick revert |
Isn't this patch update since it's just bug-fix? |
@watilde It might be a bug fix for the whatwg url module, but it's arguably not for the non-whatwg url module since there is no real spec that it adheres to. If this change were made to whatwg url's own querystring implementation that would be different and semver-major could just be applied to the non-whatwg url changes. @jasnell #10967 (comment) I probably won't get time until this weekend to review this, so I don't think a 'quick revert' will happen unless else everyone agrees. |
I think we can wail until @mscdex 's review to decide then. Personally I think it's fine to accept this if it doesn't introduce any new behavior other than fixing #10454 because the old behavior looks buggy to me (see #10967 (comment)). |
@joyeecheung Calling it a 'bug fix' is debatable. One could also argue that |
@mscdex Sorry for being vague, I am fine with marking this semver-major. |
* update state machine in parse * repeated sep should be adjusted * `&=&=` should be `{ '': [ '', '' ] }` * add test cases for querystring and URLSearchParams Fixes: nodejs#10454 PR-URL: nodejs#10967 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Timothy Gu <timothygu99@gmail.com>
Updates:
querystring
andURLSearchParams
Fixes: #10454
/cc @nodejs/url
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passesAffected core subsystem(s)
querystring, url, url-whatwg, test