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

Add searchParams option #57

Merged
merged 18 commits into from
Nov 1, 2018
Merged

Add searchParams option #57

merged 18 commits into from
Nov 1, 2018

Conversation

itaisteinherz
Copy link
Contributor

@itaisteinherz itaisteinherz commented Oct 26, 2018

Fixes #54

index.js Outdated
@@ -86,13 +86,14 @@ const timeout = (promise, ms) => Promise.race([
]);

class Ky {
constructor(input, {timeout = 10000, hooks = {beforeRequest: []}, throwHttpErrors = true, json, ...otherOptions}) {
constructor(input, {timeout = 10000, hooks = {beforeRequest: []}, throwHttpErrors = true, searchParams = '', json, ...otherOptions}) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

searchParams, (no empty string)

index.js Outdated Show resolved Hide resolved
index.js Outdated
this._retryCount = 0;

this._options = {
method: 'get',
credentials: 'same-origin', // TODO: This can be removed when the spec change is implemented in all browsers. Context: https://www.chromestatus.com/feature/4539473312350208
retry: 2,
searchParams: new URLSearchParams(searchParams),
Copy link
Collaborator

@szmarczak szmarczak Oct 26, 2018

Choose a reason for hiding this comment

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

This line is useless

@itaisteinherz
Copy link
Contributor Author

Thanks for the detailed review @szmarczak 👍🏻
I'm still not sure why the build fails, since URLSearchParams should be available on Node.js v8.

@szmarczak
Copy link
Collaborator

And it is, but it isn't a global. We would need to access it through require('url'). But we don't need that cuz we don't target Node. We target browsers only.

See #51. We can't do anything about that yet.

index.js Outdated
this._input = this._options.prefixUrl + this._input;
const url = new URL(this._options.prefixUrl + this._input);
if (searchParams) {
url.search = searchParams instanceof URLSearchParams ? searchParams : new URLSearchParams(searchParams).toString();
Copy link
Collaborator

Choose a reason for hiding this comment

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

What about:

if (typeof searchParams === 'string') {
    url.search = searchParams;
} else {
    url.search = new URLSearchParams(searchParams).toString();
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Your suggestion looks good to me, except for the fact that if searchParams is an instance of URLSearchParams you end up initiating a clone of it for no reason.
We could do this:

if (typeof searchParams === 'string' || searchParams instanceof URLSearchParams) {
    url.search = searchParams;
} else {
    url.search = new URLSearchParams(searchParams).toString();
}

Which both doesn't parse strings nor URLSearchParams objects.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Lemme fix your code:

if (typeof searchParams === 'string') {
    url.search = searchParams;
} else if (searchParams instanceof URLSearchParams) {
    url.search = searchParams.toString();
} else {
    url.search = new URLSearchParams(searchParams).toString();
}

I hope it works as expected

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could do that, but from my testing in both Node and my browser (Chrome), url.search = searchParams works.

This is how I tested it:

screenshot

Copy link
Collaborator

Choose a reason for hiding this comment

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

I haven't checked that so I didn't know, thanks for the explanation :) If you made a commit with that it would be great :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In a flash ;)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ended up doing:

if (typeof searchParams === 'string' || searchParams instanceof URLSearchParams) {
	url.search = searchParams;
} else if (searchParams) {
	url.search = new URLSearchParams(searchParams).toString();
}

Since if the searchParams option isn't defined, the test prefix-url › prefixUrl option fails (which makes sense).

@itaisteinherz
Copy link
Contributor Author

@szmarczak Can you mark #57 (comment) as resolved? We've already addressed the issue in the discussion on #57 (comment) and in 6bb65d0.

@maple3142
Copy link

How about handling this one?

ky('https://example.com/?a=1&b=2', { searchParams: { a: 2 } })

@itaisteinherz
Copy link
Contributor Author

@maple3142 Currently, all query parameters get ignored when the searchParams option is supplied, and so in your example the final URL which will be requested is https://example.com/?a=2.
This behavior was derived from #54 (comment).

@sindresorhus
Copy link
Owner

This looks good, but I need some feedback on what behavior to use when a plain Object is given. See sindresorhus/got#638. There can be confusion if someone specifies, for example, searchParams: {foo: [1, 2]}. My idea in sindresorhus/got#643, was to limit the values to just strings when a plain object is given. That would mean searchParams: {foo: 1} would have to be specified as searchParams: {foo: '1'} which is inconvenient. We could also allow numbers, but where do we set the limit? Only allow strings and numbers as values?

// @mrtnbroder @mrmlnc @vitkarpov @brandon93s

@sindresorhus
Copy link
Owner

And do anyone disagree that it should replace the search params already in the URL instead of merging them in?

@itaisteinherz
Copy link
Contributor Author

@sindresorhus I've implemented your suggestion. Currently only strings and numbers are allowed, although we could probably support any primitive type excluding objects and arrays.

index.js Show resolved Hide resolved
@felixfbecker
Copy link

It should probably mirror what new URLSearchParams(object) does.

@sholladay
Copy link
Collaborator

Don't forget to update the TypeScript types (see #49 as an example).

The build failure should be easy to fix now that the Cypress tests are up and running. :)

@sindresorhus
Copy link
Owner

Don't forget to update the TypeScript types (see #49 as an example).

And also add a test to https://github.com/sindresorhus/ky/blob/master/index.test-d.ts

@sindresorhus
Copy link
Owner

Can you also fix the merge conflict?

test/main.js Outdated Show resolved Hide resolved
readme.md Outdated Show resolved Hide resolved
@itaisteinherz
Copy link
Contributor Author

The build failure should be easy to fix now that the Cypress tests are up and running. :)

@sholladay I've never used Cypress before, and so I'm not sure how to fix the build failure.
Also, the build fails on Node.js v8 because of URLSearchParams not being available when testing using AVA. Am I supposed to port all AVA tests to Cypress, or just the searchParams-related ones (or something else)?

index.js Outdated Show resolved Hide resolved
index.js Outdated Show resolved Hide resolved
index.js Outdated Show resolved Hide resolved
test/main.js Outdated Show resolved Hide resolved
@sindresorhus
Copy link
Owner

@itaisteinherz No, we'll only use Cypress when it's impossible to use Node.js testing. Accept my code suggestion above and then rebase from master branch and the test should pass ;)

