aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/integrations/node/package.json4
-rw-r--r--packages/integrations/node/src/http-server.ts5
-rw-r--r--packages/integrations/node/src/index.ts2
-rw-r--r--packages/integrations/node/src/server.ts1
-rw-r--r--packages/integrations/node/src/standalone.ts6
-rw-r--r--packages/integrations/node/test/fixtures/prerender/package.json9
-rw-r--r--packages/integrations/node/test/fixtures/prerender/src/pages/one.astro10
-rw-r--r--packages/integrations/node/test/fixtures/prerender/src/pages/two.astro11
-rw-r--r--packages/integrations/node/test/prerender.test.js60
9 files changed, 104 insertions, 4 deletions
diff --git a/packages/integrations/node/package.json b/packages/integrations/node/package.json
index 39060dcf3..a9a6a9c04 100644
--- a/packages/integrations/node/package.json
+++ b/packages/integrations/node/package.json
@@ -31,13 +31,15 @@
},
"dependencies": {
"@astrojs/webapi": "^2.0.0",
- "send": "^0.18.0"
+ "send": "^0.18.0",
+ "server-destroy": "^1.0.1"
},
"peerDependencies": {
"astro": "workspace:^2.0.6"
},
"devDependencies": {
"@types/send": "^0.17.1",
+ "@types/server-destroy": "^1.0.1",
"astro": "workspace:*",
"astro-scripts": "workspace:*",
"chai": "^4.3.6",
diff --git a/packages/integrations/node/src/http-server.ts b/packages/integrations/node/src/http-server.ts
index 8eea3c170..fee30aaec 100644
--- a/packages/integrations/node/src/http-server.ts
+++ b/packages/integrations/node/src/http-server.ts
@@ -3,6 +3,7 @@ import http from 'http';
import https from 'https';
import send from 'send';
import { fileURLToPath } from 'url';
+import enableDestroy from 'server-destroy';
interface CreateServerOptions {
client: URL;
@@ -19,6 +20,7 @@ export function createServer(
if (req.url) {
let pathname = removeBase(req.url);
pathname = pathname[0] === '/' ? pathname : '/' + pathname;
+ pathname = new URL(pathname, `http://${host}:${port}`).pathname;
const stream = send(req, encodeURI(decodeURI(pathname)), {
root: fileURLToPath(client),
dotfiles: pathname.startsWith('/.well-known/') ? 'allow' : 'deny',
@@ -63,6 +65,7 @@ export function createServer(
httpServer = http.createServer(listener);
}
httpServer.listen(port, host);
+ enableDestroy(httpServer);
// Resolves once the server is closed
const closed = new Promise<void>((resolve, reject) => {
@@ -79,7 +82,7 @@ export function createServer(
server: httpServer,
stop: async () => {
await new Promise((resolve, reject) => {
- httpServer.close((err) => (err ? reject(err) : resolve(undefined)));
+ httpServer.destroy((err) => (err ? reject(err) : resolve(undefined)));
});
},
};
diff --git a/packages/integrations/node/src/index.ts b/packages/integrations/node/src/index.ts
index bbe5e44b4..d882f34fb 100644
--- a/packages/integrations/node/src/index.ts
+++ b/packages/integrations/node/src/index.ts
@@ -6,7 +6,7 @@ export function getAdapter(options: Options): AstroAdapter {
name: '@astrojs/node',
serverEntrypoint: '@astrojs/node/server.js',
previewEntrypoint: '@astrojs/node/preview.js',
- exports: ['handler'],
+ exports: ['handler', 'startServer'],
args: options,
};
}
diff --git a/packages/integrations/node/src/server.ts b/packages/integrations/node/src/server.ts
index e0ccf6599..c4c79f6a8 100644
--- a/packages/integrations/node/src/server.ts
+++ b/packages/integrations/node/src/server.ts
@@ -13,6 +13,7 @@ export function createExports(manifest: SSRManifest, options: Options) {
const app = new NodeApp(manifest);
return {
handler: middleware(app, options.mode),
+ startServer: () => startServer(app, options)
};
}
diff --git a/packages/integrations/node/src/standalone.ts b/packages/integrations/node/src/standalone.ts
index 789269860..d3ab36793 100644
--- a/packages/integrations/node/src/standalone.ts
+++ b/packages/integrations/node/src/standalone.ts
@@ -55,8 +55,12 @@ export default function startServer(app: NodeApp, options: Options) {
);
const protocol = server.server instanceof https.Server ? 'https' : 'http';
+
// eslint-disable-next-line no-console
console.log(`Server listening on ${protocol}://${host}:${port}`);
- return server.closed();
+ return {
+ server,
+ done: server.closed()
+ };
}
diff --git a/packages/integrations/node/test/fixtures/prerender/package.json b/packages/integrations/node/test/fixtures/prerender/package.json
new file mode 100644
index 000000000..350077973
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/nodejs-encoded",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*",
+ "@astrojs/node": "workspace:*"
+ }
+}
diff --git a/packages/integrations/node/test/fixtures/prerender/src/pages/one.astro b/packages/integrations/node/test/fixtures/prerender/src/pages/one.astro
new file mode 100644
index 000000000..f3a26721d
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender/src/pages/one.astro
@@ -0,0 +1,10 @@
+---
+---
+<html>
+ <head>
+ <title>One</title>
+ </head>
+ <body>
+ <h1>One</h1>
+ </body>
+</html>
diff --git a/packages/integrations/node/test/fixtures/prerender/src/pages/two.astro b/packages/integrations/node/test/fixtures/prerender/src/pages/two.astro
new file mode 100644
index 000000000..beb6e8d78
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/prerender/src/pages/two.astro
@@ -0,0 +1,11 @@
+---
+export const prerender = true;
+---
+<html>
+ <head>
+ <title>Two</title>
+ </head>
+ <body>
+ <h1>Two</h1>
+ </body>
+</html>
diff --git a/packages/integrations/node/test/prerender.test.js b/packages/integrations/node/test/prerender.test.js
new file mode 100644
index 000000000..e5c94391f
--- /dev/null
+++ b/packages/integrations/node/test/prerender.test.js
@@ -0,0 +1,60 @@
+import nodejs from '../dist/index.js';
+import { loadFixture, createRequestAndResponse } from './test-utils.js';
+import { expect } from 'chai';
+import * as cheerio from 'cheerio';
+import { fetch } from 'undici';
+
+describe('Prerendering', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+ let server;
+
+ before(async () => {
+ process.env.ASTRO_NODE_AUTOSTART = 'disabled';
+ fixture = await loadFixture({
+ root: './fixtures/prerender/',
+ 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();
+ });
+
+ async function load() {
+ const mod = await import('./fixtures/prerender/dist/server/entry.mjs');
+ return mod;
+ }
+
+ it('Can render SSR route', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/one`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('One');
+ });
+
+ it('Can render prerendered route', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/two`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('Two');
+ });
+
+ it('Can render prerendered route with query params', async () => {
+ const res = await fetch(`http://${server.host}:${server.port}/two?foo=bar`);
+ const html = await res.text();
+ const $ = cheerio.load(html);
+
+ expect(res.status).to.equal(200);
+ expect($('h1').text()).to.equal('Two');
+ });
+});