Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): normalize asset source locations …
Browse files Browse the repository at this point in the history
…in Vite-based development server

The Vite-based development server uses an allow list to permit access to configured assets. This list
is checked internally to Vite by using its normalized path form. To ensure that assets provided by the
build are checked correctly on all platforms, the asset list is now normalized with Vite's path
normalization prior to being used.
  • Loading branch information
clydin authored and alan-agius4 committed Dec 4, 2023
1 parent f4e819a commit 9906ab7
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export async function* serveWithVite(
assetFiles.clear();
if (result.assetFiles) {
for (const asset of result.assetFiles) {
assetFiles.set('/' + normalizePath(asset.destination), asset.source);
assetFiles.set('/' + normalizePath(asset.destination), normalizePath(asset.source));
}
}

Expand Down
59 changes: 59 additions & 0 deletions tests/legacy-cli/e2e/tests/commands/serve/assets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import assert from 'node:assert';
import { randomUUID } from 'node:crypto';
import { mkdir, rm, writeFile } from 'node:fs/promises';
import { ngServe, updateJsonFile } from '../../../utils/project';
import { getGlobalVariable } from '../../../utils/env';

export default async function () {
const outsideDirectoryName = `../outside-${randomUUID()}`;

await updateJsonFile('angular.json', (json) => {
json.projects['test-project'].architect.build.options.assets = [
'src/favicon.ico',
'src/assets',
// Ensure assets located outside the workspace root work with the dev server
{ 'input': outsideDirectoryName, 'glob': '**/*', 'output': './outside' },
];
});

await mkdir(outsideDirectoryName);
try {
await writeFile(`${outsideDirectoryName}/some-asset.xyz`, 'XYZ');

const port = await ngServe();

let response = await fetch(`http://localhost:${port}/favicon.ico`);
assert.strictEqual(response.status, 200, 'favicon.ico response should be ok');

response = await fetch(`http://localhost:${port}/outside/some-asset.xyz`);
assert.strictEqual(response.status, 200, 'outside/some-asset.xyz response should be ok');
assert.strictEqual(await response.text(), 'XYZ', 'outside/some-asset.xyz content is wrong');

// A non-existent HTML file request with accept header should fallback to the index HTML
response = await fetch(`http://localhost:${port}/does-not-exist.html`, {
headers: { accept: 'text/html' },
});
assert.strictEqual(
response.status,
200,
'non-existent file response should fallback and be ok',
);
assert.match(
await response.text(),
/<app-root/,
'non-existent file response should fallback and contain html',
);

// Vite will incorrectly fallback in all non-existent cases so skip last test case
// TODO: Remove conditional when Vite handles this case
if (getGlobalVariable('argv')['esbuild']) {
return;
}

// A non-existent file without an html accept header should not be found.
response = await fetch(`http://localhost:${port}/does-not-exist.png`);
assert.strictEqual(response.status, 404, 'non-existent file response should be not found');
} finally {
await rm(outsideDirectoryName, { force: true, recursive: true });
}
}

0 comments on commit 9906ab7

Please sign in to comment.