fix: preserve binary response bodies through adapter chain#16
Merged
Conversation
When a framework (Hono) returns a binary response body (e.g. image/png),
the adapter chain was corrupting the data at two points:
1. serverlessResponse.ts: The mock socket's write() method used getString()
which converts Buffer to UTF-8 string via toString('utf8'), replacing
bytes >= 0x80 with U+FFFD (EF BF BD). Fixed by using Buffer.indexOf()
to detect the HTTP header boundary directly in raw bytes.
2. transport.ts: buildResponse() always converted the accumulated body
buffer to string with toString('utf8'), regardless of content type.
Fixed by detecting binary content types (image/, audio/, video/,
application/octet-stream, application/pdf, font/) and base64-encoding
the body with isBase64Encoded:true in those cases.
3. index.ts: The response's isBase64Encoded (correctly set by buildResponse
based on content-type) was being overwritten by the request's
isBase64Encoded value. Removed the override.
Also removed the now-unused getString() helper and headerEnd constant.
- transport.test.ts: 12 new tests for binary content-type detection (image/audio/video/pdf/font → base64, text/json/html → utf8) - serverlessResponse.test.ts: 3 new tests for binary data preservation through mock socket write - index-hono.spec.test.ts: 3 new integration tests verifying isBase64Encoded flag set correctly for image/png vs text/html Also fixed: removed application/octet-stream from binary detection (too generic — Express defaults to it for Buffer responses).
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #16 +/- ##
==========================================
+ Coverage 91.01% 93.11% +2.09%
==========================================
Files 13 13
Lines 334 334
Branches 76 78 +2
==========================================
+ Hits 304 311 +7
+ Misses 20 15 -5
+ Partials 10 8 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Blankll
added a commit
to geek-fun/serverlessinsight
that referenced
this pull request
Jun 30, 2026
…200) ## Problem When `@geek-fun/serverless-adapter` returns a response with `isBase64Encoded: true` for binary content types (e.g. `image/png`), `transformFCResponse` was converting the base64-decoded data to a UTF-8 string via `Buffer.from(body, 'base64').toString('utf-8')`. This corrupted binary data — bytes \>= 0x80 became U+FFFD (`0xEF 0xBF 0xBD`). The result was then passed to `respondRaw()` which called `res.end(string)`, sending corrupt UTF-8 instead of raw binary bytes. ## Fix Detect binary content types by checking the `content-type` header: - `image/`, `audio/`, `video/`, `application/octet-stream`, `application/pdf`, `font/` → keep decoded body as **Buffer** - All other types (text, JSON, etc.) → convert to **UTF-8 string** as before This allows `respondRaw()` to call `res.end(buffer)` with raw bytes for binary content, while preserving backward compatibility for text/JSON responses. ## Changed Files - `src/stack/localStack/aliyunFc.ts`: Binary content-type detection + Buffer preservation - `tests/unit/stack/localStack/aliyunFc.unit.test.ts`: Updated PNG test to verify Buffer output with `Buffer.equals()` byte equality check ## Depends On - geek-fun/serverless-adapter#16 (binary response base64 encoding) --------- Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Binary response bodies (e.g.
image/pngtiles from Hono) were corrupted when proxied through the adapter chain. Bytes >= 0x80 were replaced with UTF-8 replacement character U+FFFD (0xEF 0xBF 0xBD), destroying the PNG signature.Root Cause
Two corruption points in the chain:
serverlessResponse.ts: The mock socket's
write()method calledgetString()which converts Buffer to UTF-8 string viatoString('utf8'). Binary bytes >= 0x80 become U+FFFD.transport.ts:
buildResponse()always calledbody.toString('utf8')regardless of content type.Additionally, index.ts was overwriting the response's
isBase64Encodedwith the request's value.Fix
serverlessResponse.ts: Use
Buffer.indexOf('\r\n\r\n')to find the HTTP header boundary in raw bytes. Body data is added as Buffer, never converted to string. Removed the now-unusedgetString()helper.transport.ts: Detect binary content types (
image/,audio/,video/,application/octet-stream,application/pdf,font/) and base64-encode them withisBase64Encoded: true. Text responses continue to use UTF-8.index.ts: Pass
builtResponsedirectly toprovider.formatResponse()without overriding itsisBase64Encodedfield.Testing
\x89PNGsignatures through the full chain (Hono → adapter → si-local → HTTP response)