Commit c55311b
fix: defer writeHead to prevent Content-Length truncation in payment rewriter (#161)
* fix: defer writeHead in payment response rewriter to prevent Content-Length truncation
@hono/node-server's responseViaCache sets Content-Length from the
original body size and calls writeHead before res.end. When the payment
response rewriter intercepts res.end and swaps in a larger rewritten
body (with full x402/mpp challenge data), the Content-Length already on
the wire reflects the original smaller body. The client reads only that
many bytes, truncating the JSON and causing a parse error.
Fix: defer writeHead until res.end fires, then update Content-Length to
match the (potentially rewritten) body before flushing both. For SSE
(res.write before res.end), the deferred writeHead flushes at the first
write call — no Content-Length conflict since SSE doesn't use the
responseViaCache path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: add writeHead deferral tests for JSON and SSE response paths
Tests installPaymentResponseRewriter by simulating @hono/node-server's
exact call patterns:
- JSON path: writeHead(status, {Content-Length}) then end(body)
- SSE path: writeHead(status, headers) then write(chunk)... then end()
Coverage:
- Content-Length updated to match rewritten body size
- Content-Length preserved when no rewrite occurs (no challenge, non-matching body)
- writeHead(status, statusMessage, headers) three-arg form
- end() without writeHead (implicit headers)
- Buffer body handling
- Hook restoration after end()
- SSE: writeHead flushed on first write, not duplicated
- SSE: payment error chunks rewritten, normal chunks unchanged
- SSE: only error chunk rewritten in multi-chunk stream
- Content-Length === actual body byte length invariant
Also exports installPaymentResponseRewriter for direct unit testing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent ab410f0 commit c55311b
2 files changed
Lines changed: 426 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
165 | 165 | | |
166 | 166 | | |
167 | 167 | | |
168 | | - | |
| 168 | + | |
| 169 | + | |
169 | 170 | | |
170 | 171 | | |
| 172 | + | |
171 | 173 | | |
172 | 174 | | |
173 | 175 | | |
| |||
183 | 185 | | |
184 | 186 | | |
185 | 187 | | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
186 | 208 | | |
187 | 209 | | |
188 | 210 | | |
| 211 | + | |
189 | 212 | | |
190 | 213 | | |
191 | 214 | | |
| |||
195 | 218 | | |
196 | 219 | | |
197 | 220 | | |
| 221 | + | |
198 | 222 | | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
199 | 246 | | |
200 | 247 | | |
201 | 248 | | |
| |||
0 commit comments