Skip to content

fix(serve-static): serve precompressed files for application/octet-stream#366

Open
yusukebe wants to merge 1 commit into
mainfrom
fix/serve-static-application-octet-stream
Open

fix(serve-static): serve precompressed files for application/octet-stream#366
yusukebe wants to merge 1 commit into
mainfrom
fix/serve-static-application-octet-stream

Conversation

@yusukebe

@yusukebe yusukebe commented Jul 1, 2026

Copy link
Copy Markdown
Member

Fixes #360

serveStatic({ precompressed: true }) didn't serve precompressed variants for application/octet-stream files like .bin, even when a .br/.zst/.gz existed. Now it does.

@yusukebe

yusukebe commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Hey @usualoma

I created this PR to fix #360. I thought it was better to handle application/octet-stream rather than update the docs as #360 said. Can you review?

@usualoma

usualoma commented Jul 2, 2026

Copy link
Copy Markdown
Member

Hi @yusukebe,
Thank you.

By the way, is the reason you didn't embed it directly into COMPRESSIBLE_CONTENT_TYPE_REGEX here to avoid discrepancies with the COMPRESSIBLE_CONTENT_TYPE_REGEX in the Hono core?
https://github.com/honojs/hono/blob/b20d4225c9aa9e615717ca74e437852cc9fd5b94/src/utils/compress.ts#L9-L10

I understand the desire to distinguish this from the COMPRESSIBLE_CONTENT_TYPE_REGEX in the Hono core, since it’s also used by the “compress” middleware.


However, I think there’s also the view that, in the case of precompressed, the COMPRESSIBLE_CONTENT_TYPE_REGEX check isn’t necessary.

I feel it might also be a good idea to allow passing

diff --git i/src/serve-static.ts w/src/serve-static.ts
index 9daa4c8..bea3535 100644
--- i/src/serve-static.ts
+++ w/src/serve-static.ts
@@ -12,7 +12,7 @@ export type ServeStaticOptions<E extends Env = Env> = {
   root?: string
   path?: string
   index?: string // default is 'index.html'
-  precompressed?: boolean
+  precompressed?: boolean | ((options: { path: string; mimeType?: string }) => boolean)
   rewriteRequestPath?: (path: string, c: Context<E>) => string
   onFound?: (path: string, c: Context<E>) => void | Promise<void>
   onNotFound?: (path: string, c: Context<E>) => void | Promise<void>
@@ -65,6 +65,12 @@ export const serveStatic = <E extends Env = any>(
     console.error(`serveStatic: root path '${root}' is not found, are you sure it's correct?`)
   }
 
+  const precompressedFilter: (options: { path: string; mimeType?: string }) => boolean =
+    typeof options.precompressed === 'function'
+      ? options.precompressed
+      : ({ mimeType }) =>
+          options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))
+
   return async (c, next) => {
     // Do nothing if Response is already set
     if (c.finalized) {
@@ -108,7 +114,7 @@ export const serveStatic = <E extends Env = any>(
     const mimeType = getMimeType(path)
     c.header('Content-Type', mimeType || 'application/octet-stream')
 
-    if (options.precompressed && (!mimeType || COMPRESSIBLE_CONTENT_TYPE_REGEX.test(mimeType))) {
+    if (precompressedFilter({ path, mimeType })) {
       const acceptEncodingSet = new Set(
         c.req
           .header('Accept-Encoding')

I thought about something like that, but I think it’s perfectly fine to target application/octet-stream for now!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Please document the COMPRESSIBLE_CONTENT_TYPE_REGEX-related behavior

2 participants