-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix(astro): Handle errors in middlewares better #16693
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
base: develop
Are you sure you want to change the base?
Conversation
The error description indicates that calling The controller may be closed by downstream code for multiple reasons, like a canceled request or a closed connection. I think (would have to look at the docs) there is a |
ahh I see, that makes sense. Should we maybe simply not send errors from this to sentry, then 🤔 is there a value in doing this? So just: try {
for await (const chunk of originalBody) {
const html = typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true });
const modifiedHtml = addMetaTagToHead(html);
controller.enqueue(new TextEncoder().encode(modifiedHtml));
}
} catch (e) {
controller.error(e);
} finally {
controller.close();
} would lose some visibility, but probably ok...? We could just |
A bit tricky 🤔 The iterator can fail with a user error from a component, but the body of the loop can error out of the user's control. We'd be switching from reporting unactionable errors to not reporting actionable ones. If we hand roll the iteration using the interface and a while loop we could have the try/catch on each part with different error handlers. |
Here is one way to avoid that: // Assign to a new variable to avoid TS losing the narrower type checked above.
const body = originalBody;
async function* bodyReporter(): AsyncGenerator<string | Buffer> {
try {
for await (const chunk of body) {
yield chunk;
}
} catch (e) {
// Report stream errors coming from user code or Astro rendering.
sendErrorToSentry(e);
throw e;
}
}
const reportedBody = bodyReporter();
try {
for await (const chunk of reportedBody) {
const html = typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true });
const modifiedHtml = addMetaTagToHead(html);
controller.enqueue(new TextEncoder().encode(modifiedHtml));
}
} catch (e) {
controller.error(e);
} finally {
controller.close();
} |
nice, thank you, that makes sense to me! is there a good way to test that this actually works? 😅 |
98aeae9
to
32e798f
Compare
controller.close()
usage32e798f
to
bd0f08c
Compare
Hum... A little tricky because this is deeply inside of Astro. You can make a component with |
Hopefully fixes #16491
I could not get a reproducing test there for this 🤔 I figure this is "safe" to do, but not quite sure how/when this would happen. I would assume this was "introduced" by #15995, maybe @Fryuni has a clue how/when that could happen and if this is a reasonable change 🤔