Skip to content

Comments

feat: add transformRequest option for custom request streams#604

Open
ZawaPaP wants to merge 7 commits intofastify:mainfrom
ZawaPaP:feature/support-gcf
Open

feat: add transformRequest option for custom request streams#604
ZawaPaP wants to merge 7 commits intofastify:mainfrom
ZawaPaP:feature/support-gcf

Conversation

@ZawaPaP
Copy link

@ZawaPaP ZawaPaP commented Jan 31, 2026

Summary

I implemented a new option, transformRequest, allowing users to explicitly provide a custom stream to be piped into Busboy.

Background

As discussed in #547, environment-specific behaviors (such as Google Cloud Functions) pre-consume the request body, leaving the original request stream empty. This makes multipart parsing impossible with the standard streaming approach.

How to use

const { Readable } = require('node:stream')

fastify.register(require('@fastify/multipart'), {
  transformRequest: (request) => Readable.from(request.rawBody)
})

Checklist

@ZawaPaP ZawaPaP marked this pull request as ready for review January 31, 2026 07:32
@Fdawgs Fdawgs requested a review from Copilot February 4, 2026 09:34
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a new transformRequest option to @fastify/multipart that allows users to provide a custom stream for multipart parsing. This addresses issue #547 to support serverless environments like Google Cloud Functions and Firebase where the request body is pre-consumed, making it unavailable for standard stream processing.

Changes:

  • Added transformRequest option that accepts a function to transform the request stream before piping to Busboy
  • Added TypeScript type definitions for the new option
  • Added documentation and examples showing usage for GCP/Firebase scenarios
  • Added test coverage for the basic functionality

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
index.js Implements transformRequest logic by allowing a custom stream to be piped to Busboy parser instead of the raw request
types/index.d.ts Adds TypeScript type definition for transformRequest option
types/index.test-d.ts Adds type test to verify transformRequest parameter and return types
test/multipart-transform-request.test.js Adds tests verifying transformRequest is called and can provide custom stream data
README.md Documents the transformRequest option with a GCP-specific example

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

})

request.pipe(bb)
const stream = transformRequest(request)
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When transformRequest returns a different stream than the original request, event listeners for 'close' and 'error' are only attached to the original request object (lines 275-276, outside this diff). This means errors or close events from the transformed stream won't trigger cleanup, potentially leading to resource leaks.

Consider also attaching event listeners to the transformed stream when it differs from the original request, similar to how event listeners are attached to the request object.

Suggested change
const stream = transformRequest(request)
const stream = transformRequest(request)
if (stream !== request && typeof stream?.on === 'function') {
stream.on('close', cleanup)
stream.on('error', cleanup)
}

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is correct to fix, but possibly with a different implementation

mcollina and others added 3 commits February 10, 2026 00:20
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Matteo Collina <matteo.collina@gmail.com>
@ZawaPaP
Copy link
Author

ZawaPaP commented Feb 11, 2026

Thanks for looking into this PR, @mcollina.

I have added the following based on Copilot's suggestions:

  • New test cases for error scenarios.
  • Improved error handling for transformRequest to prevent socket leaks.

Could you please take another look when you have a chance? Let me know if I should take any further action.

@ZawaPaP ZawaPaP requested a review from mcollina February 11, 2026 05:14
index.js Outdated

request.pipe(bb)
const stream = transformRequest(request)
if (stream instanceof Error) {
Copy link
Member

@mcollina mcollina Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfortunately this can't work because users can throw whatever. you should probably let the throw flow out and handle it in that way.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking a look!
I've simplified it to let the error flow out and only check if the transformed data is a stream before passing it to Busboy.

@ZawaPaP ZawaPaP requested a review from mcollina February 11, 2026 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants