summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Emanuele Stoppa <my.burning@gmail.com> 2025-03-24 14:23:37 +0000
committerGravatar GitHub <noreply@github.com> 2025-03-24 14:23:37 +0000
commitfc2dcb83543d88af9e0920b90a035652d6db5166 (patch)
tree996754563d7c204c09411469a5f0d50f16a13a3e
parent6b9020026fc0745143a5c5751a3d73f4ff05d136 (diff)
downloadastro-fc2dcb83543d88af9e0920b90a035652d6db5166.tar.gz
astro-fc2dcb83543d88af9e0920b90a035652d6db5166.tar.zst
astro-fc2dcb83543d88af9e0920b90a035652d6db5166.zip
fix(app): call renderer when routes don't match (#13483)
* fix(app): call renderer when routes don't match * chore: pick 404 exactly * chore: pick route differently Co-authored-by: ascorbic <213306+ascorbic@users.noreply.github.com>
-rw-r--r--.changeset/wet-bottles-invite.md5
-rw-r--r--packages/astro/src/core/app/index.ts10
-rw-r--r--packages/astro/test/fixtures/middleware space/integration-middleware-post.js4
-rw-r--r--packages/astro/test/middleware.test.js12
4 files changed, 30 insertions, 1 deletions
diff --git a/.changeset/wet-bottles-invite.md b/.changeset/wet-bottles-invite.md
new file mode 100644
index 000000000..629e3d318
--- /dev/null
+++ b/.changeset/wet-bottles-invite.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes a bug where an Astro adapter couldn't call the middleware when there isn't a route that matches the incoming request.
diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts
index 36560478e..baf76a026 100644
--- a/packages/astro/src/core/app/index.ts
+++ b/packages/astro/src/core/app/index.ts
@@ -7,6 +7,7 @@ import {
REROUTE_DIRECTIVE_HEADER,
clientAddressSymbol,
responseSentSymbol,
+ DEFAULT_404_COMPONENT,
} from '../constants.js';
import { getSetCookiesFromResponse } from '../cookies/index.js';
import { AstroError, AstroErrorData } from '../errors/index.js';
@@ -88,7 +89,6 @@ export class App {
#baseWithoutTrailingSlash: string;
#pipeline: AppPipeline;
#adapterLogger: AstroIntegrationLogger;
- #renderOptionsDeprecationWarningShown = false;
constructor(manifest: SSRManifest, streaming = true) {
this.#manifest = manifest;
@@ -331,6 +331,14 @@ export class App {
this.#logger.debug('router', 'Astro matched the following route for ' + request.url);
this.#logger.debug('router', 'RouteData:\n' + routeData);
}
+ // At this point we haven't found a route that matches the request, so we create
+ // a "fake" 404 route, so we can call the RenderContext.render
+ // and hit the middleware, which might be able to return a correct Response.
+ if (!routeData) {
+ routeData = this.#manifestData.routes.find(
+ (route) => route.component === '404.astro' || route.component === DEFAULT_404_COMPONENT,
+ );
+ }
if (!routeData) {
this.#logger.debug('router', "Astro hasn't found routes that match " + request.url);
this.#logger.debug('router', "Here's the available routes:\n", this.#manifestData);
diff --git a/packages/astro/test/fixtures/middleware space/integration-middleware-post.js b/packages/astro/test/fixtures/middleware space/integration-middleware-post.js
index a4e0c90ad..cb1855d48 100644
--- a/packages/astro/test/fixtures/middleware space/integration-middleware-post.js
+++ b/packages/astro/test/fixtures/middleware space/integration-middleware-post.js
@@ -8,6 +8,10 @@ export const onRequest = defineMiddleware((context, next) => {
},
});
}
+
+ if (context.url.pathname === '/does-not-exist') {
+ return context.rewrite('/rewrite');
+ }
return next();
});
diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.test.js
index 75b965932..199128ebd 100644
--- a/packages/astro/test/middleware.test.js
+++ b/packages/astro/test/middleware.test.js
@@ -318,6 +318,18 @@ describe('Middleware API in PROD mode, SSR', () => {
assert.equal(response.headers.get('content-type'), 'text/html');
});
+ it('can render a page that does not exist', async () => {
+ const request = new Request('http://example.com/does-not-exist');
+ const routeData = app.match(request);
+
+ const response = await app.render(request, { routeData });
+ assert.equal(response.status, 200);
+ const html = await response.text();
+ const $ = cheerio.load(html);
+ assert.equal($('p').html(), null);
+ assert.equal($('span').html(), 'New content!!');
+ });
+
it('can set locals for prerendered pages to use', async () => {
const text = await fixture.readFile('/client/prerendered/index.html');
assert.equal(text.includes('<p>yes they can!</p>'), true);