-
-
Notifications
You must be signed in to change notification settings - Fork 488
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
Middleware #1521
Middleware #1521
Conversation
🦋 Changeset detectedLatest commit: fc3a468 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Deploying with Cloudflare Pages
|
77f2787
to
f6bcb23
Compare
|
||
const { | ||
data, // only present if 2XX response | ||
error, // only present if 4XX or 5XX response | ||
} = await GET("/blogposts/{post_id}", { | ||
} = await client.GET("/blogposts/{post_id}", { |
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.
Extremely in-the-weeds: when writing the docs for middleware, I found const { use } = createClient()
to be an awkward syntax (it it just me or does a floating use()
just seem weird?). Renaming it (const { use: useMiddleware }
) also felt awkward. client.use(…)
felt like the most natural syntax, and matched other libraries.
As a result, it felt a little weird in other places to both keep client
around and destructure it, so I opted to simplify and just keep client
around in all places. Really, there’s no recommended syntax, and people can do what they want. I’m just trying to write the docs in the most “copy-pasteable” way 🤷
import type { paths } from "./v1"; | ||
|
||
const throwOnError: Middleware = { |
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.
People have asked for this: a more automatic way to interface with React Query. Hopefully this is sufficient!
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.
I feel this may be generally useful enough to deserve a call out in the middleware docs (even if just cross linking to the example). It may get missed otherwise
@@ -4,130 +4,28 @@ title: openapi-fetch Examples | |||
|
|||
# Examples | |||
|
|||
## Authentication |
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.
With middleware, these awkward, one-off workarounds can go away. Now it can be handled more-automatically (also this entire section was rewritten, and moved to the middleware page).
@@ -81,26 +116,17 @@ export default function createClient(clientOptions) { | |||
if (response.ok) { | |||
// if "stream", skip parsing entirely | |||
if (parseAs === "stream") { | |||
// fix for bun: bun consumes response.body, therefore clone before accessing | |||
// TODO: test this? | |||
return { data: response.clone().body, response }; |
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.
I removed a lot of the .clone()
-ing that was happening internally. I profiled this, and this can be a pretty big bottleneck, in addition to a waste of memory for large responses.
Instead, I’d rather users learn about safe vs unsafe body
access rather than shield them from this. openapi-fetch
will consume the body by calling .json()
automatically (because 99% of the time that’s what users want). And if users need to read the raw body, then they’re doing something advanced and should know to .clone()
.
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 related Bun issue here (#1486) I think is a mixture of a potential bug in Bun (which may be patched by now) along with user error. In either case, will investigate separately rather than cause potential performance bottlenecks for everyone.
Found another issue with type safety. #1525 |
3f45d46
to
831e0b0
Compare
f8e3b5e
to
db0ada7
Compare
|
||
| Library | Size (min) | “GET” request | | ||
| :------------------------- | ---------: | :------------------------- | | ||
| openapi-fetch | `4 kB` | `278k` ops/s (fastest) | | ||
| openapi-fetch | `5 kB` | `278k` ops/s (fastest) | |
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.
🤷 sometimes the bytes do things
|
||
## Mocking Requests | ||
|
||
To test requests, the `fetch` option can be supplied with any spy function like `vi.fn()` (Vitest) or `jest.fn()` (Jest). |
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.
🤔 I’ll probably rewrite this to recommend MSW as I’ve had some good success with it, but will probably wait until I refactor this codebase to use it for testing. Treat this as more of a placeholder.
}); | ||
|
||
// expect post_id to be encoded properly | ||
expect(fetchMocker.mock.calls[0][0]).toBe(`/blogposts/${post_id}`); | ||
expect(fetchMocker.mock.calls[0][0].url).toBe( | ||
`/blogposts/post?id%20=%20🥴`, |
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.
Side-effect of using new Request()
—we’re not encoding anything manually. Seems OK? Still tests UTF-8 sticks
Changes
Addresses #1122 by adding Middleware support. This is an RFC so feedback is welcome! This will be used for testing & feedback before stable release.
You can download the beta version at the
@next
tag:Dev Notes
Please read the docs first to learn about the API. The following are more “meta” notes helpful for early reviewers:
next()
callback.fetch()
land, and in my early testing, I found it to be a little overcomplicated since JSON responses (which this relies on) doesn’t utilize streaming. And to start I wanted to prefer a simpler middleware structure over a complex one (i.e. not encourage over-engineering clientside server setups).use(middleware)
seemed to be a ubiquitous way to register middlewarescreateClient({ middlewares: […] })
array, which doesn’t have any advantages, and only limits how/when middlewares are loaded..eject()
was inspired by Axios interceptors. It may or may not get use, but was essentially free. So why not?How to Review
openapi-fetch@next
.Checklist
docs/
updated (if necessary)pnpm run update:examples
run (only applicable for openapi-typescript)