Skip to content

Commit d0baa10

Browse files
committed
Merge remote-tracking branch 'origin/main' into riya-amemiya/enable-fallback
2 parents 86dc6f3 + 006fe7e commit d0baa10

File tree

4 files changed

+33
-19
lines changed

4 files changed

+33
-19
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# 1.4.6 - 3 Nov 2025
2+
Bug fix:
3+
- normalize path only when unsafe
4+
- cache `crypto` package import
5+
6+
# 1.4.5 - 1 Nov 2025
7+
Bug fix:
8+
- [#52](https://github.com/elysiajs/elysia-static/pull/52) resolve static paths correctly on Windows
9+
110
# 1.4.4 - 14 Oct 2025
211
Bug fix:
312
- fix cjs main import

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@elysiajs/static",
3-
"version": "1.4.4",
3+
"version": "1.4.6",
44
"license": "MIT",
55
"scripts": {
66
"dev": "bun run --watch example/index.ts",

src/index.ts

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
4848
if (!builtinModule) return new Elysia()
4949

5050
const [fs, path] = builtinModule
51+
const isUnsafeSep = path.sep !== '/'
52+
53+
const normalizePath = isUnsafeSep
54+
? (p: string) => p.replace(/\\/g, '/')
55+
: (p: string) => p
5156

5257
const fileCache = new LRUCache<string, Response>()
5358

@@ -78,7 +83,7 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
7883
if (decodeURI)
7984
relativePath = fastDecodeURI(relativePath) ?? relativePath
8085

81-
let pathName = path.join(prefix, relativePath)
86+
let pathName = normalizePath(path.join(prefix, relativePath))
8287

8388
if (isBun && absolutePath.endsWith('.html')) {
8489
const htmlBundle = await import(absolutePath)
@@ -94,7 +99,9 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
9499
}
95100

96101
if (!extension)
97-
pathName = pathName.slice(0, pathName.lastIndexOf('.'))
102+
pathName = normalizePath(
103+
pathName.slice(0, pathName.lastIndexOf('.'))
104+
)
98105

99106
const file: Awaited<ReturnType<typeof getFile>> = isBun
100107
? getFile(absolutePath)
@@ -180,7 +187,6 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
180187

181188
return response.clone()
182189
}
183-
184190
app.get(
185191
pathName,
186192
useETag
@@ -225,8 +231,7 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
225231
if (!absolutePath || shouldIgnore(absolutePath)) continue
226232

227233
let relativePath = absolutePath.replace(assetsDir, '')
228-
const pathName = path.join(prefix, relativePath)
229-
234+
const pathName = normalizePath(path.join(prefix, relativePath))
230235
const htmlBundle = await import(absolutePath)
231236

232237
app.get(pathName, htmlBundle.default)
@@ -239,25 +244,25 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
239244
}
240245

241246
const serveStaticFile = async (pathName: string, requestHeaders?: Record<string, string | undefined>) => {
242-
// Normalize for ignore matching
243-
const rel = pathName.startsWith(assetsDir)
244-
? pathName.slice(assetsDir.length)
245-
: pathName
247+
const normalizedPath = normalizePath(pathName)
248+
const rel = normalizedPath.startsWith(assetsDir)
249+
? normalizedPath.slice(assetsDir.length)
250+
: normalizedPath
246251
if (shouldIgnore(rel)) return null
247252

248-
const cache = fileCache.get(pathName)
253+
const cache = fileCache.get(normalizedPath)
249254
if (cache) return cache.clone()
250255

251-
const fileStat = await fs.stat(pathName).catch(() => null)
256+
const fileStat = await fs.stat(normalizedPath).catch(() => null)
252257
if (!fileStat) return null
253258

254259
if (!indexHTML && fileStat.isDirectory()) return null
255260

256261
let file: NonNullable<Awaited<ReturnType<typeof getFile>>> | undefined
257-
let targetPath = pathName
262+
let targetPath = normalizedPath
258263

259264
if (!isBun && indexHTML) {
260-
const htmlPath = path.join(pathName, 'index.html')
265+
const htmlPath = path.join(normalizedPath, 'index.html')
261266
const cache = fileCache.get(htmlPath)
262267
if (cache) return cache.clone()
263268

@@ -267,8 +272,8 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
267272
}
268273
}
269274

270-
if (!file && !fileStat.isDirectory() && (await fileExists(pathName)))
271-
file = await getFile(pathName)
275+
if (!file && !fileStat.isDirectory() && (await fileExists(normalizedPath)))
276+
file = await getFile(normalizedPath)
272277

273278
if (!file) return null
274279

@@ -299,7 +304,7 @@ export async function staticPlugin<const Prefix extends string = '/prefix'>({
299304
)
300305
})
301306

302-
fileCache.set(pathName, response)
307+
fileCache.set(normalizedPath, response)
303308
return response.clone()
304309
}
305310

src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -203,8 +203,8 @@ export async function generateETag(file: BunFile | Buffer<ArrayBufferLike>) {
203203
.update(await (file as BunFile).arrayBuffer())
204204
.digest('base64')
205205

206-
if (!crypto) Crypto = process.getBuiltinModule('crypto')
207-
if (!crypto)
206+
if (!Crypto) Crypto = process.getBuiltinModule('crypto')
207+
if (!Crypto)
208208
return void console.warn(
209209
'[@elysiajs/static] crypto is required to generate etag.'
210210
)

0 commit comments

Comments
 (0)