0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-23 21:53:55 -05:00

404 when not using subpath for items in public in dev (#5328)

* 404 when not using subpath for items in public

* Adding a changeset
This commit is contained in:
Matthew Phillips 2022-11-09 08:30:02 -05:00 committed by GitHub
parent 48bde7018e
commit bcd0f8f8c4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 3 deletions

View file

@ -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.

View file

@ -5,6 +5,7 @@ import { LogOptions } from '../core/logger/core.js';
import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js'; import notFoundTemplate, { subpathNotUsedTemplate } from '../template/4xx.js';
import { log404 } from './common.js'; import { log404 } from './common.js';
import { writeHtmlResponse } from './response.js'; import { writeHtmlResponse } from './response.js';
import * as fs from 'fs';
export function baseMiddleware( export function baseMiddleware(
settings: AstroSettings, settings: AstroSettings,
@ -12,12 +13,13 @@ export function baseMiddleware(
): vite.Connect.NextHandleFunction { ): vite.Connect.NextHandleFunction {
const { config } = settings; const { config } = settings;
const site = config.site ? new URL(config.base, config.site) : undefined; 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) { return function devBaseMiddleware(req, res, next) {
const url = req.url!; 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)) { if (pathname.startsWith(devRoot)) {
req.url = url.replace(devRoot, '/'); req.url = url.replace(devRoot, '/');
@ -41,6 +43,16 @@ export function baseMiddleware(
return writeHtmlResponse(res, 404, html); 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();
}
});
}; };
} }

View file

@ -0,0 +1 @@
this is a test

View file

@ -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);
});
});
}); });