hono icon indicating copy to clipboard operation
hono copied to clipboard

feat(request): return new Request with cached body in raw getter

Open yusukebe opened this issue 3 months ago • 5 comments

This PR will fix the problem that we wanted to resolve with #4382.

Problem

The following code will cause the error:

import { Hono } from 'hono'

const app = new Hono()

app.post('/', async (c) => {
  const data = await c.req.json()
  await c.req.raw.json() // Body already used!
  return c.json(data)
})

export default app
CleanShot 2025-09-23 at 17 17 54@2x

This is because when you do c.req.raw, the body to be used is already consumed. This is explained in https://github.com/honojs/hono/pull/4382#issue-3370569516.

Solution

In this PR, it will create a new Request object with a cached body when c.req.raw is called. The reason why it does not use getter/setter and uses Object.defineProperty is that if it were to use getter/setter, it would fail with the spread syntax {...c.req}.

Caveat

The code size will be increased.

The performance may degrade, but it's small.

The author should do the following, if applicable

  • [x] Add tests
  • [x] Run tests
  • [x] bun run format:fix && bun run lint:fix to format the code
  • [ ] Add TSDoc/JSDoc to document the code

yusukebe avatar Sep 23 '25 08:09 yusukebe

Bundle size check

main (393ded9) #4425 (e84fcb4) +/-
Bundle Size (B) 18,294B 18,557B 263B
Bundle Size (KB) 17.87K 18.12K 0.25K

Compiler Diagnostics (tsc)

main (393ded9) #4425 (e84fcb4) +/-
Files 300 300 0
Lines 140,207 140,227 20
Identifiers 127,056 127,083 27
Symbols 264,250 264,292 42
Types 155,889 155,935 46
Instantiations 538,872 538,826 -46
Memory used 310,269K 318,514K 8,245K
I/O read 0.02s 0.03s 0.01s
I/O write 0s 0s 0s
Parse time 0.72s 0.73s 0.01s
Bind time 0.3s 0.3s 0s
Check time 2.67s 2.77s 0.1s
Emit time 0s 0s 0s
Total time 3.69s 3.8s 0.11s

Compiler Diagnostics (typescript-go)

main (393ded9) #4425 (e84fcb4) +/-
Files 269 269 0
Lines 118,096 118,116 20
Identifiers 116,489 116,516 27
Symbols 353,957 353,972 15
Types 277,831 277,878 47
Instantiations 3,528,587 3,528,359 -228
Memory used 223,102K 223,163K 61K
Memory allocs 10,491,846 10,491,879 33
Parse time 0.07s 0.082s 0.012s
Bind time 0.024s 0.023s -0.001s
Check time 1.426s 1.616s 0.19s
Emit time 0s 0s 0s
Total time 1.534s 1.723s 0.189s

Reported by octocov

github-actions[bot] avatar Sep 23 '25 08:09 github-actions[bot]

HTTP Performance Benchmark

Framework Runtime Average Ping Query Body
hono (origin/main) bun 36,007.10 48,800.58 31,322.64 27,898.07
hono (current) bun 35,418.11 47,988.25 30,267.06 27,999.03
Change -1.64% -1.66% -3.37% +0.36%

github-actions[bot] avatar Sep 23 '25 08:09 github-actions[bot]

Bundle size check

main (393ded9) #4425 (eacb440) +/-
Bundle Size (B) 18,294B 18,557B 263B
Bundle Size (KB) 17.87K 18.12K 0.25K

Compiler Diagnostics (tsc)

main (393ded9) #4425 (eacb440) +/-
Files 300 300 0
Lines 140,207 140,228 21
Identifiers 127,056 127,083 27
Symbols 264,250 264,292 42
Types 155,889 155,935 46
Instantiations 538,872 538,826 -46
Memory used 310,269K 308,090K -2,179K
I/O read 0.02s 0.03s 0.01s
I/O write 0s 0s 0s
Parse time 0.72s 0.78s 0.06s
Bind time 0.3s 0.3s 0s
Check time 2.67s 2.77s 0.1s
Emit time 0s 0s 0s
Total time 3.69s 3.86s 0.17s

Compiler Diagnostics (typescript-go)

main (393ded9) #4425 (eacb440) +/-
Files 269 269 0
Lines 118,096 118,117 21
Identifiers 116,489 116,516 27
Symbols 353,957 353,972 15
Types 277,831 277,878 47
Instantiations 3,528,587 3,528,359 -228
Memory used 223,102K 223,175K 73K
Memory allocs 10,491,846 10,491,870 24
Parse time 0.07s 0.078s 0.008s
Bind time 0.024s 0.016s -0.008s
Check time 1.426s 1.509s 0.083s
Emit time 0s 0s 0s
Total time 1.534s 1.605s 0.071s

Reported by octocov

github-actions[bot] avatar Sep 23 '25 08:09 github-actions[bot]

HTTP Performance Benchmark

Framework Runtime Average Ping Query Body
hono (origin/main) bun 38,250.69 53,142.55 33,106.71 28,502.80
hono (current) bun 37,401.78 52,662.68 31,646.26 27,896.40
Change -2.22% -0.90% -4.41% -2.13%

github-actions[bot] avatar Sep 23 '25 08:09 github-actions[bot]

Codecov Report

:x: Patch coverage is 94.28571% with 2 lines in your changes missing coverage. Please review. :white_check_mark: Project coverage is 91.28%. Comparing base (393ded9) to head (4c411e6).

Files with missing lines Patch % Lines
src/request.ts 94.28% 2 Missing :warning:
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4425      +/-   ##
==========================================
+ Coverage   91.25%   91.28%   +0.02%     
==========================================
  Files         171      171              
  Lines       10913    10933      +20     
  Branches     3144     3149       +5     
==========================================
+ Hits         9959     9980      +21     
+ Misses        953      952       -1     
  Partials        1        1              

:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Have feedback on the report? Share it here.

:rocket: New features to boost your workflow:
  • :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • :package: JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

codecov[bot] avatar Sep 23 '25 08:09 codecov[bot]