Skip to content

Commit

Permalink
Prefer (allowed) static assets to routes (#5070)
Browse files Browse the repository at this point in the history
* failing test for #5066

* allow vite to serve files where appropriate

* print helpful 403 in dev

* Update packages/kit/src/vite/dev/index.js

* try and figure out why windows is failing

* try this

* store protocol and verbose instead of vite_config

* neaten up

* account for server.fs.strict

* Update packages/kit/test/apps/basics/test/test.js

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>

* Create nice-boxes-exercise.md

Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
  • Loading branch information
Rich-Harris and benmccann committed Jul 8, 2022
1 parent 897dcd7 commit a6e3072
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/nice-boxes-exercise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sveltejs/kit": patch
---

Serve static assets before routes in dev, but only if in an allowed directory
15 changes: 14 additions & 1 deletion packages/kit/src/vite/dev/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ const cwd = process.cwd();

/**
* @param {import('vite').ViteDevServer} vite
* @param {import('vite').ResolvedConfig} vite_config
* @param {import('types').ValidatedConfig} svelte_config
* @return {Promise<Promise<() => void>>}
*/
export async function dev(vite, svelte_config) {
export async function dev(vite, vite_config, svelte_config) {
installPolyfills();

sync.init(svelte_config);
Expand Down Expand Up @@ -212,6 +213,18 @@ export async function dev(vite, svelte_config) {
}
}

const file = posixify(path.resolve(decoded.slice(1)));
const is_file = fs.existsSync(file) && !fs.statSync(file).isDirectory();
const allowed =
!vite_config.server.fs.strict ||
vite_config.server.fs.allow.some((dir) => file.startsWith(dir));

if (is_file && allowed) {
// @ts-expect-error
serve_static_middleware.handle(req, res);
return;
}

if (!decoded.startsWith(svelte_config.kit.paths.base)) {
return not_found(
res,
Expand Down
17 changes: 10 additions & 7 deletions packages/kit/src/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function kit() {
/** @type {import('types').ValidatedConfig} */
let svelte_config;

/** @type {import('vite').UserConfig} */
/** @type {import('vite').ResolvedConfig} */
let vite_config;

/** @type {import('vite').ConfigEnv} */
Expand Down Expand Up @@ -121,7 +121,6 @@ function kit() {
name: 'vite-plugin-svelte-kit',

async config(config, config_env) {
vite_config = config;
vite_config_env = config_env;
svelte_config = await load_config();
is_build = config_env.command === 'build';
Expand Down Expand Up @@ -185,6 +184,10 @@ function kit() {
return result;
},

configResolved(config) {
vite_config = config;
},

buildStart() {
if (is_build) {
rimraf(paths.build_dir);
Expand All @@ -196,8 +199,9 @@ function kit() {
},

async writeBundle(_options, bundle) {
const verbose = vite_config.logLevel === 'info';
const log = logger({ verbose });
const log = logger({
verbose: vite_config.logLevel === 'info'
});

fs.writeFileSync(
`${paths.client_out_dir}/version.json`,
Expand Down Expand Up @@ -330,12 +334,11 @@ function kit() {
},

async configureServer(vite) {
return await dev(vite, svelte_config);
return await dev(vite, vite_config, svelte_config);
},

configurePreviewServer(vite) {
const protocol = vite_config.preview?.https ? 'https' : 'http';
return preview(vite, svelte_config, protocol);
return preview(vite, svelte_config, vite_config.preview.https ? 'https' : 'http');
}
};
}
Expand Down
7 changes: 7 additions & 0 deletions packages/kit/test/apps/basics/src/routes/package.json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function get() {
return {
body: {
works: true
}
};
}
6 changes: 6 additions & 0 deletions packages/kit/test/apps/basics/src/routes/src/[...anything].js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('./__types/[...anything]').RequestHandler} */
export function get() {
return {
body: 'dynamically rendered file'
};
}
12 changes: 9 additions & 3 deletions packages/kit/test/apps/basics/test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2705,12 +2705,18 @@ test.describe('Static files', () => {
expect(response.status()).toBe(process.env.DEV ? 403 : 404);
});

test('Vite serves assets in src directory', async ({ page, request }) => {
test('Vite serves assets in allowed directories', async ({ page, request }) => {
await page.goto('/assets');
const path = await page.textContent('h1');

const response = await request.get(path);
expect(response.status()).toBe(200);
const r1 = await request.get(path);
expect(r1.status()).toBe(200);
expect(await r1.text()).toContain('http://www.w3.org/2000/svg');

// check that we can fetch a route which overlaps with the name of a file
const r2 = await request.get('/package.json');
expect(r2.status()).toBe(200);
expect(await r2.json()).toEqual({ works: true });
});

test('Filenames are case-sensitive', async ({ request }) => {
Expand Down

0 comments on commit a6e3072

Please sign in to comment.