-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
Bugfix #7070 Middleware not working with endpoints #7079
Conversation
* when middleware is used with endpoints, defer execution of **renderEndpoint** until the middleware invokes next() (making it properly chainable, like it is for pages) * stronger type definitions for endpoint return types so that the types can be reused for a few purposes * abstract conversion of endpoint "simple" return type into a Response into a reusable function * modify endpoint middleware next() implementation, which invokes **renderEndpoint**, to convert any simple result into a Response and log a warning * add unit test coverage * expand the @examples/middleware to show usage with endpoint scenarios
🦋 Changeset detectedLatest commit: 72d61a4 The changes in this PR will be included in the next version bump. 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 |
I'm not sure why the checks are failing on:
I didn't change this import on util.ts, and the tests run locally OK for me. I re-pushed a commit to get these checks to re-run and they failed again for the same reason Are the GitHub CI tests flaky, or did my PR really change something tangible causing this? |
} else { | ||
warn( | ||
logging, | ||
'ssr', |
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.
Any particular reason to use ssr
as logging instead of middleware
?
@@ -16,21 +16,24 @@ import { AstroError, AstroErrorData } from '../errors/index.js'; | |||
import { warn, type LogOptions } from '../logger/core.js'; | |||
import { callMiddleware } from '../middleware/callMiddleware.js'; | |||
import { isValueSerializable } from '../render/core.js'; | |||
import { simpleEndpointOutputToResponse } from '../util.js'; |
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.
We can't import util
in this file because this file relies on node:
specific utilities. It's preferable to move simpleEndpointOutputToResponse
somewhere else, where node
is not used.
@@ -221,3 +224,31 @@ export function resolvePath(specifier: string, importer: string) { | |||
return specifier; | |||
} | |||
} | |||
|
|||
// EndpointOutput.body is typed as "Body" (not exported) which is only allowed to be a string | |||
export function isEndpointOutput(o: any): o is EndpointOutput { |
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.
nit: I think we can give a better name instead of o
. Maybe "responseOutput" works better
Here's why |
Ok I got it. Based on your issue comment here: #7070 (comment) Then, I'm happy to wait for an update from you/astro team.. as it stands right now I put some code in there which converts For now I will update this PR so it works how I intended and let you decide what direction to go in, I'm happy to contribute more changes to align with that |
Closing in favor of #7106 |
Changes
renderEndpoint
until the middleware invokesnext()
(making it properly chainable, like it is for pages)next()
implementation, which invokesrenderEndpoint
, to convert any simple result into a Response and log a warning. This is necessary because middleware handlers are typed to only support receiving aResponse
instance from the result ofnext()
.I looked into changing middleware handlers to all needing to handle
Response | EndpointOutput
, but that was a deep rabbit hole that would have potentially breaking changes for any existing middleware handler code out in the wild.So, instead, to make middleware "just work" for all use cases, in a sane way people would expect (which is that middleware should ALWAYS run, so you can trust it for things like auth/session checks, etc), I added an automatic conversion from any endpoint "simple" result into a
Response
immediately after it's resolved vianext()
using the same process thatApp.callEndpoint
used, abstracting that functionality into a common utility function.Testing
Unit tests were added which cover:
Response
resultResponse
directly, never invokingnext()
(thus the API endpoint is never executed)text/plain;charset=utf-8
encodingapplication/json;charset=utf-8
encoding derived from path extensionDocs
/cc @withastro/maintainers-docs for feedback!