-
Notifications
You must be signed in to change notification settings - Fork 34
Description
Summary
When using elide serve with a fetch handler that returns a Response with a custom Content-Type header, the header is overwritten based on the body type, ignoring the user-specified value.
Regression Source
This bug was introduced in PR #1736 ("feat: new server engine", merged Nov 8, 2025).
The mapResponseBody() function was added as part of the new server engine, and it unconditionally overwrites Content-Type:
// From PR #1736 diff - packages/graalvm/.../FetchIntrinsic.kt
+ private fun mapResponseBody(
+ value: Value?,
+ headers: FetchMutableHeaders,
+ ...
+ value.isString -> {
+ val bytes = value.asString().toByteArray(StandardCharsets.UTF_8)
+ headers.set("Content-Type", "text/plain") // ← Bug: unconditionally overwritesThe new fetch handler pattern's body mapping logic doesn't respect user-specified headers.
Expected Behavior
export default async function fetch(request: Request) {
return new Response("<h1>Hello</h1>", {
headers: { "Content-Type": "text/html; charset=utf-8" }
});
}Should return Content-Type: text/html; charset=utf-8
Actual Behavior
Returns Content-Type: text/plain because mapResponseBody() unconditionally overwrites the header.
Root Cause
In FetchIntrinsic.kt, the mapResponseBody() function always calls headers.set("Content-Type", ...) based on body type:
- String body →
text/plain - Buffer →
application/octet-stream - Object →
application/json
This overwrites any user-specified Content-Type because headers are passed to mapResponseBody() after being populated from user options, and then overwritten.
Proposed Fix
Check if Content-Type is already set before overwriting:
// Before (bug):
headers.set("Content-Type", "text/plain")
// After (fix):
if (!headers.has("Content-Type")) headers.set("Content-Type", "text/plain")Verification
Confirmed via curl that custom headers ARE applied but Content-Type is overwritten:
< X-Custom: test-value ← Works!
< Content-Type: text/plain ← Overwritten (should be text/html)
Affected Versions
Testing revealed:
- beta9: Fetch handler pattern not yet available (server doesn't start)
- beta10, beta11-rc1 through rc3: Have fetch handler but with Content-Type bug
Since PR #1736 introduced both the fetch handler pattern AND the mapResponseBody() function, all versions with fetch handler support have this bug.
No Workaround Available
- Cannot use older version (fetch handlers didn't exist before feat: new server engine #1736)
- Cannot use different API (old
Elide.httpwas removed in feat: new server engine #1736) - Fix is required to serve HTML with correct Content-Type
Environment
- Elide version: 1.0.0-beta11-rc3
- OS: Linux
- Runtime: Native