summaryrefslogtreecommitdiff
path: root/packages/integrations
diff options
context:
space:
mode:
Diffstat (limited to 'packages/integrations')
-rw-r--r--packages/integrations/netlify/src/netlify-edge-functions.ts28
-rw-r--r--packages/integrations/netlify/src/netlify-functions.ts10
-rw-r--r--packages/integrations/node/src/nodeMiddleware.ts11
-rw-r--r--packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro2
-rw-r--r--packages/integrations/node/test/fixtures/prerender-404/package.json9
-rw-r--r--packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro5
-rw-r--r--packages/integrations/node/test/fixtures/prerender-404/src/pages/static.astro12
-rw-r--r--packages/integrations/node/test/node-middleware.test.js40
-rw-r--r--packages/integrations/node/test/prerender-404.test.js189
-rw-r--r--packages/integrations/vercel/src/edge/entrypoint.ts20
-rw-r--r--packages/integrations/vercel/src/serverless/entrypoint.ts7
11 files changed, 270 insertions, 63 deletions
diff --git a/packages/integrations/netlify/src/netlify-edge-functions.ts b/packages/integrations/netlify/src/netlify-edge-functions.ts
index 4a6d3674c..3897a5120 100644
--- a/packages/integrations/netlify/src/netlify-edge-functions.ts
+++ b/packages/integrations/netlify/src/netlify-edge-functions.ts
@@ -15,25 +15,19 @@ export function createExports(manifest: SSRManifest) {
if (manifest.assets.has(url.pathname)) {
return;
}
- if (app.match(request)) {
- const ip =
- request.headers.get('x-nf-client-connection-ip') ||
- context?.ip ||
- (context as any)?.remoteAddr?.hostname;
- Reflect.set(request, clientAddressSymbol, ip);
- const response = await app.render(request);
- if (app.setCookieHeaders) {
- for (const setCookieHeader of app.setCookieHeaders(response)) {
- response.headers.append('Set-Cookie', setCookieHeader);
- }
+ const routeData = app.match(request)
+ const ip =
+ request.headers.get('x-nf-client-connection-ip') ||
+ context?.ip ||
+ (context as any)?.remoteAddr?.hostname;
+ Reflect.set(request, clientAddressSymbol, ip);
+ const response = await app.render(request, routeData);
+ if (app.setCookieHeaders) {
+ for (const setCookieHeader of app.setCookieHeaders(response)) {
+ response.headers.append('Set-Cookie', setCookieHeader);
}
- return response;
}
-
- return new Response(null, {
- status: 404,
- statusText: 'Not found',
- });
+ return response;
};
return { default: handler };
diff --git a/packages/integrations/netlify/src/netlify-functions.ts b/packages/integrations/netlify/src/netlify-functions.ts
index 8d0196d5e..cc6636ec4 100644
--- a/packages/integrations/netlify/src/netlify-functions.ts
+++ b/packages/integrations/netlify/src/netlify-functions.ts
@@ -70,15 +70,7 @@ export const createExports = (manifest: SSRManifest, args: Args) => {
}
const request = new Request(rawUrl, init);
- let routeData = app.match(request, { matchNotFound: true });
-
- if (!routeData) {
- return {
- statusCode: 404,
- body: 'Not found',
- };
- }
-
+ const routeData = app.match(request);
const ip = headers['x-nf-client-connection-ip'];
Reflect.set(request, clientAddressSymbol, ip);
let locals = {};
diff --git a/packages/integrations/node/src/nodeMiddleware.ts b/packages/integrations/node/src/nodeMiddleware.ts
index 4963afc9f..8d31b6806 100644
--- a/packages/integrations/node/src/nodeMiddleware.ts
+++ b/packages/integrations/node/src/nodeMiddleware.ts
@@ -5,7 +5,9 @@ import { createOutgoingHttpHeaders } from './createOutgoingHttpHeaders';
import { responseIterator } from './response-iterator';
import type { Options } from './types';
-export default function (app: NodeApp, mode: Options['mode']) {
+// Disable no-unused-vars to avoid breaking signature change
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+export default function (app: NodeApp, _mode: Options['mode']) {
return async function (
req: IncomingMessage,
res: ServerResponse,
@@ -13,8 +15,7 @@ export default function (app: NodeApp, mode: Options['mode']) {
locals?: object
) {
try {
- const route =
- mode === 'standalone' ? app.match(req, { matchNotFound: true }) : app.match(req);
+ const route = app.match(req);
if (route) {
try {
const response = await app.render(req, route, locals);
@@ -29,8 +30,8 @@ export default function (app: NodeApp, mode: Options['mode']) {
} else if (next) {
return next();
} else {
- res.writeHead(404);
- res.end('Not found');
+ const response = await app.render(req);
+ await writeWebResponse(app, res, response);
}
} catch (err: unknown) {
if (!res.headersSent) {
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
index 4684c8665..79f4944bc 100644
--- a/packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro
+++ b/packages/integrations/node/test/fixtures/node-middleware/src/pages/404.astro
@@ -9,5 +9,5 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404</title>
</head>
-<body><h1>404!!!!!!!!!!</h1></body>
+<body>Page does not exist</body>
</html>
diff --git a/packages/integrations/node/test/fixtures/prerender-404/package.json b/packages/integrations/node/test/fixtures/prerender-404/package.json
new file mode 100644
index 000000000..dfd109c91
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender-404/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/nodejs-prerender-404",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*",
+ "@astrojs/node": "workspace:*"
+ }
+}
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro b/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
new file mode 100644
index 000000000..230402bbc
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender-404/src/pages/404.astro
@@ -0,0 +1,5 @@
+---
+export const prerender = true;
+---
+
+Page does not exist
diff --git a/packages/integrations/node/test/fixtures/prerender-404/src/pages/static.astro b/packages/integrations/node/test/fixtures/prerender-404/src/pages/static.astro
new file mode 100644
index 000000000..af6bad2fb
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender-404/src/pages/static.astro
@@ -0,0 +1,12 @@
+---
+export const prerender = true;
+---
+
+<html>
+<head>
+ <title>Static Page</title>
+</head>
+ <body>
+ <h1>Hello world!</h1>
+ </body>
+</html>
diff --git a/packages/integrations/node/test/node-middleware.test.js b/packages/integrations/node/test/node-middleware.test.js
index a658f93ef..350e48c7a 100644
--- a/packages/integrations/node/test/node-middleware.test.js
+++ b/packages/integrations/node/test/node-middleware.test.js
@@ -3,35 +3,51 @@ import { loadFixture } from './test-utils.js';
import { expect } from 'chai';
import * as cheerio from 'cheerio';
-describe('test 404 cant load', () => {
+/**
+ * @typedef {import('../../../astro/test/test-utils').Fixture} Fixture
+ */
+
+async function load() {
+ const mod = await import(`./fixtures/node-middleware/dist/server/entry.mjs?dropcache=${Date.now()}`);
+ return mod;
+}
+
+describe('behavior from middleware', () => {
+ /** @type {import('./test-utils').Fixture} */
let fixture;
+ let server;
+
before(async () => {
+ process.env.ASTRO_NODE_AUTOSTART = 'disabled';
+ process.env.PRERENDER = false;
fixture = await loadFixture({
root: './fixtures/node-middleware/',
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
+ const { startServer } = await load();
+ let res = startServer();
+ server = res.server;
});
- describe('test 404', async () => {
- let devPreview;
- before(async () => {
- devPreview = await fixture.preview();
- });
- after(async () => {
- await devPreview.stop();
- });
+ after(async () => {
+ await server.stop();
+ await fixture.clean();
+ delete process.env.PRERENDER;
+ })
+
+ describe('404', async () => {
it('when mode is standalone', async () => {
- const res = await fixture.fetch('/error-page');
+ const res = await fetch(`http://${server.host}:${server.port}/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!!!!!!!!!!');
+ const body = $('body');
+ expect(body.text()).to.equal('Page does not exist');
});
});
});
diff --git a/packages/integrations/node/test/prerender-404.test.js b/packages/integrations/node/test/prerender-404.test.js
new file mode 100644
index 000000000..df36fa414
--- /dev/null
+++ b/packages/integrations/node/test/prerender-404.test.js
@@ -0,0 +1,189 @@
+import nodejs from '../dist/index.js';
+import { loadFixture } from './test-utils.js';
+import { expect } from 'chai';
+import * as cheerio from 'cheerio';
+import { fetch } from 'undici';
+
+/**
+ * @typedef {import('../../../astro/test/test-utils').Fixture} Fixture
+ */
+
+async function load() {
+ const mod = await import(`./fixtures/prerender-404/dist/server/entry.mjs?dropcache=${Date.now()}`);
+ return mod;
+}
+describe('Prerender 404', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+ let server;
+
+ describe('With base', async () => {
+ before(async () => {
+ process.env.ASTRO_NODE_AUTOSTART = 'disabled';
+ process.env.PRERENDER = true;
+
+ fixture = await loadFixture({
+ base: '/some-base',
+ root: './fixtures/prerender-404/',
+ output: 'server',
+ adapter: nodejs({ mode: 'standalone' }),
+ });
+ await fixture.build();
+ const { startServer } = await load();
+ let res = startServer();
+ server = res.server;
+ });
+
+ after(async () => {
+ await server.stop();
+ await fixture.clean();
+ delete process.env.PRERENDER;
+ });
+
+ it('Can render SSR route', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/some-base/static`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('Hello world!');
+ });
+
+ it('Can handle prerendered 404', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(404);
+ expect($('body').text()).to.equal('Page does not exist');
+ });
+ });
+
+ describe('Without base', async () => {
+ before(async () => {
+ process.env.ASTRO_NODE_AUTOSTART = 'disabled';
+ process.env.PRERENDER = true;
+
+ fixture = await loadFixture({
+ root: './fixtures/prerender-404/',
+ output: 'server',
+ adapter: nodejs({ mode: 'standalone' }),
+ });
+ await fixture.build();
+ const { startServer } = await await load();
+ let res = startServer();
+ server = res.server;
+ });
+
+ after(async () => {
+ await server.stop();
+ await fixture.clean();
+ delete process.env.PRERENDER;
+ });
+
+ it('Can render SSR route', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/static`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('Hello world!');
+ });
+
+ it('Can handle prerendered 404', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/missing`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(404);
+ expect($('body').text()).to.equal('Page does not exist');
+ });
+ });
+});
+
+describe('Hybrid 404', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+ let server;
+
+ describe('With base', async () => {
+ before(async () => {
+ process.env.ASTRO_NODE_AUTOSTART = 'disabled';
+ process.env.PRERENDER = false;
+ fixture = await loadFixture({
+ base: '/some-base',
+ root: './fixtures/prerender-404/',
+ output: 'hybrid',
+ adapter: nodejs({ mode: 'standalone' }),
+ });
+ await fixture.build();
+ const { startServer } = await await load();
+ let res = startServer();
+ server = res.server;
+ });
+
+ after(async () => {
+ await server.stop();
+ await fixture.clean();
+ delete process.env.PRERENDER;
+ });
+
+ it('Can render SSR route', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/some-base/static`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('Hello world!');
+ });
+
+ it('Can handle prerendered 404', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(404);
+ expect($('body').text()).to.equal('Page does not exist');
+ });
+ });
+
+ describe('Without base', async () => {
+ before(async () => {
+ process.env.ASTRO_NODE_AUTOSTART = 'disabled';
+ process.env.PRERENDER = false;
+ fixture = await loadFixture({
+ root: './fixtures/prerender-404/',
+ output: 'hybrid',
+ adapter: nodejs({ mode: 'standalone' }),
+ });
+ await fixture.build();
+ const { startServer } = await await load();
+ let res = startServer();
+ server = res.server;
+ });
+
+ after(async () => {
+ await server.stop();
+ await fixture.clean();
+ delete process.env.PRERENDER;
+ });
+
+ it('Can render SSR route', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/static`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('Hello world!');
+ });
+
+ it('Can handle prerendered 404', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/missing`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(404);
+ expect($('body').text()).to.equal('Page does not exist');
+ });
+ });
+});
diff --git a/packages/integrations/vercel/src/edge/entrypoint.ts b/packages/integrations/vercel/src/edge/entrypoint.ts
index a9870ef2b..4b88bc793 100644
--- a/packages/integrations/vercel/src/edge/entrypoint.ts
+++ b/packages/integrations/vercel/src/edge/entrypoint.ts
@@ -13,21 +13,15 @@ export function createExports(manifest: SSRManifest) {
const app = new App(manifest);
const handler = async (request: Request): Promise<Response> => {
- if (app.match(request)) {
- Reflect.set(request, clientAddressSymbol, request.headers.get('x-forwarded-for'));
- const response = await app.render(request);
- if (app.setCookieHeaders) {
- for (const setCookieHeader of app.setCookieHeaders(response)) {
- response.headers.append('Set-Cookie', setCookieHeader);
- }
+ const routeData = app.match(request);
+ Reflect.set(request, clientAddressSymbol, request.headers.get('x-forwarded-for'));
+ const response = await app.render(request, routeData);
+ if (app.setCookieHeaders) {
+ for (const setCookieHeader of app.setCookieHeaders(response)) {
+ response.headers.append('Set-Cookie', setCookieHeader);
}
- return response;
}
-
- return new Response(null, {
- status: 404,
- statusText: 'Not found',
- });
+ return response;
};
return { default: handler };
diff --git a/packages/integrations/vercel/src/serverless/entrypoint.ts b/packages/integrations/vercel/src/serverless/entrypoint.ts
index 48c9b71d9..9e3cb1da0 100644
--- a/packages/integrations/vercel/src/serverless/entrypoint.ts
+++ b/packages/integrations/vercel/src/serverless/entrypoint.ts
@@ -23,12 +23,7 @@ export const createExports = (manifest: SSRManifest) => {
return res.end(err.reason || 'Invalid request body');
}
- let routeData = app.match(request, { matchNotFound: true });
- if (!routeData) {
- res.statusCode = 404;
- return res.end('Not found');
- }
-
+ let routeData = app.match(request);
let locals = {};
if (request.headers.has(ASTRO_LOCALS_HEADER)) {
let localsAsString = request.headers.get(ASTRO_LOCALS_HEADER);