diff options
author | 2025-03-24 14:23:37 +0000 | |
---|---|---|
committer | 2025-03-24 14:23:37 +0000 | |
commit | fc2dcb83543d88af9e0920b90a035652d6db5166 (patch) | |
tree | 996754563d7c204c09411469a5f0d50f16a13a3e | |
parent | 6b9020026fc0745143a5c5751a3d73f4ff05d136 (diff) | |
download | astro-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.md | 5 | ||||
-rw-r--r-- | packages/astro/src/core/app/index.ts | 10 | ||||
-rw-r--r-- | packages/astro/test/fixtures/middleware space/integration-middleware-post.js | 4 | ||||
-rw-r--r-- | packages/astro/test/middleware.test.js | 12 |
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); |