diff --git a/examples/basics/package.json b/examples/basics/package.json index 9c64cd2b8bc0..bb6ca0e5dbfa 100644 --- a/examples/basics/package.json +++ b/examples/basics/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/blog/package.json b/examples/blog/package.json index 3207e29547ef..d7e3755bfb21 100644 --- a/examples/blog/package.json +++ b/examples/blog/package.json @@ -14,6 +14,6 @@ "@astrojs/mdx": "^3.1.9", "@astrojs/rss": "^4.0.9", "@astrojs/sitemap": "^3.2.1", - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/component/package.json b/examples/component/package.json index 00b21725de4c..bef28130fe32 100644 --- a/examples/component/package.json +++ b/examples/component/package.json @@ -15,7 +15,7 @@ ], "scripts": {}, "devDependencies": { - "astro": "^4.16.11" + "astro": "^4.16.12" }, "peerDependencies": { "astro": "^4.0.0" diff --git a/examples/container-with-vitest/package.json b/examples/container-with-vitest/package.json index 209517b3c109..a67eefdad308 100644 --- a/examples/container-with-vitest/package.json +++ b/examples/container-with-vitest/package.json @@ -12,7 +12,7 @@ "test": "vitest run" }, "dependencies": { - "astro": "^4.16.11", + "astro": "^4.16.12", "@astrojs/react": "^3.6.2", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/examples/framework-alpine/package.json b/examples/framework-alpine/package.json index 7216c73d14fb..f9d0bf2340e6 100644 --- a/examples/framework-alpine/package.json +++ b/examples/framework-alpine/package.json @@ -14,6 +14,6 @@ "@astrojs/alpinejs": "^0.4.0", "@types/alpinejs": "^3.13.10", "alpinejs": "^3.14.3", - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/framework-lit/package.json b/examples/framework-lit/package.json index c57bfb792c25..66730f1ad759 100644 --- a/examples/framework-lit/package.json +++ b/examples/framework-lit/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/lit": "^4.3.0", "@webcomponents/template-shadowroot": "^0.2.1", - "astro": "^4.16.11", + "astro": "^4.16.12", "lit": "^3.2.1" } } diff --git a/examples/framework-multiple/package.json b/examples/framework-multiple/package.json index 5495d4655f4f..fa0af0805e23 100644 --- a/examples/framework-multiple/package.json +++ b/examples/framework-multiple/package.json @@ -18,7 +18,7 @@ "@astrojs/vue": "^4.5.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", - "astro": "^4.16.11", + "astro": "^4.16.12", "preact": "^10.24.3", "react": "^18.3.1", "react-dom": "^18.3.1", diff --git a/examples/framework-preact/package.json b/examples/framework-preact/package.json index 6ab39cf91ed2..075f2287c9d8 100644 --- a/examples/framework-preact/package.json +++ b/examples/framework-preact/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/preact": "^3.5.3", "@preact/signals": "^1.3.0", - "astro": "^4.16.11", + "astro": "^4.16.12", "preact": "^10.24.3" } } diff --git a/examples/framework-react/package.json b/examples/framework-react/package.json index f1e5c4f217c1..607ffdf2e64a 100644 --- a/examples/framework-react/package.json +++ b/examples/framework-react/package.json @@ -14,7 +14,7 @@ "@astrojs/react": "^3.6.2", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", - "astro": "^4.16.11", + "astro": "^4.16.12", "react": "^18.3.1", "react-dom": "^18.3.1" } diff --git a/examples/framework-solid/package.json b/examples/framework-solid/package.json index 5565c2ccf01a..4445b4a102d7 100644 --- a/examples/framework-solid/package.json +++ b/examples/framework-solid/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/solid-js": "^4.4.2", - "astro": "^4.16.11", + "astro": "^4.16.12", "solid-js": "^1.9.3" } } diff --git a/examples/framework-svelte/package.json b/examples/framework-svelte/package.json index 9645ab227ca6..779267dd64ba 100644 --- a/examples/framework-svelte/package.json +++ b/examples/framework-svelte/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/svelte": "^5.7.3", - "astro": "^4.16.11", + "astro": "^4.16.12", "svelte": "^5.1.16" } } diff --git a/examples/framework-vue/package.json b/examples/framework-vue/package.json index a5e7b2689586..6f958985a460 100644 --- a/examples/framework-vue/package.json +++ b/examples/framework-vue/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@astrojs/vue": "^4.5.2", - "astro": "^4.16.11", + "astro": "^4.16.12", "vue": "^3.5.12" } } diff --git a/examples/hackernews/package.json b/examples/hackernews/package.json index ebfff074be9c..da868174d01c 100644 --- a/examples/hackernews/package.json +++ b/examples/hackernews/package.json @@ -12,6 +12,6 @@ }, "dependencies": { "@astrojs/node": "^8.3.4", - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/integration/package.json b/examples/integration/package.json index 846ac11773ab..86bfeaa8decd 100644 --- a/examples/integration/package.json +++ b/examples/integration/package.json @@ -15,7 +15,7 @@ ], "scripts": {}, "devDependencies": { - "astro": "^4.16.11" + "astro": "^4.16.12" }, "peerDependencies": { "astro": "^4.0.0" diff --git a/examples/minimal/package.json b/examples/minimal/package.json index 9c01f84ee732..3af139efdc3c 100644 --- a/examples/minimal/package.json +++ b/examples/minimal/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/portfolio/package.json b/examples/portfolio/package.json index f20d2eae917f..02c2c8384e2e 100644 --- a/examples/portfolio/package.json +++ b/examples/portfolio/package.json @@ -11,6 +11,6 @@ "astro": "astro" }, "dependencies": { - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/ssr/package.json b/examples/ssr/package.json index 876b53fe4a6a..acc59c15340c 100644 --- a/examples/ssr/package.json +++ b/examples/ssr/package.json @@ -14,7 +14,7 @@ "dependencies": { "@astrojs/node": "^8.3.4", "@astrojs/svelte": "^5.7.3", - "astro": "^4.16.11", + "astro": "^4.16.12", "svelte": "^5.1.16" } } diff --git a/examples/starlog/package.json b/examples/starlog/package.json index df175b24ff04..cf9aee8bad53 100644 --- a/examples/starlog/package.json +++ b/examples/starlog/package.json @@ -10,7 +10,7 @@ "astro": "astro" }, "dependencies": { - "astro": "^4.16.11", + "astro": "^4.16.12", "sass": "^1.80.6", "sharp": "^0.33.3" } diff --git a/examples/toolbar-app/package.json b/examples/toolbar-app/package.json index 1dc223fa6628..e8a23892ec5e 100644 --- a/examples/toolbar-app/package.json +++ b/examples/toolbar-app/package.json @@ -15,6 +15,6 @@ "./app": "./dist/app.js" }, "devDependencies": { - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/with-markdoc/package.json b/examples/with-markdoc/package.json index ebe40b589520..bca2443b1c2c 100644 --- a/examples/with-markdoc/package.json +++ b/examples/with-markdoc/package.json @@ -12,6 +12,6 @@ }, "dependencies": { "@astrojs/markdoc": "^0.11.5", - "astro": "^4.16.11" + "astro": "^4.16.12" } } diff --git a/examples/with-mdx/package.json b/examples/with-mdx/package.json index 8f486fb801f1..70ba88b2fbb1 100644 --- a/examples/with-mdx/package.json +++ b/examples/with-mdx/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/mdx": "^3.1.9", "@astrojs/preact": "^3.5.3", - "astro": "^4.16.11", + "astro": "^4.16.12", "preact": "^10.24.3" } } diff --git a/examples/with-nanostores/package.json b/examples/with-nanostores/package.json index 759a8e5e1cd5..557adbaf1445 100644 --- a/examples/with-nanostores/package.json +++ b/examples/with-nanostores/package.json @@ -13,7 +13,7 @@ "dependencies": { "@astrojs/preact": "^3.5.3", "@nanostores/preact": "^0.5.2", - "astro": "^4.16.11", + "astro": "^4.16.12", "nanostores": "^0.11.3", "preact": "^10.24.3" } diff --git a/examples/with-tailwindcss/package.json b/examples/with-tailwindcss/package.json index 4d8860e94a7e..901f494c6546 100644 --- a/examples/with-tailwindcss/package.json +++ b/examples/with-tailwindcss/package.json @@ -14,7 +14,7 @@ "@astrojs/mdx": "^3.1.9", "@astrojs/tailwind": "^5.1.2", "@types/canvas-confetti": "^1.6.4", - "astro": "^4.16.11", + "astro": "^4.16.12", "autoprefixer": "^10.4.20", "canvas-confetti": "^1.9.3", "postcss": "^8.4.47", diff --git a/examples/with-vitest/package.json b/examples/with-vitest/package.json index 7778c8de2c9b..21ca1eac0a06 100644 --- a/examples/with-vitest/package.json +++ b/examples/with-vitest/package.json @@ -12,7 +12,7 @@ "test": "vitest" }, "dependencies": { - "astro": "^4.16.11", + "astro": "^4.16.12", "vitest": "^2.1.4" } } diff --git a/packages/astro/CHANGELOG.md b/packages/astro/CHANGELOG.md index 50d2f4263142..87d6178e1b2e 100644 --- a/packages/astro/CHANGELOG.md +++ b/packages/astro/CHANGELOG.md @@ -1,5 +1,11 @@ # astro +## 4.16.12 + +### Patch Changes + +- [#12420](https://github.com/withastro/astro/pull/12420) [`acac0af`](https://github.com/withastro/astro/commit/acac0af53466f8a381ccdac29ed2ad735d7b4e79) Thanks [@ematipico](https://github.com/ematipico)! - Fixes an issue where the dev server returns a 404 status code when a user middleware returns a valid `Response`. + ## 4.16.11 ### Patch Changes diff --git a/packages/astro/package.json b/packages/astro/package.json index 4534f1ce057b..e7ddcb616e6e 100644 --- a/packages/astro/package.json +++ b/packages/astro/package.json @@ -1,6 +1,6 @@ { "name": "astro", - "version": "4.16.11", + "version": "4.16.12", "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.", "type": "module", "author": "withastro", diff --git a/packages/astro/src/core/constants.ts b/packages/astro/src/core/constants.ts index 6183e155721c..dc09a1f69474 100644 --- a/packages/astro/src/core/constants.ts +++ b/packages/astro/src/core/constants.ts @@ -31,6 +31,11 @@ export const REWRITE_DIRECTIVE_HEADER_KEY = 'X-Astro-Rewrite'; export const REWRITE_DIRECTIVE_HEADER_VALUE = 'yes'; +/** + * This header is set by the no-op Astro middleware. + */ +export const NOOP_MIDDLEWARE_HEADER = 'X-Astro-Noop'; + /** * The name for the header used to help i18n middleware, which only needs to act on "page" and "fallback" route types. */ diff --git a/packages/astro/src/core/middleware/noop-middleware.ts b/packages/astro/src/core/middleware/noop-middleware.ts index bf5f10d89054..b141285f699c 100644 --- a/packages/astro/src/core/middleware/noop-middleware.ts +++ b/packages/astro/src/core/middleware/noop-middleware.ts @@ -1,3 +1,7 @@ import type { MiddlewareHandler } from '../../@types/astro.js'; +import { NOOP_MIDDLEWARE_HEADER } from '../constants.js'; -export const NOOP_MIDDLEWARE_FN: MiddlewareHandler = (_, next) => next(); +export const NOOP_MIDDLEWARE_FN: MiddlewareHandler = (ctx, next) => { + ctx.request.headers.set(NOOP_MIDDLEWARE_HEADER, 'true'); + return next(); +}; diff --git a/packages/astro/src/vite-plugin-astro-server/route.ts b/packages/astro/src/vite-plugin-astro-server/route.ts index 9f6d434b55e8..8de52d158bb0 100644 --- a/packages/astro/src/vite-plugin-astro-server/route.ts +++ b/packages/astro/src/vite-plugin-astro-server/route.ts @@ -2,6 +2,7 @@ import type http from 'node:http'; import type { ComponentInstance, ManifestData, RouteData } from '../@types/astro.js'; import { DEFAULT_404_COMPONENT, + NOOP_MIDDLEWARE_HEADER, REROUTE_DIRECTIVE_HEADER, REWRITE_DIRECTIVE_HEADER_KEY, clientLocalsSymbol, @@ -191,16 +192,11 @@ export async function handleRoute({ mod = preloadedComponent; - const isDefaultPrerendered404 = - matchedRoute.route.route === '/404' && - matchedRoute.route.prerender && - matchedRoute.route.component === DEFAULT_404_COMPONENT; - renderContext = await RenderContext.create({ locals, pipeline, pathname, - middleware: isDefaultPrerendered404 ? undefined : middleware, + middleware: isDefaultPrerendered404(matchedRoute.route) ? undefined : middleware, request, routeData: route, }); @@ -213,10 +209,15 @@ export async function handleRoute({ response = await renderContext.render(mod); isReroute = response.headers.has(REROUTE_DIRECTIVE_HEADER); isRewrite = response.headers.has(REWRITE_DIRECTIVE_HEADER_KEY); + const statusCodedMatched = getStatusByMatchedRoute(matchedRoute); statusCode = isRewrite ? // Ignore `matchedRoute` status for rewrites response.status - : (getStatusByMatchedRoute(matchedRoute) ?? response.status); + : // Our internal noop middleware sets a particular header. If the header isn't present, it means that the user have + // their own middleware, so we need to return what the user returns. + !response.headers.has(NOOP_MIDDLEWARE_HEADER) && !isReroute + ? response.status + : (statusCodedMatched ?? response.status); } catch (err: any) { const custom500 = getCustom500Route(manifestData); if (!custom500) { @@ -308,3 +309,7 @@ function getStatusByMatchedRoute(matchedRoute?: MatchedRoute) { if (matchedRoute?.route.route === '/500') return 500; return undefined; } + +function isDefaultPrerendered404(route: RouteData) { + return route.route === '/404' && route.prerender && route.component === DEFAULT_404_COMPONENT; +} diff --git a/packages/astro/test/fixtures/middleware space/src/middleware.js b/packages/astro/test/fixtures/middleware space/src/middleware.js index 6310994554ea..185fc31168e7 100644 --- a/packages/astro/test/fixtures/middleware space/src/middleware.js +++ b/packages/astro/test/fixtures/middleware space/src/middleware.js @@ -74,4 +74,13 @@ const third = defineMiddleware(async (context, next) => { return next(); }); -export const onRequest = sequence(first, second, third); +const fourth = defineMiddleware((context, next) => { + if (context.request.url.includes('/no-route-but-200')) { + return new Response("It's OK!", { + status: 200 + }); + } + return next() +}) + +export const onRequest = sequence(first, second, third, fourth); diff --git a/packages/astro/test/middleware.test.js b/packages/astro/test/middleware.test.js index 612937d80433..2bcfe8d57d41 100644 --- a/packages/astro/test/middleware.test.js +++ b/packages/astro/test/middleware.test.js @@ -70,6 +70,13 @@ describe('Middleware in DEV mode', () => { assert.equal($('title').html(), 'MiddlewareNoDataOrNextCalled'); }); + it('should return 200 if the middleware returns a 200 Response', async () => { + const response = await fixture.fetch('/no-route-but-200'); + assert.equal(response.status, 200); + const html = await response.text(); + assert.match(html, /It's OK!/); + }); + it('should allow setting cookies', async () => { const res = await fixture.fetch('/'); assert.equal(res.headers.get('set-cookie'), 'foo=bar'); @@ -239,6 +246,14 @@ describe('Middleware API in PROD mode, SSR', () => { assert.notEqual($('title').html(), 'MiddlewareNoDataReturned'); }); + it('should return 200 if the middleware returns a 200 Response', async () => { + const request = new Request('http://example.com/no-route-but-200'); + const response = await app.render(request); + assert.equal(response.status, 200); + const html = await response.text(); + assert.match(html, /It's OK!/); + }); + it('should correctly work for API endpoints that return a Response object', async () => { const request = new Request('http://example.com/api/endpoint'); const response = await app.render(request); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bacad1731905..e3066152ca04 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -139,7 +139,7 @@ importers: examples/basics: dependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/blog: @@ -154,13 +154,13 @@ importers: specifier: ^3.2.1 version: link:../../packages/integrations/sitemap astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/component: devDependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/container-with-vitest: @@ -169,7 +169,7 @@ importers: specifier: ^3.6.2 version: link:../../packages/integrations/react astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro react: specifier: ^18.3.1 @@ -200,7 +200,7 @@ importers: specifier: ^3.14.3 version: 3.14.3 astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/framework-lit: @@ -212,7 +212,7 @@ importers: specifier: ^0.2.1 version: 0.2.1 astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro lit: specifier: ^3.2.1 @@ -242,7 +242,7 @@ importers: specifier: ^18.3.1 version: 18.3.1 astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro preact: specifier: ^10.24.3 @@ -272,7 +272,7 @@ importers: specifier: ^1.3.0 version: 1.3.0(preact@10.24.3) astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro preact: specifier: ^10.24.3 @@ -290,7 +290,7 @@ importers: specifier: ^18.3.1 version: 18.3.1 astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro react: specifier: ^18.3.1 @@ -305,7 +305,7 @@ importers: specifier: ^4.4.2 version: link:../../packages/integrations/solid astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro solid-js: specifier: ^1.9.3 @@ -317,7 +317,7 @@ importers: specifier: ^5.7.3 version: link:../../packages/integrations/svelte astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro svelte: specifier: ^5.1.16 @@ -329,7 +329,7 @@ importers: specifier: ^4.5.2 version: link:../../packages/integrations/vue astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro vue: specifier: ^3.5.12 @@ -341,25 +341,25 @@ importers: specifier: ^8.3.4 version: 8.3.4(astro@packages+astro) astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/integration: devDependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/minimal: dependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/portfolio: dependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/ssr: @@ -371,7 +371,7 @@ importers: specifier: ^5.7.3 version: link:../../packages/integrations/svelte astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro svelte: specifier: ^5.1.16 @@ -380,7 +380,7 @@ importers: examples/starlog: dependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro sass: specifier: ^1.80.6 @@ -392,7 +392,7 @@ importers: examples/toolbar-app: devDependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/with-markdoc: @@ -401,7 +401,7 @@ importers: specifier: ^0.11.5 version: link:../../packages/integrations/markdoc astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro examples/with-mdx: @@ -413,7 +413,7 @@ importers: specifier: ^3.5.3 version: link:../../packages/integrations/preact astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro preact: specifier: ^10.24.3 @@ -428,7 +428,7 @@ importers: specifier: ^0.5.2 version: 0.5.2(nanostores@0.11.3)(preact@10.24.3) astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro nanostores: specifier: ^0.11.3 @@ -449,7 +449,7 @@ importers: specifier: ^1.6.4 version: 1.6.4 astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro autoprefixer: specifier: ^10.4.20 @@ -467,7 +467,7 @@ importers: examples/with-vitest: dependencies: astro: - specifier: ^4.16.11 + specifier: ^4.16.12 version: link:../../packages/astro vitest: specifier: ^2.1.4