Skip to content

Commit

Permalink
fix(serve-static):supports directory contains . and not ends / (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
yusukebe committed Aug 11, 2024
1 parent ac069d1 commit 7a254bc
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 1 deletion.
12 changes: 12 additions & 0 deletions runtime_tests/bun/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,18 @@ describe('Serve Static Middleware', () => {
expect(res.status).toBe(200)
expect(await res.text()).toBe('Bun!!')
})

it('Should return 200 response - /static/helloworld', async () => {
const res = await app.request('http://localhost/static/helloworld')
expect(res.status).toBe(200)
expect(await res.text()).toBe('Hi\n')
})

it('Should return 200 response - /static/hello.world', async () => {
const res = await app.request('http://localhost/static/hello.world')
expect(res.status).toBe(200)
expect(await res.text()).toBe('Hi\n')
})
})

// Bun support WebCrypto since v0.2.2
Expand Down
1 change: 1 addition & 0 deletions runtime_tests/bun/static/hello.world/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi
1 change: 1 addition & 0 deletions runtime_tests/bun/static/helloworld/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi
8 changes: 8 additions & 0 deletions runtime_tests/deno/middleware.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ Deno.test('Serve Static middleware', async () => {
} as Request)
assertEquals(res.status, 404)
assertEquals(await res.text(), '404 Not Found')

res = await app.request('http://localhost/static/helloworld')
assertEquals(res.status, 200)
assertEquals(await res.text(), 'Hi\n')

res = await app.request('http://localhost/static/hello.world')
assertEquals(res.status, 200)
assertEquals(await res.text(), 'Hi\n')
})

Deno.test('JWT Authentication middleware', async () => {
Expand Down
1 change: 1 addition & 0 deletions runtime_tests/deno/static/hello.world/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi
1 change: 1 addition & 0 deletions runtime_tests/deno/static/helloworld/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hi
10 changes: 10 additions & 0 deletions src/adapter/bun/serve-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { serveStatic as baseServeStatic } from '../../middleware/serve-static'
import type { ServeStaticOptions } from '../../middleware/serve-static'
import type { Env, MiddlewareHandler } from '../../types'
import { stat } from 'node:fs/promises'

export const serveStatic = <E extends Env = Env>(
options: ServeStaticOptions<E>
Expand All @@ -16,10 +17,19 @@ export const serveStatic = <E extends Env = Env>(
const pathResolve = (path: string) => {
return `./${path}`
}
const isDir = async (path: string) => {
let isDir
try {
const stats = await stat(path)
isDir = stats.isDirectory()
} catch {}
return isDir
}
return baseServeStatic({
...options,
getContent,
pathResolve,
isDir,
})(c, next)
}
}
11 changes: 10 additions & 1 deletion src/adapter/deno/serve-static.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { Env, MiddlewareHandler } from '../../types'

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const { open } = Deno
const { open, lstatSync } = Deno

export const serveStatic = <E extends Env = Env>(
options: ServeStaticOptions<E>
Expand All @@ -22,10 +22,19 @@ export const serveStatic = <E extends Env = Env>(
const pathResolve = (path: string) => {
return `./${path}`
}
const isDir = (path: string) => {
let isDir
try {
const stat = lstatSync(path)
isDir = stat.isDirectory
} catch {}
return isDir
}
return baseServeStatic({
...options,
getContent,
pathResolve,
isDir,
})(c, next)
}
}
17 changes: 17 additions & 0 deletions src/middleware/serve-static/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ describe('Serve Static Middleware', () => {
pathResolve: (path) => {
return `./${path}`
},
isDir: (path) => {
return path === 'static/hello.world'
},
})

app.get('/static/*', serveStatic)
Expand All @@ -37,6 +40,20 @@ describe('Serve Static Middleware', () => {
expect(await res.text()).toBe('Hello in ./static/sub/index.html')
})

it('Should return 200 response - /static/helloworld', async () => {
const res = await app.request('/static/helloworld')
expect(res.status).toBe(200)
expect(res.headers.get('Content-Type')).toMatch(/^text\/html/)
expect(await res.text()).toBe('Hello in ./static/helloworld/index.html')
})

it('Should return 200 response - /static/hello.world', async () => {
const res = await app.request('/static/hello.world')
expect(res.status).toBe(200)
expect(res.headers.get('Content-Type')).toMatch(/^text\/html/)
expect(await res.text()).toBe('Hello in ./static/hello.world/index.html')
})

it('Should decode URI strings - /static/%E7%82%8E.txt', async () => {
const res = await app.request('/static/%E7%82%8E.txt')
expect(res.status).toBe(200)
Expand Down
12 changes: 12 additions & 0 deletions src/middleware/serve-static/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const serveStatic = <E extends Env = Env>(
options: ServeStaticOptions<E> & {
getContent: (path: string, c: Context<E>) => Promise<Data | Response | null>
pathResolve?: (path: string) => string
isDir?: (path: string) => boolean | undefined | Promise<boolean | undefined>
}
): MiddlewareHandler => {
return async (c, next) => {
Expand All @@ -39,6 +40,17 @@ export const serveStatic = <E extends Env = Env>(
filename = options.rewriteRequestPath ? options.rewriteRequestPath(filename) : filename
const root = options.root

// If it was Directory, force `/` on the end.
if (!filename.endsWith('/') && options.isDir) {
const path = getFilePathWithoutDefaultDocument({
filename,
root,
})
if (path && (await options.isDir(path))) {
filename = filename + '/'
}
}

let path = getFilePath({
filename,
root,
Expand Down

0 comments on commit 7a254bc

Please sign in to comment.