`text/plain` request bodies are parsed instead of streamed: non-UTF-8 bytes corrupted, bodies over 1 MiB rejected with 413

Open Beginner friendly
#493 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
82/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
javascript, node.js

Research direction

Start in index.js around lines 718–719, where the proxy registers body parsers, and read the nearby parser tests. Add coverage for text/plain uploads with non-UTF-8 bytes and bodies above the default body limit, then register the needed parser and confirm the tests show byte-for-byte forwarding without a 413 response.

Written by the indexing model from the issue text.

Description

Prerequisites
  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported
Fastify version

5.12.8

Plugin version

@fastify/http-proxy 11.6.6 (also main at ce4d419), @fastify/reply-from 12.8.1

Node.js version

26.13.0

Operating system

Linux

Operating system version (i.e. 20.04, 11.3, 10)

Debian 12

Description

The README says non-JSON payloads are streamed directly to the destination. That holds for text/csv or application/octet-stream, but not for text/plain: Fastify's built-in text/plain parser still runs, because the plugin only overrides application/json and * (index.js lines 718-719). The body is decoded as UTF-8 and re-sent as a string, so a text/plain upload in any other charset is corrupted, and a text/plain upload larger than bodyLimit gets a 413 instead of being streamed.

// repro.mjs
import http from 'node:http';
import Fastify from 'fastify';
import proxy from '@fastify/http-proxy';

// upstream: report how many bytes arrived and the first bytes
http.createServer((req, res) => {
  const chunks = [];
  req.on('data', (c) => chunks.push(c));
  req.on('end', () => {
    const b = Buffer.concat(chunks);
    res.end(`got ${b.length} bytes: ${b.subarray(0, 6).toString('hex')}`);
  });
}).listen(3001);

const app = Fastify();
app.register(proxy, { upstream: 'http://127.0.0.1:3001' });
await app.listen({ port: 3000 });

const send = async (type, body) => {
  const r = await fetch('http://127.0.0.1:3000/upload', { method: 'POST', headers: { 'content-type': type }, body });
  console.log(type.padEnd(30), `sent ${body.length} bytes: ${body.subarray(0, 6).toString('hex')} ->`, r.status, await r.text());
};
const latin1 = Buffer.from('café crème', 'latin1');
await send('text/plain; charset=iso-8859-1', latin1);
await send('text/csv; charset=iso-8859-1', latin1);
await send('text/plain', Buffer.alloc(2 * 1024 * 1024, 'a'));
await send('application/octet-stream', Buffer.alloc(2 * 1024 * 1024, 'a'));
process.exit(0);

node repro.mjs prints:

text/plain; charset=iso-8859-1 sent 10 bytes: 636166e92063 -> 200 got 14 bytes: 636166efbfbd
text/csv; charset=iso-8859-1   sent 10 bytes: 636166e92063 -> 200 got 10 bytes: 636166e92063
text/plain                     sent 2097152 bytes: 616161616161 -> 413 {"statusCode":413,"code":"FST_ERR_CTP_BODY_TOO_LARGE","error":"Payload Too Large","message":"Request body is too large"}
application/octet-stream       sent 2097152 bytes: 616161616161 -> 200 got 2097152 bytes: 616161616161
Link to code that reproduces the bug

https://gist.github.com/trackoor/a9dc305ecd07ded3018ca5fea688a582

Expected Behavior

text/plain bodies reach the upstream byte for byte, like every other non-JSON type: 10 bytes 636166e92063 in the first line and 200 got 2097152 bytes in the third. Registering bodyParser for text/plain next to application/json should be enough.

Found with a differential-testing tool; the report was drafted with AI assistance and reviewed and edited by me.

Credit: https://ucsbplse.github.io/

Dominant language
JavaScript
Stars
394
Forks
105
Avg merge
9h 34m
Merged PRs (30d)
2

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from fastify/fastify-http-proxy

All issues in fastify/fastify-http-proxy

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.