mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 07:50:45 +00:00
Fix proprietary asset serving in dev (#3662 regression)
The proprietary/ fallback middleware was registered with `return () => {}`,
which placed it after Vite's htmlFallbackMiddleware. Browser `<img>`
requests carry `*/*` in their Accept header, so htmlFallback intercepted
them and returned index.html — meaning OpenFrontLogo.svg, Favicon.svg,
etc. silently rendered as the HTML shell.
Register the middleware up front, check resources/ first so publicDir
retains precedence, and set Content-Type via mrmime so browsers actually
render the SVGs.
This commit is contained in:
+25
-23
@@ -1,5 +1,6 @@
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import fs from "fs";
|
||||
import { lookup as lookupMime } from "mrmime";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { defineConfig, loadEnv, type Plugin } from "vite";
|
||||
@@ -19,31 +20,30 @@ import {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
function serveProprietaryDir(dir: string): Plugin {
|
||||
const resolvedDir = path.resolve(dir) + path.sep;
|
||||
function serveProprietaryDir(
|
||||
proprietaryDir: string,
|
||||
resourcesDir: string,
|
||||
): Plugin {
|
||||
return {
|
||||
name: "serve-proprietary-dir",
|
||||
configureServer(server) {
|
||||
// Return a function so the middleware is registered after Vite's internal
|
||||
// static-file handler (publicDir). This makes proprietary/ a fallback
|
||||
// rather than taking precedence over resources/.
|
||||
return () => {
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (!req.url) return next();
|
||||
const urlPath = new URL(req.url, "http://localhost").pathname;
|
||||
const filePath = path.resolve(
|
||||
dir,
|
||||
decodeURIComponent(urlPath).replace(/^\//, ""),
|
||||
);
|
||||
if (!filePath.startsWith(resolvedDir)) return next();
|
||||
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
|
||||
res.setHeader("Cache-Control", "no-cache");
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
};
|
||||
// Must run before Vite's htmlFallback; skip when resources/ has the file
|
||||
// so publicDir keeps precedence.
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (!req.url) return next();
|
||||
const rel = decodeURIComponent(
|
||||
new URL(req.url, "http://x").pathname,
|
||||
).replace(/^\//, "");
|
||||
if (rel.includes("..")) return next();
|
||||
if (fs.existsSync(path.join(resourcesDir, rel))) return next();
|
||||
const filePath = path.join(proprietaryDir, rel);
|
||||
if (!fs.existsSync(filePath) || !fs.statSync(filePath).isFile())
|
||||
return next();
|
||||
const mime = lookupMime(filePath);
|
||||
if (mime) res.setHeader("Content-Type", mime);
|
||||
res.setHeader("Cache-Control", "no-store");
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -123,7 +123,9 @@ export default defineConfig(({ mode }) => {
|
||||
|
||||
plugins: [
|
||||
tsconfigPaths(),
|
||||
...(!isProduction ? [serveProprietaryDir(proprietaryDir)] : []),
|
||||
...(!isProduction
|
||||
? [serveProprietaryDir(proprietaryDir, resourcesDir)]
|
||||
: []),
|
||||
...(isProduction
|
||||
? []
|
||||
: [
|
||||
|
||||
Reference in New Issue
Block a user