From bcd0f8f8c4c27d19296ec08d7bf7d8f5047d583e Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Wed, 9 Nov 2022 08:30:02 -0500 Subject: [PATCH] 404 when not using subpath for items in public in dev (#5328) * 404 when not using subpath for items in public * Adding a changeset --- .changeset/plenty-eyes-develop.md | 7 +++ .../src/vite-plugin-astro-server/base.ts | 18 ++++++-- .../astro/test/fixtures/alias/public/test.txt | 1 + packages/astro/test/units/dev/dev.test.js | 46 +++++++++++++++++++ 4 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 .changeset/plenty-eyes-develop.md create mode 100644 packages/astro/test/fixtures/alias/public/test.txt diff --git a/.changeset/plenty-eyes-develop.md b/.changeset/plenty-eyes-develop.md new file mode 100644 index 0000000000..74073721bf --- /dev/null +++ b/.changeset/plenty-eyes-develop.md @@ -0,0 +1,7 @@ +--- +'astro': patch +--- + +404 when not using subpath for items in public in dev + +Previously if using a base like `base: '/subpath/` you could load things from the root, which would break in prod. Now you must include the subpath. diff --git a/packages/astro/src/vite-plugin-astro-server/base.ts b/packages/astro/src/vite-plugin-astro-server/base.ts index 2618749dba..dcab634b77 100644 --- a/packages/astro/src/vite-plugin-astro-server/base.ts +++ b/packages/astro/src/vite-plugin-astro-server/base.ts @@ -5,6 +5,7 @@ import { LogOptions } from '../core/logger/core.js'; import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js'; import { log404 } from './common.js'; import { writeHtmlResponse } from './response.js'; +import * as fs from 'fs'; export function baseMiddleware( settings: AstroSettings, @@ -12,12 +13,13 @@ export function baseMiddleware( ): vite.Connect.NextHandleFunction { const { config } = settings; const site = config.site ? new URL(config.base, config.site) : undefined; - const devRoot = site ? site.pathname : '/'; + const devRoot = site ? site.pathname : new URL(config.base, 'http://localhost').pathname; return function devBaseMiddleware(req, res, next) { const url = req.url!; - const pathname = decodeURI(new URL(url, 'http://vitejs.dev').pathname); + const pathname = decodeURI(new URL(url, 'http://localhost').pathname); + if (pathname.startsWith(devRoot)) { req.url = url.replace(devRoot, '/'); @@ -41,6 +43,16 @@ export function baseMiddleware( return writeHtmlResponse(res, 404, html); } - next(); + // Check to see if it's in public and if so 404 + const publicPath = new URL('.' + req.url, config.publicDir); + fs.stat(publicPath, (_err, stats) => { + if(stats) { + log404(logging, pathname); + const html = subpathNotUsedTemplate(devRoot, pathname); + return writeHtmlResponse(res, 404, html); + } else { + next(); + } + }); }; } diff --git a/packages/astro/test/fixtures/alias/public/test.txt b/packages/astro/test/fixtures/alias/public/test.txt new file mode 100644 index 0000000000..90bfcb5106 --- /dev/null +++ b/packages/astro/test/fixtures/alias/public/test.txt @@ -0,0 +1 @@ +this is a test diff --git a/packages/astro/test/units/dev/dev.test.js b/packages/astro/test/units/dev/dev.test.js index 88fbaac456..062fcba238 100644 --- a/packages/astro/test/units/dev/dev.test.js +++ b/packages/astro/test/units/dev/dev.test.js @@ -157,4 +157,50 @@ describe('dev container', () => { } ); }); + + it('items in public/ are not available from root when using a base', async () => { + await runInContainer({ + root, + userConfig: { + base: '/sub/' + } + }, async (container) => { + // First try the subpath + let r = createRequestAndResponse({ + method: 'GET', + url: '/sub/test.txt', + }); + + container.handle(r.req, r.res); + await r.done; + + expect(r.res.statusCode).to.equal(200); + + // Next try the root path + r = createRequestAndResponse({ + method: 'GET', + url: '/test.txt', + }); + + container.handle(r.req, r.res); + await r.done; + + expect(r.res.statusCode).to.equal(404); + }); + }); + + it('items in public/ are available from root when not using a base', async () => { + await runInContainer({ root }, async (container) => { + // Try the root path + let r = createRequestAndResponse({ + method: 'GET', + url: '/test.txt', + }); + + container.handle(r.req, r.res); + await r.done; + + expect(r.res.statusCode).to.equal(200); + }); + }); });