From 84d8fcf5df348bf988fdc6da09de141f88568534 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Thu, 20 Feb 2025 14:16:05 +0000 Subject: [PATCH 1/5] feat: add new `allowedHosts` option --- .changeset/grumpy-sloths-fail.md | 28 +++++++++++++++++++ packages/astro/src/cli/dev/index.ts | 1 + packages/astro/src/cli/flags.ts | 6 ++++ packages/astro/src/cli/preview/index.ts | 1 + packages/astro/src/core/config/schema.ts | 9 ++++++ packages/astro/src/core/dev/container.ts | 4 +-- .../src/core/preview/static-preview-server.ts | 1 + packages/astro/src/types/public/config.ts | 20 +++++++++++++ 8 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 .changeset/grumpy-sloths-fail.md diff --git a/.changeset/grumpy-sloths-fail.md b/.changeset/grumpy-sloths-fail.md new file mode 100644 index 000000000000..96f9e8f7624f --- /dev/null +++ b/.changeset/grumpy-sloths-fail.md @@ -0,0 +1,28 @@ +--- +'astro': minor +--- + +Adds a new option in the config called `server.allowedHosts` and CLI option called `--allowed-hosts`. + +This new options allows to specify the hostnames that the dev server and preview server are allowed to respond to + +```shell +astro dev --allowed-hosts=foo.bar.example.com,bar.example.com +``` + +```shell +astro preview --allowed-hosts=foo.bar.example.com,bar.example.com +``` + +```js +// astro.config.mjs +import {defineConfig} from "astro/config"; + +export default defineConfig({ + server: { + allowedHosts: ['foo.bar.example.com', 'bar.example.com'] + } +}) +``` + +More information are available in the [vite documentation](https://vite.dev/config/server-options.html#server-allowedhosts). diff --git a/packages/astro/src/cli/dev/index.ts b/packages/astro/src/cli/dev/index.ts index 4bf888c430f6..d995da154a95 100644 --- a/packages/astro/src/cli/dev/index.ts +++ b/packages/astro/src/cli/dev/index.ts @@ -20,6 +20,7 @@ export async function dev({ flags }: DevOptions) { ['--host ', `Expose on a network IP address at `], ['--open', 'Automatically open the app in the browser on server start'], ['--force', 'Clear the content layer cache, forcing a full rebuild.'], + ['--allowed-hosts', 'Specify a comma-separated list of allowed hosts.'], ['--help (-h)', 'See all available flags.'], ], }, diff --git a/packages/astro/src/cli/flags.ts b/packages/astro/src/cli/flags.ts index 7466fdda7aea..c283ec85e0c1 100644 --- a/packages/astro/src/cli/flags.ts +++ b/packages/astro/src/cli/flags.ts @@ -25,6 +25,12 @@ export function flagsToAstroInlineConfig(flags: Flags): AstroInlineConfig { typeof flags.host === 'string' || typeof flags.host === 'boolean' ? flags.host : undefined, open: typeof flags.open === 'string' || typeof flags.open === 'boolean' ? flags.open : undefined, + allowedHosts: + typeof flags.allowedHosts === 'string' + ? flags.allowedHosts.split(',') + : typeof flags.allowedHosts === 'boolean' && flags.allowedHosts === true + ? flags.allowedHosts + : [], }, }; } diff --git a/packages/astro/src/cli/preview/index.ts b/packages/astro/src/cli/preview/index.ts index 468332ce3b97..2940fbf84313 100644 --- a/packages/astro/src/cli/preview/index.ts +++ b/packages/astro/src/cli/preview/index.ts @@ -18,6 +18,7 @@ export async function preview({ flags }: PreviewOptions) { ['--host', `Listen on all addresses, including LAN and public addresses.`], ['--host ', `Expose on a network IP address at `], ['--open', 'Automatically open the app in the browser on server start'], + ['--allowed-hosts', 'Specify a comma-separated list of allowed hosts.'], ['--help (-h)', 'See all available flags.'], ], }, diff --git a/packages/astro/src/core/config/schema.ts b/packages/astro/src/core/config/schema.ts index 83546aeb9a9e..82609e3b498a 100644 --- a/packages/astro/src/core/config/schema.ts +++ b/packages/astro/src/core/config/schema.ts @@ -77,6 +77,7 @@ export const ASTRO_CONFIG_DEFAULTS = { host: false, port: 4321, open: false, + allowedHosts: [], }, integrations: [], markdown: markdownConfigDefaults, @@ -214,6 +215,10 @@ export const AstroConfigSchema = z.object({ .default(ASTRO_CONFIG_DEFAULTS.server.host), port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port), headers: z.custom().optional(), + allowedHosts: z + .union([z.array(z.string()), z.literal(true)]) + .optional() + .default(ASTRO_CONFIG_DEFAULTS.server.allowedHosts), }) .default({}), ), @@ -718,6 +723,10 @@ export function createRelativeSchema(cmd: string, fileProtocolRoot: string) { port: z.number().optional().default(ASTRO_CONFIG_DEFAULTS.server.port), headers: z.custom().optional(), streaming: z.boolean().optional().default(true), + allowedHosts: z + .union([z.array(z.string()), z.literal(true)]) + .optional() + .default(ASTRO_CONFIG_DEFAULTS.server.allowedHosts), }) .optional() .default({}), diff --git a/packages/astro/src/core/dev/container.ts b/packages/astro/src/core/dev/container.ts index d1570f4920cb..c984fae7d254 100644 --- a/packages/astro/src/core/dev/container.ts +++ b/packages/astro/src/core/dev/container.ts @@ -56,7 +56,7 @@ export async function createContainer({ const { base, - server: { host, headers, open: serverOpen }, + server: { host, headers, open: serverOpen, allowedHosts }, } = settings.config; // serverOpen = true, isRestart = false @@ -92,7 +92,7 @@ export async function createContainer({ const mode = inlineConfig?.mode ?? 'development'; const viteConfig = await createVite( { - server: { host, headers, open }, + server: { host, headers, open, allowedHosts }, optimizeDeps: { include: rendererClientEntries, }, diff --git a/packages/astro/src/core/preview/static-preview-server.ts b/packages/astro/src/core/preview/static-preview-server.ts index 855506ef91ce..13798ef99e2c 100644 --- a/packages/astro/src/core/preview/static-preview-server.ts +++ b/packages/astro/src/core/preview/static-preview-server.ts @@ -36,6 +36,7 @@ export default async function createStaticPreviewServer( port: settings.config.server.port, headers: settings.config.server.headers, open: settings.config.server.open, + allowedHosts: settings.config.server.allowedHosts }, plugins: [vitePluginAstroPreview(settings)], }); diff --git a/packages/astro/src/types/public/config.ts b/packages/astro/src/types/public/config.ts index 84dc3fd83484..540ff015c48c 100644 --- a/packages/astro/src/types/public/config.ts +++ b/packages/astro/src/types/public/config.ts @@ -95,6 +95,26 @@ export type ServerConfig = { * ``` */ open?: string | boolean; + + /** + * @name server.allowedHosts + * @type {string[] | true} + * @default `false` + * @version 5.4.0 + * @description + * + * A list of hostnames that Astro is allowed to respond to. When the value is set to `true`, any + * hostname is allowed. + * + * ```js + * { + * server: { + * allowedHosts: ['staging.example.com', 'qa.example.com'] + * } + * } + * ``` + */ + allowedHosts?: string[] | boolean; }; export type SessionDriverName = BuiltinDriverName | 'custom' | 'test'; From cd646783bda7dc5581bc0e8248278c54d266b28f Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Fri, 21 Feb 2025 14:37:11 +0000 Subject: [PATCH 2/5] Apply suggestions from code review Co-authored-by: Armand Philippot --- .changeset/grumpy-sloths-fail.md | 4 ++-- packages/astro/src/cli/dev/index.ts | 2 +- packages/astro/src/cli/preview/index.ts | 2 +- packages/astro/src/types/public/config.ts | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.changeset/grumpy-sloths-fail.md b/.changeset/grumpy-sloths-fail.md index 96f9e8f7624f..157724cd2243 100644 --- a/.changeset/grumpy-sloths-fail.md +++ b/.changeset/grumpy-sloths-fail.md @@ -4,7 +4,7 @@ Adds a new option in the config called `server.allowedHosts` and CLI option called `--allowed-hosts`. -This new options allows to specify the hostnames that the dev server and preview server are allowed to respond to +This new option allows to specify the hostnames that the dev server and preview server are allowed to respond to. ```shell astro dev --allowed-hosts=foo.bar.example.com,bar.example.com @@ -25,4 +25,4 @@ export default defineConfig({ }) ``` -More information are available in the [vite documentation](https://vite.dev/config/server-options.html#server-allowedhosts). +More information are available in the [Vite documentation](https://vite.dev/config/server-options.html#server-allowedhosts). diff --git a/packages/astro/src/cli/dev/index.ts b/packages/astro/src/cli/dev/index.ts index d995da154a95..d10d000592cf 100644 --- a/packages/astro/src/cli/dev/index.ts +++ b/packages/astro/src/cli/dev/index.ts @@ -20,7 +20,7 @@ export async function dev({ flags }: DevOptions) { ['--host ', `Expose on a network IP address at `], ['--open', 'Automatically open the app in the browser on server start'], ['--force', 'Clear the content layer cache, forcing a full rebuild.'], - ['--allowed-hosts', 'Specify a comma-separated list of allowed hosts.'], + ['--allowed-hosts', 'Specify a comma-separated list of allowed hosts or allow any hostname.'], ['--help (-h)', 'See all available flags.'], ], }, diff --git a/packages/astro/src/cli/preview/index.ts b/packages/astro/src/cli/preview/index.ts index 2940fbf84313..9e0b88e111b8 100644 --- a/packages/astro/src/cli/preview/index.ts +++ b/packages/astro/src/cli/preview/index.ts @@ -18,7 +18,7 @@ export async function preview({ flags }: PreviewOptions) { ['--host', `Listen on all addresses, including LAN and public addresses.`], ['--host ', `Expose on a network IP address at `], ['--open', 'Automatically open the app in the browser on server start'], - ['--allowed-hosts', 'Specify a comma-separated list of allowed hosts.'], + ['--allowed-hosts', 'Specify a comma-separated list of allowed hosts or allow any hostname.'], ['--help (-h)', 'See all available flags.'], ], }, diff --git a/packages/astro/src/types/public/config.ts b/packages/astro/src/types/public/config.ts index 540ff015c48c..78b6c834bf6e 100644 --- a/packages/astro/src/types/public/config.ts +++ b/packages/astro/src/types/public/config.ts @@ -99,7 +99,7 @@ export type ServerConfig = { /** * @name server.allowedHosts * @type {string[] | true} - * @default `false` + * @default `[]` * @version 5.4.0 * @description * @@ -114,7 +114,7 @@ export type ServerConfig = { * } * ``` */ - allowedHosts?: string[] | boolean; + allowedHosts?: string[] | true; }; export type SessionDriverName = BuiltinDriverName | 'custom' | 'test'; From f981b656c3f3cc9347a14162abf9d6fe230be1bb Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 25 Feb 2025 15:37:11 +0000 Subject: [PATCH 3/5] Apply suggestions from code review Co-authored-by: Sarah Rainsberger <5098874+sarah11918@users.noreply.github.com> --- .changeset/grumpy-sloths-fail.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/grumpy-sloths-fail.md b/.changeset/grumpy-sloths-fail.md index 157724cd2243..55100c56b370 100644 --- a/.changeset/grumpy-sloths-fail.md +++ b/.changeset/grumpy-sloths-fail.md @@ -2,9 +2,9 @@ 'astro': minor --- -Adds a new option in the config called `server.allowedHosts` and CLI option called `--allowed-hosts`. +Adds a new configuration option `server.allowedHosts` and CLI option `--allowed-hosts`. -This new option allows to specify the hostnames that the dev server and preview server are allowed to respond to. +Now you can specify the hostnames that the dev and preview servers are allowed to respond to. This is useful for... ```shell astro dev --allowed-hosts=foo.bar.example.com,bar.example.com @@ -25,4 +25,4 @@ export default defineConfig({ }) ``` -More information are available in the [Vite documentation](https://vite.dev/config/server-options.html#server-allowedhosts). +This feature is the same as [Vite's `server.allowHosts` configuration](https://vite.dev/config/server-options.html#server-allowedhosts). From 4e03d688c2da22911a8e30b02abb68ff6634e762 Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Tue, 25 Feb 2025 15:39:27 +0000 Subject: [PATCH 4/5] chore: move config --- packages/astro/src/types/public/config.ts | 41 ++++++++++++----------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/packages/astro/src/types/public/config.ts b/packages/astro/src/types/public/config.ts index 78b6c834bf6e..edcb70b164c3 100644 --- a/packages/astro/src/types/public/config.ts +++ b/packages/astro/src/types/public/config.ts @@ -68,6 +68,27 @@ export type ServerConfig = { */ port?: number; + + /** + * @name server.allowedHosts + * @type {string[] | true} + * @default `[]` + * @version 5.4.0 + * @description + * + * A list of hostnames that Astro is allowed to respond to. When the value is set to `true`, any + * hostname is allowed. + * + * ```js + * { + * server: { + * allowedHosts: ['staging.example.com', 'qa.example.com'] + * } + * } + * ``` + */ + allowedHosts?: string[] | true; + /** * @name server.headers * @typeraw {OutgoingHttpHeaders} @@ -95,26 +116,6 @@ export type ServerConfig = { * ``` */ open?: string | boolean; - - /** - * @name server.allowedHosts - * @type {string[] | true} - * @default `[]` - * @version 5.4.0 - * @description - * - * A list of hostnames that Astro is allowed to respond to. When the value is set to `true`, any - * hostname is allowed. - * - * ```js - * { - * server: { - * allowedHosts: ['staging.example.com', 'qa.example.com'] - * } - * } - * ``` - */ - allowedHosts?: string[] | true; }; export type SessionDriverName = BuiltinDriverName | 'custom' | 'test'; From d11d3e49d89e29d651a1889d62a929bd4f53771d Mon Sep 17 00:00:00 2001 From: Emanuele Stoppa Date: Wed, 26 Feb 2025 10:31:34 +0000 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: Sarah Rainsberger <5098874+sarah11918@users.noreply.github.com> --- .changeset/grumpy-sloths-fail.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.changeset/grumpy-sloths-fail.md b/.changeset/grumpy-sloths-fail.md index 55100c56b370..1a5e9b272b76 100644 --- a/.changeset/grumpy-sloths-fail.md +++ b/.changeset/grumpy-sloths-fail.md @@ -4,7 +4,9 @@ Adds a new configuration option `server.allowedHosts` and CLI option `--allowed-hosts`. -Now you can specify the hostnames that the dev and preview servers are allowed to respond to. This is useful for... +Now you can specify the hostnames that the dev and preview servers are allowed to respond to. This is useful for allowing additional subdomains, or running the dev server in a web container. + +`allowedHosts` checks the Host header on HTTP requests from browsers and if it doesn't match, it will reject the request to prevent CSRF and XSS attacks. ```shell astro dev --allowed-hosts=foo.bar.example.com,bar.example.com