summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/odd-rats-drop.md6
-rw-r--r--packages/astro/src/core/app/node.ts7
-rw-r--r--packages/integrations/node/src/standalone.ts4
-rw-r--r--packages/integrations/node/test/fixtures/url-protocol/package.json9
-rw-r--r--packages/integrations/node/test/fixtures/url-protocol/src/pages/index.astro11
-rw-r--r--packages/integrations/node/test/url-protocol.test.js73
-rw-r--r--pnpm-lock.yaml8
7 files changed, 116 insertions, 2 deletions
diff --git a/.changeset/odd-rats-drop.md b/.changeset/odd-rats-drop.md
new file mode 100644
index 000000000..1b2f930f0
--- /dev/null
+++ b/.changeset/odd-rats-drop.md
@@ -0,0 +1,6 @@
+---
+'astro': patch
+'@astrojs/node': patch
+---
+
+Fix `Astro.url.protocol` when using the @astrojs/node SSR adapter with HTTPS
diff --git a/packages/astro/src/core/app/node.ts b/packages/astro/src/core/app/node.ts
index 801ede4c9..2ab662d66 100644
--- a/packages/astro/src/core/app/node.ts
+++ b/packages/astro/src/core/app/node.ts
@@ -3,13 +3,18 @@ import type { SerializedSSRManifest, SSRManifest } from './types';
import * as fs from 'fs';
import { IncomingMessage } from 'http';
+import { TLSSocket } from 'tls';
import { deserializeManifest } from './common.js';
import { App, MatchOptions } from './index.js';
const clientAddressSymbol = Symbol.for('astro.clientAddress');
function createRequestFromNodeRequest(req: IncomingMessage, body?: Uint8Array): Request {
- let url = `http://${req.headers.host}${req.url}`;
+ const protocol =
+ req.socket instanceof TLSSocket || req.headers['x-forwarded-proto'] === 'https'
+ ? 'https'
+ : 'http';
+ let url = `${protocol}://${req.headers.host}${req.url}`;
let rawHeaders = req.headers as Record<string, any>;
const entries = Object.entries(rawHeaders);
const method = req.method || 'GET';
diff --git a/packages/integrations/node/src/standalone.ts b/packages/integrations/node/src/standalone.ts
index d68c3a500..789269860 100644
--- a/packages/integrations/node/src/standalone.ts
+++ b/packages/integrations/node/src/standalone.ts
@@ -1,4 +1,5 @@
import type { NodeApp } from 'astro/app/node';
+import https from 'https';
import path from 'path';
import { fileURLToPath } from 'url';
import { createServer } from './http-server.js';
@@ -53,8 +54,9 @@ export default function startServer(app: NodeApp, options: Options) {
handler
);
+ const protocol = server.server instanceof https.Server ? 'https' : 'http';
// eslint-disable-next-line no-console
- console.log(`Server listening on http://${host}:${port}`);
+ console.log(`Server listening on ${protocol}://${host}:${port}`);
return server.closed();
}
diff --git a/packages/integrations/node/test/fixtures/url-protocol/package.json b/packages/integrations/node/test/fixtures/url-protocol/package.json
new file mode 100644
index 000000000..4b0775716
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/url-protocol/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "@test/url-protocol",
+ "version": "0.0.0",
+ "private": true,
+ "dependencies": {
+ "astro": "workspace:*",
+ "@astrojs/node": "workspace:*"
+ }
+}
diff --git a/packages/integrations/node/test/fixtures/url-protocol/src/pages/index.astro b/packages/integrations/node/test/fixtures/url-protocol/src/pages/index.astro
new file mode 100644
index 000000000..61fb9867b
--- /dev/null
+++ b/packages/integrations/node/test/fixtures/url-protocol/src/pages/index.astro
@@ -0,0 +1,11 @@
+---
+---
+
+<html lang="en">
+ <head>
+ <title>url-protocol</title>
+ </head>
+ <body>
+ {Astro.url.protocol}
+ </body>
+</html>
diff --git a/packages/integrations/node/test/url-protocol.test.js b/packages/integrations/node/test/url-protocol.test.js
new file mode 100644
index 000000000..0da4bdeb0
--- /dev/null
+++ b/packages/integrations/node/test/url-protocol.test.js
@@ -0,0 +1,73 @@
+import { TLSSocket } from 'tls';
+import nodejs from '../dist/index.js';
+import { loadFixture, createRequestAndResponse } from './test-utils.js';
+import { expect } from 'chai';
+
+describe('URL protocol', () => {
+ /** @type {import('./test-utils').Fixture} */
+ let fixture;
+
+ before(async () => {
+ fixture = await loadFixture({
+ root: './fixtures/url-protocol/',
+ output: 'server',
+ adapter: nodejs({ mode: 'standalone' }),
+ });
+ await fixture.build();
+ });
+
+ it('return http when non-secure', async () => {
+ const { handler } = await import('./fixtures/url-protocol/dist/server/entry.mjs');
+ let { req, res, text } = createRequestAndResponse({
+ url: '/',
+ });
+
+ handler(req, res);
+ req.send();
+
+ const html = await text();
+ expect(html).to.include('http:');
+ });
+
+ it('return https when secure', async () => {
+ const { handler } = await import('./fixtures/url-protocol/dist/server/entry.mjs');
+ let { req, res, text } = createRequestAndResponse({
+ socket: new TLSSocket(),
+ url: '/',
+ });
+
+ handler(req, res);
+ req.send();
+
+ const html = await text();
+ expect(html).to.include('https:');
+ });
+
+ it('return http when the X-Forwarded-Proto header is set to http', async () => {
+ const { handler } = await import('./fixtures/url-protocol/dist/server/entry.mjs');
+ let { req, res, text } = createRequestAndResponse({
+ headers: { 'X-Forwarded-Proto': 'http' },
+ url: '/',
+ });
+
+ handler(req, res);
+ req.send();
+
+ const html = await text();
+ expect(html).to.include('http:');
+ });
+
+ it('return https when the X-Forwarded-Proto header is set to https', async () => {
+ const { handler } = await import('./fixtures/url-protocol/dist/server/entry.mjs');
+ let { req, res, text } = createRequestAndResponse({
+ headers: { 'X-Forwarded-Proto': 'https' },
+ url: '/',
+ });
+
+ handler(req, res);
+ req.send();
+
+ const html = await text();
+ expect(html).to.include('https:');
+ });
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5dc3bf7eb..454931ff2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3109,6 +3109,14 @@ importers:
'@astrojs/node': link:../../..
astro: link:../../../../../astro
+ packages/integrations/node/test/fixtures/url-protocol:
+ specifiers:
+ '@astrojs/node': workspace:*
+ astro: workspace:*
+ dependencies:
+ '@astrojs/node': link:../../..
+ astro: link:../../../../../astro
+
packages/integrations/node/test/fixtures/well-known-locations:
specifiers:
'@astrojs/node': workspace:*