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

Use request to normalize options #180

Merged
merged 5 commits into from
Oct 28, 2019

Conversation

sholladay
Copy link
Collaborator

@sholladay sholladay commented Oct 1, 2019

Closes #166
Closes #139

This PR:

  • Aims to simplify Ky and solve some edge case issues and confusing behavior related to how our options are normalized and merged.
  • Makes it so that internally, and within hooks, a Request instance is now used as the source of truth instead of input. This replaces some of the bespoke logic that we've had for processing options. It also makes life easier for people using the hooks option, because they will receive a normalized request, whose behavior is more obvious and is well-specified by web standards. We can discuss whether the raw input should be available as well.
  • Cleans up the separation betwen Ky options and fetch options internally, so there's a clear distinction and it's easy to pass around one or the other, or both.
  • Adds the ability for beforeRequest hooks to return a Request instance to replace the existing request.

@sholladay sholladay force-pushed the normalize-request branch 4 times, most recently from d26b9cd to 48379b8 Compare October 2, 2019 05:05
@sholladay
Copy link
Collaborator Author

Maybe I just need some sleep and am missing something obvious, but it's not clear to me why that timeout test is failing. I did not intentionally change any timeout or retry behavior.

Any thoughts @szmarczak?

timeout
};
this._fetchOptions = {
// TODO: credentials can be removed when the spec change is implemented in all browsers. Context: https://www.chromestatus.com/feature/4539473312350208
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I tested Chrome, Firefox, Safari, and Edge 18, and all of them default to same-origin now. Not sure about mobile browsers, though. Should we remove this?

Copy link
Owner

Choose a reason for hiding this comment

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

Nah, not worth the risk. It's only a few bytes anyway.

@sholladay
Copy link
Collaborator Author

I kinda want to change the signature of hooks.

Prior to this PR, we had:

  • beforeRequest(input, options)
  • beforeRetry(input, options, error, retryCount)
  • afterResponse(input, options, response)

This PR changes input to request in these signatures, anyway. So it is worth considering any other breaking changes we want to do. For example...

  • We could attach the response to the request passed to afterResponse, rather than having it as a separate argument. I find this more elegant since the response belongs to a particular request. Plus it improves the symmetry of the call signature between beforeRequest and afterResponse.
  • We could attach retryCount to the request or error passed to beforeRetry, rather than passing it as a separate argument. I don't have strong feelings about this one, but I do feel that any function with four arguments is a bit much.

@sholladay sholladay force-pushed the normalize-request branch 2 times, most recently from 3947db2 to 8cc6381 Compare October 3, 2019 08:10
@sholladay sholladay changed the title WIP: Use request to normalize options Use request to normalize options Oct 3, 2019
@sholladay
Copy link
Collaborator Author

Ready for review. Could use help on that one failing test.

// @sindresorhus @szmarczak

@sholladay
Copy link
Collaborator Author

For now, I've worked around the timeout test issue by changing it to validate synchronously.

I would argue that:

  1. This is how input validation should work, anyway.
  2. Even if you disagree with 1, it still makes our validation more consistent.

@sindresorhus
Copy link
Owner

Promise-returning methods should always reject: https://twitter.com/jaffathecake/status/638659818996269056?s=21

@sholladay
Copy link
Collaborator Author

Alright, I made it a rejection. It's still validated in the constructor to work around the broken test that failed for reasons I don't understand.

@sholladay
Copy link
Collaborator Author

sholladay commented Oct 7, 2019

It was a real pain to make it reject asynchronously before the request, because the rejected promise didn't have the Body methods, so .json() didn't exist and would immediately throw an error, for example. I had to place the rejection in a very specific, non-obvious place.

I wholeheartedly disagree with this design pattern of rejecting user mistakes asynchronously. But I aim to please, so I made it work. The tests are passing. Please review.

At this point, the main thing I'm wondering is what options the hooks should receive. I'm thinking either:
A. Only fetch options (current behavior of this PR)
B. All Ky and fetch options mixed together

The benefit of A is that we can more easily support users directly mutating the options, without forcing them to return a Request. It also avoids the illusion that you can override Ky's settings within hooks and prevents the temptation to try to do so.

As for B, I'm not sure if there is a concrete use case for reading Ky's options within hooks, but I can sort of imagine it being useful to do something special when throwHttpErrors is false or when timeout has a large value, etc. The only downside is that to support hooks mutating the object, we'd have to go back to a single combined options object (i.e. not separate fetch options vs Ky options), which I'd be fine with, albeit it feels a little less clean.

@sholladay
Copy link
Collaborator Author

sholladay commented Oct 28, 2019

Anything else needed here?

In addition to the issues that this PR already addresses, I also have fixes for #167, #182, and #187, which I want to implement on top of these changes. I could easily include those in this PR (most of them actually remove lines of code), however I don't want to do too many unrelated things and make it harder to review. If we can merge this soon, I will get to those quickly.

It would be preferable to hold off on a release (even though everything here is working as-is). I realized that hooks really should be receiving all options for both Ky and fetch mixed together, so that the hooks themselves can call Ky and "inherit" the Ky options. I'd like to address that at the same time as #167, which as mentioned previously, should probably be done in a separate PR.

@sindresorhus sindresorhus merged commit c5821a7 into sindresorhus:master Oct 28, 2019
@sindresorhus
Copy link
Owner

This is great. Nice work 👌 And sorry for the delay. I reviewed this a week ago and was going to merge and then got distracted and forgot about it...

@sholladay
Copy link
Collaborator Author

@sindresorhus is codecov broken? I just noticed that the status check for this PR says "No report found to compare against" and clicking on the details also doesn't bring up anything useful. Maybe it needs to be re-authorized?

@sindresorhus
Copy link
Owner

Ah yeah. It was not enabled on the GitHub side. Done now.

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.

Modify the request URL in the beforeRequest hook Document how to override headers in beforeRequest hook
2 participants