mirror of
https://github.com/withastro/astro.git
synced 2025-03-24 23:21:57 -05:00
fix(app/node): include x-forwarded-port
header in url (#10666)
* fix(app/node): include `x-forwarded-port` header in url * add changeset * add test
This commit is contained in:
parent
317d18ef8c
commit
55ddb2ba48
7 changed files with 47 additions and 22 deletions
5
.changeset/brave-pumpkins-train.md
Normal file
5
.changeset/brave-pumpkins-train.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes an issue where forwarded requests did not include hostname on node-based adapters. This also makes error pages more reliable.
|
|
@ -63,8 +63,9 @@ export class NodeApp extends App {
|
||||||
const protocol =
|
const protocol =
|
||||||
req.headers['x-forwarded-proto'] ??
|
req.headers['x-forwarded-proto'] ??
|
||||||
('encrypted' in req.socket && req.socket.encrypted ? 'https' : 'http');
|
('encrypted' in req.socket && req.socket.encrypted ? 'https' : 'http');
|
||||||
const hostname = req.headers.host || req.headers[':authority'];
|
const hostname = req.headers["x-forwarded-host"] ?? req.headers.host ?? req.headers[":authority"];
|
||||||
const url = `${protocol}://${hostname}${req.url}`;
|
const port = req.headers["x-forwarded-port"];
|
||||||
|
const url = `${protocol}://${hostname}${port ? `:${port}` : ''}${req.url}`;
|
||||||
const options: RequestInit = {
|
const options: RequestInit = {
|
||||||
method: req.method || 'GET',
|
method: req.method || 'GET',
|
||||||
headers: makeRequestHeaders(req),
|
headers: makeRequestHeaders(req),
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
---
|
|
||||||
---
|
|
||||||
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<title>url-protocol</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{Astro.url.protocol}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "@test/url-protocol",
|
"name": "@test/url",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
9
packages/integrations/node/test/fixtures/url/src/pages/index.astro
vendored
Normal file
9
packages/integrations/node/test/fixtures/url/src/pages/index.astro
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
---
|
||||||
|
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>URL</title>
|
||||||
|
</head>
|
||||||
|
<body>{Astro.url.href}</body>
|
||||||
|
</html>
|
|
@ -3,14 +3,15 @@ import { before, describe, it } from 'node:test';
|
||||||
import { TLSSocket } from 'node:tls';
|
import { TLSSocket } from 'node:tls';
|
||||||
import nodejs from '../dist/index.js';
|
import nodejs from '../dist/index.js';
|
||||||
import { createRequestAndResponse, loadFixture } from './test-utils.js';
|
import { createRequestAndResponse, loadFixture } from './test-utils.js';
|
||||||
|
import * as cheerio from 'cheerio';
|
||||||
|
|
||||||
describe('URL protocol', () => {
|
describe('URL', () => {
|
||||||
/** @type {import('./test-utils').Fixture} */
|
/** @type {import('./test-utils.js').Fixture} */
|
||||||
let fixture;
|
let fixture;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/url-protocol/',
|
root: './fixtures/url/',
|
||||||
output: 'server',
|
output: 'server',
|
||||||
adapter: nodejs({ mode: 'standalone' }),
|
adapter: nodejs({ mode: 'standalone' }),
|
||||||
});
|
});
|
||||||
|
@ -18,7 +19,7 @@ describe('URL protocol', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return http when non-secure', async () => {
|
it('return http when non-secure', async () => {
|
||||||
const { handler } = await import('./fixtures/url-protocol/dist/server/entry.mjs');
|
const { handler } = await import('./fixtures/url/dist/server/entry.mjs');
|
||||||
let { req, res, text } = createRequestAndResponse({
|
let { req, res, text } = createRequestAndResponse({
|
||||||
url: '/',
|
url: '/',
|
||||||
});
|
});
|
||||||
|
@ -31,7 +32,7 @@ describe('URL protocol', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return https when secure', async () => {
|
it('return https when secure', async () => {
|
||||||
const { handler } = await import('./fixtures/url-protocol/dist/server/entry.mjs');
|
const { handler } = await import('./fixtures/url/dist/server/entry.mjs');
|
||||||
let { req, res, text } = createRequestAndResponse({
|
let { req, res, text } = createRequestAndResponse({
|
||||||
socket: new TLSSocket(),
|
socket: new TLSSocket(),
|
||||||
url: '/',
|
url: '/',
|
||||||
|
@ -45,7 +46,7 @@ describe('URL protocol', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return http when the X-Forwarded-Proto header is set to http', async () => {
|
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');
|
const { handler } = await import('./fixtures/url/dist/server/entry.mjs');
|
||||||
let { req, res, text } = createRequestAndResponse({
|
let { req, res, text } = createRequestAndResponse({
|
||||||
headers: { 'X-Forwarded-Proto': 'http' },
|
headers: { 'X-Forwarded-Proto': 'http' },
|
||||||
url: '/',
|
url: '/',
|
||||||
|
@ -59,7 +60,7 @@ describe('URL protocol', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('return https when the X-Forwarded-Proto header is set to https', async () => {
|
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');
|
const { handler } = await import('./fixtures/url/dist/server/entry.mjs');
|
||||||
let { req, res, text } = createRequestAndResponse({
|
let { req, res, text } = createRequestAndResponse({
|
||||||
headers: { 'X-Forwarded-Proto': 'https' },
|
headers: { 'X-Forwarded-Proto': 'https' },
|
||||||
url: '/',
|
url: '/',
|
||||||
|
@ -71,4 +72,24 @@ describe('URL protocol', () => {
|
||||||
const html = await text();
|
const html = await text();
|
||||||
assert.equal(html.includes('https:'), true);
|
assert.equal(html.includes('https:'), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('includes forwarded host and port in the url', async () => {
|
||||||
|
const { handler } = await import('./fixtures/url/dist/server/entry.mjs');
|
||||||
|
let { req, res, text } = createRequestAndResponse({
|
||||||
|
headers: {
|
||||||
|
'X-Forwarded-Proto': 'https',
|
||||||
|
'X-Forwarded-Host': 'abc.xyz',
|
||||||
|
'X-Forwarded-Port': '444'
|
||||||
|
},
|
||||||
|
url: '/',
|
||||||
|
});
|
||||||
|
|
||||||
|
handler(req, res);
|
||||||
|
req.send();
|
||||||
|
|
||||||
|
const html = await text();
|
||||||
|
const $ = cheerio.load(html);
|
||||||
|
|
||||||
|
assert.equal($('body').text(), "https://abc.xyz:444/");
|
||||||
|
});
|
||||||
});
|
});
|
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
|
@ -4703,7 +4703,7 @@ importers:
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../../../../astro
|
version: link:../../../../../astro
|
||||||
|
|
||||||
packages/integrations/node/test/fixtures/url-protocol:
|
packages/integrations/node/test/fixtures/url:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/node':
|
'@astrojs/node':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
|
|
Loading…
Add table
Reference in a new issue