Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cloudflare-prerender-routing-mismatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fixes non-prerendered routes failing when a dynamic prerendered route exists in the same project with `prerenderEnvironment: 'node'`
27 changes: 26 additions & 1 deletion packages/astro/src/vite-plugin-app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,19 @@ export class AstroServerApp extends BaseApp<RunnablePipeline> {
return pipeline;
}

/**
* Handle a request.
* @returns The return value indicates whether or not the request was handled
* by this handler. If the result is not `true`, then the request has not
* been handled yet and other handlers can be run.
*/
public async handleRequest({
controller,
incomingRequest,
incomingResponse,
isHttps,
}: HandleRequest): Promise<void> {
prerenderOnly,
}: HandleRequest): Promise<boolean> {
// When the dev server runs behind a TLS-terminating reverse proxy (e.g.
// Caddy, nginx, Traefik), the proxy connects to Vite over plain HTTP while
// the browser communicates over HTTPS. In that setup isHttps is false, but
Expand Down Expand Up @@ -199,16 +206,31 @@ export class AstroServerApp extends BaseApp<RunnablePipeline> {

const self = this;
await self.#loadFetchHandler();

let handled = true;
await runWithErrorHandling({
controller,
pathname,
async run() {
const matchedRoute = await self.devMatch(pathname);
if (!matchedRoute) {
if (prerenderOnly) {
// In prerender-only mode, signal that we didn't handle this
// so the caller can fall through to the SSR handler.
handled = false;
return;
}
// This should never happen, because ensure404Route will add a 404 route if none exists.
throw new Error('No route matched, and default 404 route was not found.');
}

// When running as the prerender handler, only handle prerendered routes.
// If the best-matching route is SSR, let the SSR handler handle it instead.
if (prerenderOnly && !matchedRoute.routeData.prerender) {
handled = false;
return;
}

const request = createRequest({
url,
headers: incomingRequest.headers,
Expand Down Expand Up @@ -250,6 +272,7 @@ export class AstroServerApp extends BaseApp<RunnablePipeline> {
return error;
},
});
return handled;
}

match(request: Request, _allowPrerenderedRoutes: boolean): RouteData | undefined {
Expand Down Expand Up @@ -282,4 +305,6 @@ type HandleRequest = {
incomingRequest: http.IncomingMessage;
incomingResponse: http.ServerResponse;
isHttps: boolean;
/** When true, only handle prerendered routes. Returns false for SSR routes. */
prerenderOnly?: boolean;
};
9 changes: 7 additions & 2 deletions packages/astro/src/vite-plugin-app/createAstroServerApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,17 @@ export default async function createAstroServerApp(
}

return {
handler(incomingRequest: http.IncomingMessage, incomingResponse: http.ServerResponse) {
app.handleRequest({
handler(
incomingRequest: http.IncomingMessage,
incomingResponse: http.ServerResponse,
options?: { prerenderOnly?: boolean },
) {
return app.handleRequest({
controller,
incomingRequest,
incomingResponse,
isHttps: loader?.isHttps() ?? false,
prerenderOnly: options?.prerenderOnly,
});
},
};
Expand Down
13 changes: 11 additions & 2 deletions packages/astro/src/vite-plugin-astro-server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,18 @@ export default function createVitePluginAstroServer({
return next();
}

localStorage.run(request, () => {
prerenderHandler.handler(request, response);
const handled = await new Promise<boolean>((resolve) => {
localStorage.run(request, () => {
prerenderHandler
.handler(request, response, { prerenderOnly: true })
.then((result: boolean) => resolve(result))
.catch(() => resolve(true));
});
});

if (!handled) {
return next();
}
} catch (err) {
next(err);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
export const prerender = true;

export function getStaticPaths() {
return [
{ params: { page: 'one' } },
{ params: { page: 'two' } },
];
}

const { page } = Astro.params;
---

<html lang="en">
<head>
<meta charset="utf-8" />
<title>Page {page}</title>
</head>
<body>
<h1>Page {page}</h1>
<p id="page-name">{page}</p>
</body>
</html>
Loading