Skip to content

fix: set explicit content-type for Uint8Array responses#1386

Open
mixelburg wants to merge 1 commit into
h3js:mainfrom
mixelburg:fix/uint8array-content-type
Open

fix: set explicit content-type for Uint8Array responses#1386
mixelburg wants to merge 1 commit into
h3js:mainfrom
mixelburg:fix/uint8array-content-type

Conversation

@mixelburg

@mixelburg mixelburg commented May 13, 2026

Copy link
Copy Markdown

Description

When returning a Uint8Array from an h3 handler, the content-type header was not set by h3. This caused inconsistent behavior across runtimes:

  • Node.js: no content-type set → browsers default to text/html and display the content
  • Bun: automatically sets application/octet-stream → browsers trigger file download instead of displaying

Solution

Explicitly set content-type: application/octet-stream for Uint8Array responses when no content-type is already set. This ensures consistent behavior across runtimes and allows users to override by setting the header explicitly before returning.

app.get("/", (e) => {
  e.res.headers.set("content-type", "text/plain");
  return new TextEncoder().encode("hello");
});

Changes

  • src/response.ts: Added content-type: application/octet-stream header for Uint8Array responses (guarded by !event.res.headers.has("content-type"))

Testing

  • All 1148 functional tests pass
  • Bundle size tests fail due to added bytes (expected for any code addition)

Fixes #1158

Summary by CodeRabbit

  • Bug Fixes
    • Fixed an issue where binary responses could be returned without a Content-Type header; responses now include a default Content-Type of application/octet-stream so binary payloads are served correctly and reliably.

@mixelburg mixelburg requested a review from pi0 as a code owner May 13, 2026 22:19
@coderabbitai

coderabbitai Bot commented May 13, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 43f29969-640b-42b7-af21-105f50f15f98

📥 Commits

Reviewing files that changed from the base of the PR and between 22101d0 and 1d2e15b.

📒 Files selected for processing (1)
  • src/response.ts

📝 Walkthrough

Walkthrough

prepareResponseBody now ensures Uint8Array responses include a content-type header, defaulting to application/octet-stream when no content-type is present, in addition to existing content-length handling.

Changes

Binary Response Headers

Layer / File(s) Summary
Binary response content-type header
src/response.ts
When preparing Uint8Array responses, prepareResponseBody now conditionally sets event.res.headers['content-type'] to application/octet-stream if the header is not already defined.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 I nibble bytes and set their tone,
A header placed when none is shown.
From fuzzy bits to browser view,
application/octet-stream rings true.
Hop—now payloads land as due.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely describes the main change: setting explicit content-type headers for Uint8Array responses.
Linked Issues check ✅ Passed The code change directly addresses issue #1158 by setting content-type: application/octet-stream when a Uint8Array is returned and no content-type header exists, ensuring consistent cross-runtime behavior.
Out of Scope Changes check ✅ Passed The change is narrowly scoped to src/response.ts and directly addresses the issue of missing content-type headers for Uint8Array responses, with no extraneous modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

When returning a Uint8Array from an h3 handler, the content-type
header was not set. This caused inconsistent behavior across runtimes:

- Node.js: no content-type set (browsers default to text/html)
- Bun: automatically sets application/octet-stream, triggering file
  download in browsers

The fix explicitly sets content-type: application/octet-stream for
Uint8Array responses when no content-type is already set. This ensures
consistent behavior across runtimes and allows users to override the
content-type by setting it explicitly before returning.

All 1148 functional tests pass. Bundle size tests fail due to the
added bytes (expected for any code addition).

Fixes h3js#1158
@mixelburg mixelburg force-pushed the fix/uint8array-content-type branch from 22101d0 to 1d2e15b Compare June 13, 2026 00:19
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.

bun sets default content-type for Uint8Array

1 participant