Skip to content

Bound the Mastodon response body read and cancel oversized bodies - #129

Merged
NinjaLikesCheez merged 3 commits into
mainfrom
fix/mastodon-bounded-body
Oct 19, 2026
Merged

NinjaLikesCheez merged 3 commits into
mainfrom
fix/mastodon-bounded-body

Conversation

@NinjaLikesCheez

Copy link
Copy Markdown
Contributor

What was wrong

discardBody in src/adapters/mastodon/client.ts said it read the response body only to bound memory, but:

  • With no content-length (a chunked response), it called response.text(), which buffers the whole body before the size check. An instance (or anything in front of it) streaming a huge body would have it all held in memory.
  • With a content-length over the limit, it returned without reading or cancelling the body, leaving the stream and its connection open.

What changed

  • A body that declares a content-length over maxResponseBytes (default 64 KiB) is cancelled with body.cancel() without being read.
  • Otherwise the body is read through a stream reader that counts bytes and cancels as soon as the total passes the limit. Nothing is buffered or kept; the body is only drained so the connection can be reused.
  • A failed cancel is ignored, so a 2xx status is still treated as posted and a non-OK status still throws the same safe MastodonError (status only, with no body and no token).
  • Changelog entry under Unreleased / Fixed.

How it was tested

New tests in src/adapters/mastodon/client.test.ts mock HTTP at the client boundary with an instrumented ReadableStream (no live instance):

  • an over-limit content-length is cancelled with at most one chunk pulled
  • a chunked body is cancelled after passing the cap (at most 3 of 1000 chunks pulled)
  • an oversized error body is cancelled and the error is still Mastodon responded with HTTP 500
  • a small chunked body is read to the end and not cancelled
  • a body-less 204 is accepted
  • a cancel that throws is ignored on both paths

Four of the new tests fail against the old code. just check passes.

🤖 Generated with Claude Code

discardBody buffered a chunked body in full with response.text() before
checking its size, and left a body with an over-limit content-length
unread and open. Read through a stream reader with a byte cap instead,
and cancel the body once it is (or declares to be) over the limit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NinjaLikesCheez NinjaLikesCheez added the bug Something isn't working label Oct 18, 2026
@NinjaLikesCheez
NinjaLikesCheez merged commit 961b59c into main Oct 19, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant