Skip to content

Instantly share code, notes, and snippets.

@vvo
Last active March 19, 2025 23:45
Show Gist options
  • Save vvo/014cef462707337326476271074e5f75 to your computer and use it in GitHub Desktop.
Save vvo/014cef462707337326476271074e5f75 to your computer and use it in GitHub Desktop.
import type { IncomingMessage } from 'http';
import { Transform, type TransformCallback } from 'stream';
/**
* A transform stream that ensures chunks are at least minChunkSize bytes
* (except possibly the last chunk)
*/
export class MinimumChunkSizeStream extends Transform {
private buffer: Buffer;
private minChunkSize: number;
constructor(minChunkSize: number = 8192) {
super();
this.buffer = Buffer.alloc(0);
this.minChunkSize = minChunkSize;
}
_transform(
chunk: Buffer,
_encoding: BufferEncoding,
callback: TransformCallback,
): void {
// Add new data to our buffer
this.buffer = Buffer.concat([this.buffer, chunk]);
// While we have enough data, push complete chunks
while (this.buffer.length >= this.minChunkSize) {
// Use Buffer.subarray() instead of slice() - it's the modern approach
const chunkToSend = this.buffer.subarray(0, this.minChunkSize);
this.push(chunkToSend);
this.buffer = this.buffer.subarray(this.minChunkSize);
}
// We've processed all complete chunks, wait for more data
callback();
}
_flush(callback: TransformCallback): void {
// Push any remaining data as the final chunk (may be smaller than minChunkSize)
if (this.buffer.length > 0) {
this.push(this.buffer);
}
callback();
}
}
/**
* Wraps an IncomingMessage (Node.js server request) to ensure data is processed in chunks of at
* least minChunkSize bytes
* Usage: const chunkedReq = createChunkedRequestWrapper(req);
*/
export function createChunkedRequestWrapper(
request: IncomingMessage,
minChunkSize: number = 8192,
): Transform {
const chunker = new MinimumChunkSizeStream(minChunkSize);
// Pipe the request through our chunker
request.pipe(chunker);
// Handle error propagation
request.on('error', (err: Error) => {
chunker.emit('error', err);
});
return chunker;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment