Skip to content

Allow client option for custom dispatcher into fetch requests (e.g. to disable certificate validation) #1631 #1837

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

Closed
wants to merge 0 commits into from

Conversation

mellster2012
Copy link
Contributor

Changes

Allow client option for custom dispatcher into fetch requests (e.g. to disable certificate validation)

How to Review

This has been discussed before under a previous PR #1636. The branches were quite out of sync so it was easier to start from scratch.

Checklist

  • Unit tests updated
  • docs/ updated (if necessary)
  • pnpm run update:examples run (only applicable for openapi-typescript)

@mellster2012 mellster2012 requested a review from a team as a code owner August 10, 2024 23:05
Copy link

changeset-bot bot commented Aug 10, 2024

⚠️ No Changeset found

Latest commit: c9ba9dc

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@mellster2012
Copy link
Contributor Author

@drwpow This is the redone PR which was previously at #1636

@kerwanp
Copy link
Contributor

kerwanp commented Aug 14, 2024

Hey @mellster2012 ! Looks good to me, thanks for the PR.

This just need a changeset and a documentation update to merge this (dispatcher option).

@@ -10,10 +10,14 @@ import type {
SuccessResponse,
} from "openapi-typescript-helpers";

import type { Dispatcher } from "undici";
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we redeclare this type so we don’t have an undici dependency (even type-wise)? The type signatures can match, but I don’t want people who install openapi-fetch to also have undici install as well.

@@ -77,6 +77,7 @@
"openapi-typescript-codegen": "^0.25.0",
"openapi-typescript-fetch": "^2.0.0",
"superagent": "^9.0.2",
"undici": "^6.14.1",
Copy link
Contributor

Choose a reason for hiding this comment

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

See other comment—unfortunately this is a dependency because of how it’s used, and I’d like to avoid that. Let’s just copy the Dispatcher type locally to prevent this.

@@ -125,7 +126,7 @@ export default function createClient(clientOptions) {
}

// fetch!
let response = await fetch(request);
let response = await fetch(request, dispatcher ? { dispatcher } : undefined);
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: I’m a bit skeptical of this as-written, because this is invalid for the official fetch() specification. It doesn’t throw an error just by virtue of extra params getting ignored, but in basically all implementations of fetch() that aren’t undici, this is invalid.

Of course, the argument I guess is people won’t be adding this if they aren’t using undici as their custom fetcher, so it’s at least within the user’s control. But I want to point out that treating all fetch()s as if they’re a custom third-party implementation is dangerous (I know undici is basically used as Node’s official fetch() implementation now, but it still differs in significant ways from browsers so we have to be careful).

Not a hard requirement, but it would be nice to have an additional check here, such as dispatcher && isUndici ? … where something is determined inside createClient() to check if the fetch() function signature will accept this param or not.

Copy link
Contributor

@drwpow drwpow left a comment

Choose a reason for hiding this comment

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

I’m still in favor of adding this feature, and this is getting there, but we’re missing documentation! We need to answer:

  1. When would users use this option? What usecases/prior art? (We chatted about this in another issue, so just consolidating that into docs so others can find that info)
  2. How would they opt in? Do they need to use undici? Will other custom fetch clients work?
  3. What is some example code they can copy/paste to get started with this feature?

All of this should be clear to users how to use this function.

Also be sure to add a patch changeset to openapi-fetch (yes this is a feature add, but we’re following the convention of minor changes are breaking in 0.x, and this isn’t breaking, I believe)!

await client.GET("/self");

// assert baseUrl and path mesh as expected
expect(getRequestUrl().href).toBe(toAbsoluteURL("/self"));
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this test testing what we think it is? I don’t see how this uses dispatch (or maybe I’m missing it?)

@mellster2012
Copy link
Contributor Author

I'll work on the improvements/suggestions as soon as time permits, including the documentation.

@mellster2012
Copy link
Contributor Author

mellster2012 commented Sep 6, 2024

The Dispatcher type is quite large and contains other (nested) undici custom types, and including all these extra types doesn't provide much benefit for the bloat. Also the fetch implementation here by default does not provide an optional RequestInit, rather an expanded requestInit is hidden within the CustomRequest type, which seems already like a deviation.

My suggestion would be to revert back to providing the optional addition of custom RequestInit properties into the ClientOptions, e.g. RequestInitExtensions of type Record<string, unknown>, so any number of custom properties can be added, and pass them to the fetch call as 2nd parameter as RequestInit when present (like it's currently proposed in this PR), with the user assuming the control and responsibility of using the correct custom fetch implementation with it.

@drwpow @kerwanp let me know what you think - thanks!

@drwpow
Copy link
Contributor

drwpow commented Oct 25, 2024

My suggestion would be to revert back to providing the optional addition of custom RequestInit properties into the ClientOptions, e.g. RequestInitExtensions of type Record<string, unknown>, so any number of custom properties can be added, and pass them to the fetch call as 2nd parameter as RequestInit when present (like it's currently proposed in this PR), with the user assuming the control and responsibility of using the correct custom fetch implementation with it.

@drwpow @kerwanp let me know what you think - thanks!

I’m on board with trying that. Currently the problem with using the 2nd parameter approach is we found out that the fetch() implementation is different across different browsers and Node 😓. Specifically, most implementations want EITHER ✅ fetch(Request) OR ✅ fetch(string, RequestInit object), but NEVER ❌ fetch(string, Request) or ❌ fetch(Request, object).

Fortunately we added tests to catch this that does catch some gamebreaking regressions from happening again, but taking a 2nd look over everything I’m not confident we have all the tests in place (will work on adding that). All that said, for now, we’re somewhat stuck with the single-param fetch API of fetch(Request) as long as we have our current middleware API that uses Request/Response for performance and minimalism. But to that end, we can adjust the middleware API too and improve that with, say, a proper RequestInit object. But one decision affects the other, and vice-versa.

Sorry for the extra context; this just overlaps several other APIs/behavior, and past regressions, so I wanted to spend a little more thought on it.

Also the fetch implementation here by default does not provide an optional RequestInit, rather an expanded requestInit is hidden within the CustomRequest type, which seems already like a deviation.

To previous point, the CustomRequest type extends the built-in Request class, and though it does allow for additional properties, is still a valid implementation of the fetch spec that works in Node.js and all browsers, and is tested and working. So any changes to the fetch() call will just need a LOT of testing.

@drwpow drwpow added the openapi-fetch Relevant to the openapi-fetch library label Oct 26, 2024
@mellster2012
Copy link
Contributor Author

mellster2012 commented Nov 22, 2024

Sounds good, starting a fresh PR.

@mellster2012
Copy link
Contributor Author

#2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
openapi-fetch Relevant to the openapi-fetch library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants