serveStatic root is incorrect on Windows + Bun for absolute path (other interpreters probably too)
What version of Hono are you using?
4.6.3
What runtime/platform is your app running on?
Bun
What steps can reproduce the bug?
app.use("/static/*",
serveStatic({
root: __dirname,
onNotFound(path, c) {
console.log(path)
}
}));
What is the expected behavior?
Server serve static file from __dirname +"/static"
What do you see instead?
Windows: Server always returns "resource not found". console.log in the onNotFound handler shows path starting from "./C:/Users/..."
Linux: Working as it should
Additional information
That is probably is the reason of the problem
I think serveStatic should always expect absolute path or not modify the path. To make it safe just avoid ".." in the file name.
Also "static" (or probably the url prefix used during the middleware registration) is always added to the root path when searching for the file. It seams to be strange too.
Perhaps it would be better to pass the __dirname prefix by replacing it...
I think hardcoding poses a security risk.
__dirname.replace(/^C:/, "")
I'm planning that the serveStatic supports Windows: https://github.com/honojs/hono/pull/3477
This issue is also present with Deno. This issue can be worked around by using a relative path. Here is what I have in my project to make my absolute path relative to the current working directory.
const dirname = path.dirname(path.fromFileUrl(mainUrl));
const absolutePublicPath = path.resolve(dirname, "./public");
// Workaround for Hono Windows issue: use simple relative path from cwd
const cwd = Deno.cwd();
const relativePath = path.relative(cwd, absolutePublicPath);
// Ensure forward slashes on Windows for Hono compatibility
const publicPath = Deno.build.os === "windows"
? relativePath.replace(/\\/g, "/")
: relativePath;
// Note: There's a known issue with Hono's serveStatic on Windows (https://github.com/honojs/hono/issues/3475)
// This workaround attempts to work around path separator and relative path issues
app.get( "*", serveStatic({ root: publicPath }));