diff --git a/runtime_tests/bun/index.test.tsx b/runtime_tests/bun/index.test.tsx index db2f7edd1b..471ba814e7 100644 --- a/runtime_tests/bun/index.test.tsx +++ b/runtime_tests/bun/index.test.tsx @@ -12,12 +12,21 @@ import { basicAuth } from '../../src/middleware/basic-auth' import { jwt } from '../../src/middleware/jwt' import { HonoRequest } from '../../src/request' import { stream, streamSSE } from '../..//src/helper/streaming' +import os from 'node:os' +import { unlink } from 'node:fs/promises' // Test just only minimal patterns. // Because others are tested well in Cloudflare Workers environment already. Bun.env.NAME = 'Bun' +// BEGIN: for staticServe absolute path +const homedir = os.homedir() +const absolute_path_file = `${homedir}/test-serve-static-hono-bun.css` +// temporary creation, will be deleted +await Bun.write(absolute_path_file, 'body {background-color: blue;}') +// END + describe('Basic', () => { const app = new Hono() app.get('/a/:foo', (c) => { @@ -88,6 +97,7 @@ describe('Serve Static Middleware', () => { '/favicon-notfound.ico', serveStatic({ path: './runtime_tests/bun/favicon-notfound.ico', onNotFound }) ) + app.use('/test-serve-static-hono-bun.css', serveStatic({ path: absolute_path_file })) app.use('/favicon-notfound.ico', async (c, next) => { await next() c.header('X-Custom', 'Bun') @@ -116,6 +126,15 @@ describe('Serve Static Middleware', () => { expect(res.headers.get('Content-Type')).toBe('image/x-icon') }) + it('Should return static file with absolute path correctly', async () => { + const res = await app.request(new Request('http://localhost/test-serve-static-hono-bun.css')) + await res.arrayBuffer() + expect(res.status).toBe(200) + expect(res.headers.get('Content-Type')).toBe('text/css; charset=utf-8') + // deleting 'test-serve-static-hono-bun.css' + await unlink(absolute_path_file) + }) + it('Should return 404 response', async () => { const res = await app.request(new Request('http://localhost/favicon-notfound.ico')) expect(res.status).toBe(404) diff --git a/src/adapter/bun/serve-static.ts b/src/adapter/bun/serve-static.ts index be9fa2cca0..b292c9016b 100644 --- a/src/adapter/bun/serve-static.ts +++ b/src/adapter/bun/serve-static.ts @@ -9,13 +9,15 @@ export const serveStatic = ( ): MiddlewareHandler => { return async function serveStatic(c, next) { const getContent = async (path: string) => { - path = `./${path}` + // let absolute path be, otherwise add './' + path = path.startsWith('/') ? path : `./${path}` // @ts-ignore const file = Bun.file(path) return (await file.exists()) ? file : null } const pathResolve = (path: string) => { - return `./${path}` + // let absolute path be, otherwise add './' + return path.startsWith('/') ? path : `./${path}` } const isDir = async (path: string) => { let isDir diff --git a/src/utils/filepath.ts b/src/utils/filepath.ts index f3f2ea82e3..c1147d861e 100644 --- a/src/utils/filepath.ts +++ b/src/utils/filepath.ts @@ -39,8 +39,9 @@ export const getFilePathWithoutDefaultDocument = ( return } - // /foo.html => foo.html - filename = filename.replace(/^\.?[\/\\]/, '') + // ./foo.html => foo.html + // ignore /foo.html as it's intentionally absolute path + filename = filename.replace(/^\.[\/\\]/, '') // foo\bar.txt => foo/bar.txt filename = filename.replace(/\\/, '/') @@ -50,7 +51,9 @@ export const getFilePathWithoutDefaultDocument = ( // ./assets/foo.html => assets/foo.html let path = root ? root + '/' + filename : filename - path = path.replace(/^\.?\//, '') + + // ignore absolute path e.g. /assets/foo.css + path = path.replace(/^\.\//, '') return path }