sindresorhus and others added 5 commits November 1, 2018 11:06
Co-Authored-By: itaisteinherz <itaisteinherz@gmail.com>
Co-Authored-By: itaisteinherz <itaisteinherz@gmail.com>
Co-Authored-By: itaisteinherz <itaisteinherz@gmail.com>
Co-Authored-By: itaisteinherz <itaisteinherz@gmail.com>
@itaisteinherz
Copy link
Contributor Author

itaisteinherz commented Nov 1, 2018

Accept my code suggestion above and then rebase from master branch and the test should pass ;)

Done, but I still had to merge from master because I couldn't figure out how to rebase properly 😓
Thanks for pointing out what needed to be changed in order to make the CI build pass 👍🏻

@szmarczak
Copy link
Collaborator

LGTM.

@sindresorhus
Copy link
Owner

sindresorhus commented Nov 1, 2018

This still needs TypeScript typings, like mentioned in #57 (comment). Otherwise, the code changes are looking good.

@itaisteinherz
Copy link
Contributor Author

itaisteinherz commented Nov 1, 2018

@sindresorhus I'll finish the TypeScript typings in an hour or so.

@itaisteinherz
Copy link
Contributor Author

Done in 8c8c1ca 👌🏻

@sindresorhus
Copy link
Owner

You missed #57 (comment), but I can fix that for you.

@sindresorhus sindresorhus merged commit a7c71b5 into sindresorhus:master Nov 1, 2018
@sindresorhus
Copy link
Owner

Thank you for working on this :)

sindresorhus added a commit that referenced this pull request Nov 1, 2018
dangdennis pushed a commit to dangdennis/ky that referenced this pull request Nov 4, 2018
dangdennis pushed a commit to dangdennis/ky that referenced this pull request Nov 4, 2018
dangdennis pushed a commit to dangdennis/ky that referenced this pull request Nov 4, 2018
dangdennis pushed a commit to dangdennis/ky that referenced this pull request Nov 4, 2018
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.

6 participants