Conversation
🦋 Changeset detectedLatest commit: bea82f0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
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 |
There was a problem hiding this comment.
Pull request overview
This PR introduces request-aware diagnostics for unhandled crashes in Qwik City integrations by exposing the “current request event” via a new public API, and then using it in starter templates to enrich uncaught-exception logging. It also hardens resource deserialization against thenable/promise-like values and improves how request-handler completion errors are surfaced for edge adapters.
Changes:
- Add
getRequestEvent()as a public Qwik City runtime export, with generated API/docs updates and unit tests. - Update multiple starter adapters (Node/Express/Fastify/Cloud Run/Bun/Deno) to log request metadata on unhandled exceptions (and in some runtimes, unhandled rejections).
- Harden
ResourceSerializeragainst deserialized thenables and ensure rejected resource promises are handled without triggering unhandled-rejection noise; add unit tests.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| starters/apps/perf.prod/src/entry.express.tsx | Adds uncaught-exception monitoring and logs request context using getRequestEvent(). |
| starters/adapters/node-server/src/entry.node-server.tsx | Adds uncaught-exception monitoring and logs request context using getRequestEvent(). |
| starters/adapters/fastify/src/entry.fastify.tsx | Adds uncaught-exception monitoring and logs request context using getRequestEvent(). |
| starters/adapters/express/src/entry.express.tsx | Adds uncaught-exception monitoring and logs request context using getRequestEvent(). |
| starters/adapters/deno/src/entry.deno.ts | Adds global error/unhandledrejection listeners and logs request context via getRequestEvent(). |
| starters/adapters/cloud-run/src/entry.cloud-run.tsx | Adds uncaught-exception monitoring and logs request context using getRequestEvent(). |
| starters/adapters/bun/src/entry.bun.ts | Adds uncaught-exception/unhandled-rejection handlers and logs request context via getRequestEvent(). |
| packages/qwik/src/core/container/serializers.ts | Adds thenable detection + handled rejected promises; rejects unsafe deserialized resource values. |
| packages/qwik/src/core/container/serializers.unit.ts | Adds unit tests for ResourceSerializer thenable-rejection behavior. |
| packages/qwik-city/src/runtime/src/server-functions.ts | Exports new public getRequestEvent() helper. |
| packages/qwik-city/src/runtime/src/server-functions.unit.ts | Adds unit tests covering getRequestEvent() behavior with/without async request store. |
| packages/qwik-city/src/runtime/src/index.ts | Re-exports getRequestEvent() from the runtime entrypoint. |
| packages/qwik-city/src/runtime/src/qwik-city.runtime.api.md | Updates API extractor output to include getRequestEvent. |
| packages/qwik-city/src/middleware/request-handler/user-response.ts | Makes completion always resolve (captures errors) and handles createRequestEvent failures. |
| packages/qwik-city/src/middleware/request-handler/user-response.unit.ts | Adds test for runQwikCity behavior when request-event creation fails. |
| packages/qwik-city/src/middleware/vercel-edge/index.ts | Renames completion callback var to err and logs completion errors. |
| packages/qwik-city/src/middleware/netlify-edge/index.ts | Renames completion callback var to err and logs completion errors. |
| packages/qwik-city/src/middleware/deno/index.ts | Renames completion callback var to err and logs completion errors. |
| packages/qwik-city/src/middleware/cloudflare-pages/index.ts | Renames completion callback var to err and logs completion errors. |
| packages/qwik-city/src/middleware/bun/index.ts | Renames completion callback var to err and logs completion errors. |
| packages/docs/src/routes/api/qwik-city/index.mdx | Adds API docs section entry for getRequestEvent. |
| packages/docs/src/routes/api/qwik-city/api.json | Adds getRequestEvent entry to generated API JSON. |
| .changeset/swift-numbers-reply.md | Adds changeset documenting the new getRequestEvent() feature. |
Comments suppressed due to low confidence (5)
packages/qwik-city/src/middleware/vercel-edge/index.ts:101
- In the
createRequestEventfailure path,handledResponse.responsecan resolve tonullwhilehandledResponse.completionresolves to an error. In that case this middleware will currently fall through to the 404 response even though an internal error occurred. Consider: ifresponseis falsy, awaitcompletionand return a 500 response when it contains an error (instead of returning Not Found).
const handledResponse = await requestHandler(serverRequestEv, opts, qwikSerializer);
if (handledResponse) {
handledResponse.completion.then((err) => {
if (err) {
console.error(err);
}
});
const response = await handledResponse.response;
if (response) {
return response;
}
}
packages/qwik-city/src/middleware/netlify-edge/index.ts:74
- Same as other edge adapters: if
handledResponse.responseresolves tonullbuthandledResponse.completionresolves to an error (e.g., request event creation failure), this will fall back to the 404 path. Consider checkingcompletionwhenresponseis falsy and returning a 500 instead of Not Found.
// send request to qwik city request handler
const handledResponse = await requestHandler(serverRequestEv, opts, qwikSerializer);
if (handledResponse) {
handledResponse.completion.then((err) => {
if (err) {
console.error(err);
}
});
const response = await handledResponse.response;
if (response) {
return response;
}
}
packages/qwik-city/src/middleware/deno/index.ts:99
- If
handledResponse.responseresolves tonullbuthandledResponse.completionresolves to an error (e.g.,createRequestEventthrowing), this router returnsnull(treated as “not handled”), which can lead to a misleading 404 later. Consider awaitingcompletionwhenresponseis falsy and returning a 500 response when an error is present.
// send request to qwik city request handler
const handledResponse = await requestHandler(serverRequestEv, opts, qwikSerializer);
if (handledResponse) {
handledResponse.completion.then((err) => {
if (err) {
console.error(err);
}
});
const response = await handledResponse.response;
if (response) {
return response;
}
}
packages/qwik-city/src/middleware/cloudflare-pages/index.ts:113
- If
handledResponse.responseresolves tonullbuthandledResponse.completionresolves to an error (e.g., request event creation failure), this will currently fall through to the 404 response. Consider checkingcompletionwhenresponseis falsy and returning a 500 response instead of Not Found so internal errors aren’t masked as 404s.
// send request to qwik city request handler
const handledResponse = await requestHandler(serverRequestEv, opts, qwikSerializer);
if (handledResponse) {
handledResponse.completion.then((err) => {
if (err) {
console.error(err);
}
});
const response = await handledResponse.response;
if (response) {
if (response.ok && cache && response.headers.has('Cache-Control')) {
// Store the fetched response as cacheKey
// Use waitUntil so you can return the response without blocking on
// writing to cache
ctx.waitUntil(cache.put(cacheKey, response.clone()));
}
return response;
}
}
packages/qwik-city/src/middleware/bun/index.ts:98
- If
handledResponse.responseresolves tonullbuthandledResponse.completionresolves to an error (e.g.,createRequestEventthrowing), this router returnsnulland the request is treated as “not handled”. Consider awaitingcompletionwhenresponseis falsy and returning a 500 response when an error is present so failures don’t get misclassified as not-found.
// send request to qwik city request handler
const handledResponse = await requestHandler(serverRequestEv, opts, qwikSerializer);
if (handledResponse) {
handledResponse.completion.then((err) => {
if (err) {
console.error(err);
}
});
const response = await handledResponse.response;
if (response) {
// bun fails to redirect if there is a body.
// remove the body if there a redirect.
const status = response.status;
const location = response.headers.get('Location');
const isRedirect = status >= 301 && status <= 308 && location;
if (isRedirect) {
return new Response(null, response);
}
return response;
}
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
commit: |
built with Refined Cloudflare Pages Action⚡ Cloudflare Pages Deployment
|
No description provided.