fix: serve data files with reserved characters in dev and preview
sirv decodes request paths with decodeURI, which leaves %26 (&) and %23 (#) encoded, so data files with such characters in their names were not found by the dev and preview servers. Hand sirv the fully decoded path, the way Apache resolves it in production.
This commit is contained in:
+28
-1
@@ -20,7 +20,34 @@ const staticContents = (): Plugin => {
|
||||
// browser revalidates against the ETag instead of falling back to
|
||||
// heuristic caching. Without it a re-dump, or another site served
|
||||
// from the same localhost port, is answered from a stale cache.
|
||||
middlewares.use(sirv(dir, { dev, etag: true, maxAge: 0 }));
|
||||
const serve = sirv(dir, { dev, etag: true, maxAge: 0 });
|
||||
middlewares.use((req, res, next) => {
|
||||
// sirv decodes the path with decodeURI, which leaves reserved
|
||||
// characters such as %26 (&) and %23 (#) encoded, so a file like
|
||||
// `CFP&Reg.png` is not found. sirv reuses `req._parsedUrl` when
|
||||
// it was parsed from the same `req.url`, so hand it the path
|
||||
// decoded the way Apache resolves it.
|
||||
const raw = req.url ?? '/';
|
||||
const idx = raw.search(/[?#]/);
|
||||
const pathname = idx === -1 ? raw : raw.slice(0, idx);
|
||||
if (pathname.includes('%')) {
|
||||
try {
|
||||
const decoded = pathname.split('/').map(decodeURIComponent).join('/');
|
||||
if (!decoded.includes('%')) {
|
||||
(req as typeof req & { _parsedUrl?: object })._parsedUrl = {
|
||||
pathname: decoded,
|
||||
search: '',
|
||||
query: undefined,
|
||||
hash: undefined,
|
||||
raw,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
// leave malformed escapes to sirv
|
||||
}
|
||||
}
|
||||
serve(req, res, next);
|
||||
});
|
||||
}
|
||||
};
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user