From 9869f2f6d8c344babb8a59cb54918de14bd95dcc Mon Sep 17 00:00:00 2001 From: wulinsheng123 <409187100@qq.com> Date: Wed, 11 Jan 2023 00:59:20 +0800 Subject: [PATCH] can jump 404 when that page does not exist (#5701) --- .changeset/red-snakes-fetch.md | 5 +++ packages/integrations/node/package.json | 1 + packages/integrations/node/src/middleware.ts | 7 ++-- packages/integrations/node/src/server.ts | 4 +- packages/integrations/node/src/standalone.ts | 2 +- .../integrations/node/test/api-route.test.js | 9 +++-- .../fixtures/node-middleware/package.json | 9 +++++ .../node-middleware/src/pages/404.astro | 13 +++++++ .../node-middleware/src/pages/index.astro | 11 ++++++ .../node/test/node-middleware.test.js | 37 +++++++++++++++++++ pnpm-lock.yaml | 10 +++++ 11 files changed, 99 insertions(+), 9 deletions(-) create mode 100644 .changeset/red-snakes-fetch.md create mode 100644 packages/integrations/node/test/fixtures/node-middleware/package.json create mode 100644 packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro create mode 100644 packages/integrations/node/test/fixtures/node-middleware/src/pages/index.astro create mode 100644 packages/integrations/node/test/node-middleware.test.js diff --git a/.changeset/red-snakes-fetch.md b/.changeset/red-snakes-fetch.md new file mode 100644 index 000000000..a60b006ef --- /dev/null +++ b/.changeset/red-snakes-fetch.md @@ -0,0 +1,5 @@ +--- +'@astrojs/node': patch +--- + +Support custom 404 page in standalone mode diff --git a/packages/integrations/node/package.json b/packages/integrations/node/package.json index 779b8792b..86910a34e 100644 --- a/packages/integrations/node/package.json +++ b/packages/integrations/node/package.json @@ -41,6 +41,7 @@ "astro": "workspace:*", "astro-scripts": "workspace:*", "chai": "^4.3.6", + "cheerio": "^1.0.0-rc.11", "mocha": "^9.2.2", "node-mocks-http": "^1.11.0", "undici": "^5.14.0" diff --git a/packages/integrations/node/src/middleware.ts b/packages/integrations/node/src/middleware.ts index bfa7b74d5..1af4539a6 100644 --- a/packages/integrations/node/src/middleware.ts +++ b/packages/integrations/node/src/middleware.ts @@ -2,16 +2,17 @@ import type { NodeApp } from 'astro/app/node'; import type { IncomingMessage, ServerResponse } from 'http'; import type { Readable } from 'stream'; import { responseIterator } from './response-iterator'; +import type { Options } from './types'; -export default function (app: NodeApp) { +export default function (app: NodeApp, mode: Options['mode']) { return async function ( req: IncomingMessage, res: ServerResponse, next?: (err?: unknown) => void ) { try { - const route = app.match(req); - + const route = + mode === 'standalone' ? app.match(req, { matchNotFound: true }) : app.match(req); if (route) { try { const response = await app.render(req); diff --git a/packages/integrations/node/src/server.ts b/packages/integrations/node/src/server.ts index 9cff04cf5..e0ccf6599 100644 --- a/packages/integrations/node/src/server.ts +++ b/packages/integrations/node/src/server.ts @@ -9,10 +9,10 @@ polyfill(globalThis, { exclude: 'window document', }); -export function createExports(manifest: SSRManifest) { +export function createExports(manifest: SSRManifest, options: Options) { const app = new NodeApp(manifest); return { - handler: middleware(app), + handler: middleware(app, options.mode), }; } diff --git a/packages/integrations/node/src/standalone.ts b/packages/integrations/node/src/standalone.ts index 54a3940b4..d68c3a500 100644 --- a/packages/integrations/node/src/standalone.ts +++ b/packages/integrations/node/src/standalone.ts @@ -37,7 +37,7 @@ export function getResolvedHostForHttpServer(host: string | boolean) { export default function startServer(app: NodeApp, options: Options) { const port = process.env.PORT ? Number(process.env.PORT) : options.port ?? 8080; const { client } = resolvePaths(options); - const handler = middleware(app); + const handler = middleware(app, options.mode); // Allow to provide host value at runtime const host = getResolvedHostForHttpServer( diff --git a/packages/integrations/node/test/api-route.test.js b/packages/integrations/node/test/api-route.test.js index 2cc15c761..39ba10dbf 100644 --- a/packages/integrations/node/test/api-route.test.js +++ b/packages/integrations/node/test/api-route.test.js @@ -1,5 +1,5 @@ import nodejs from '../dist/index.js'; -import { loadFixture, createRequestAndResponse, toPromise } from './test-utils.js'; +import { loadFixture, createRequestAndResponse } from './test-utils.js'; import { expect } from 'chai'; describe('API routes', () => { @@ -17,18 +17,21 @@ describe('API routes', () => { it('Can get the request body', async () => { const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs'); - let { req, res, done } = createRequestAndResponse({ method: 'POST', url: '/recipes', }); handler(req, res); - req.send(JSON.stringify({ id: 2 })); + req.send(JSON.stringify({ id: 2 })); + let [buffer] = await done; + let json = JSON.parse(buffer.toString('utf-8')); + expect(json.length).to.equal(1); + expect(json[0].name).to.equal('Broccoli Soup'); }); diff --git a/packages/integrations/node/test/fixtures/node-middleware/package.json b/packages/integrations/node/test/fixtures/node-middleware/package.json new file mode 100644 index 000000000..7a49010f1 --- /dev/null +++ b/packages/integrations/node/test/fixtures/node-middleware/package.json @@ -0,0 +1,9 @@ +{ + "name": "@test/node-middleware", + "version": "0.0.0", + "private": true, + "dependencies": { + "astro": "workspace:*", + "@astrojs/node": "workspace:*" + } +} diff --git a/packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro b/packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro new file mode 100644 index 000000000..4684c8665 --- /dev/null +++ b/packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro @@ -0,0 +1,13 @@ +--- +--- + + + + + + + + 404 + +

404!!!!!!!!!!

+ diff --git a/packages/integrations/node/test/fixtures/node-middleware/src/pages/index.astro b/packages/integrations/node/test/fixtures/node-middleware/src/pages/index.astro new file mode 100644 index 000000000..28ff7d223 --- /dev/null +++ b/packages/integrations/node/test/fixtures/node-middleware/src/pages/index.astro @@ -0,0 +1,11 @@ +--- +--- + + +node-middleware + + +
1
+ + diff --git a/packages/integrations/node/test/node-middleware.test.js b/packages/integrations/node/test/node-middleware.test.js new file mode 100644 index 000000000..8a2f947d5 --- /dev/null +++ b/packages/integrations/node/test/node-middleware.test.js @@ -0,0 +1,37 @@ +import nodejs from '../dist/index.js'; +import { loadFixture , createRequestAndResponse} from './test-utils.js'; +import { expect } from 'chai'; +import * as cheerio from 'cheerio'; + +describe('test 404 cant load', () => { + let fixture; + before(async () => { + fixture = await loadFixture({ + root: './fixtures/node-middleware/', + output: 'server', + adapter: nodejs({ mode: 'standalone' }), + }); + await fixture.build(); + }); + describe('test 404', async () => { + let devPreview; + + before(async () => { + devPreview = await fixture.preview(); + }); + after(async () => { + await devPreview.stop(); + }); + it('when mode is standalone', async () => { + const res = await fixture.fetch('/error-page'); + + expect(res.status).to.equal(404); + + const html = await res.text(); + const $ = cheerio.load(html); + + const h1 = $('h1'); + expect(h1.text()).to.equal('404!!!!!!!!!!'); + }); + }) +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2757d8fa3..e83d9f7a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3063,6 +3063,7 @@ importers: astro: workspace:* astro-scripts: workspace:* chai: ^4.3.6 + cheerio: ^1.0.0-rc.11 mocha: ^9.2.2 node-mocks-http: ^1.11.0 send: ^0.18.0 @@ -3075,6 +3076,7 @@ importers: astro: link:../../astro astro-scripts: link:../../../scripts chai: 4.3.7 + cheerio: 1.0.0-rc.12 mocha: 9.2.2 node-mocks-http: 1.12.1 undici: 5.14.0 @@ -3087,6 +3089,14 @@ importers: '@astrojs/node': link:../../.. astro: link:../../../../../astro + packages/integrations/node/test/fixtures/node-middleware: + specifiers: + '@astrojs/node': workspace:* + astro: workspace:* + dependencies: + '@astrojs/node': link:../../.. + astro: link:../../../../../astro + packages/integrations/partytown: specifiers: '@builder.io/partytown': ^0.7.1