### Basic Multipart Parsing Example Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Demonstrates the fundamental usage of Busboy for parsing multipart/form-data requests. Ensure you have the 'busboy' package installed and imported. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers }); bb.on('file', (name, file, info) => { console.log('file: name: ' + name + ', encoding: ' + info.encoding + ', mimeType: ' + info.mimeType); file.on('data', (data) => { console.log('file data: ' + data); }); file.on('end', () => { console.log('file end'); }); }); bb.on('field', (name, val, info) => { console.log('field: name: ' + name + ', value: ' + val); }); bb.on('data', (data) => { console.log('chunk: ' + data); }); bb.on('end', () => { console.log('end'); res.end(); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Example Decoding Process Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/decoder.md Demonstrates how the Decoder processes a URL-encoded string, converting percent-encoded characters and handling plus signs. ```javascript const decoder = new Decoder(); // Input: "user%3Djohn%2Bdoe" // Expected output: "user=john+doe" const result = decoder.write('user%3Djohn%2Bdoe'); // Step 1: Replace + with space (no + in this example) // Step 2: Decode %3D → = // Step 3: Decode %2B → + // Result: "user=john+doe" ``` -------------------------------- ### Custom File Detection Example Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Illustrates how to use a custom function to determine if a part should be treated as a file. This allows for more flexible file handling based on specific criteria. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers, isPartAFile: (fieldname, filename, encoding, mimetype) => { // Only treat files with a filename as actual files return Boolean(filename); } }); bb.on('file', (name, file, info) => { console.log('file: name: ' + name + ', encoding: ' + info.encoding + ', mimeType: ' + info.mimeType); file.on('data', (data) => { console.log('file data: ' + data); }); file.on('end', () => { console.log('file end'); }); }); bb.on('field', (name, val, info) => { console.log('field: name: ' + name + ', value: ' + val); }); bb.on('end', () => { console.log('end'); res.end(); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Multipart Form Content-Type Example Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md Example of a Content-Type header for multipart/form-data, which supports file uploads and per-part headers. ```text Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW ``` -------------------------------- ### Example BusboyHeaders with Content-Type Source: https://github.com/fastify/busboy/blob/main/_autodocs/types.md Demonstrates a valid BusboyHeaders object with only the required 'content-type' header. ```typescript // Valid const headers: BusboyHeaders = { 'content-type': 'multipart/form-data; boundary=---abc123' }; ``` -------------------------------- ### Save Uploaded File to Disk Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/file-stream.md This example shows how to pipe the incoming file stream directly to a file write stream on disk, effectively saving the uploaded file. ```javascript const fs = require('node:fs'); const path = require('node:path'); busboy.on('file', (fieldname, file, filename) => { const destination = path.join('/uploads', filename); file.pipe(fs.createWriteStream(destination)); }); ``` -------------------------------- ### Complete Busboy Configuration Example Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md This snippet demonstrates a comprehensive configuration for Busboy, setting options for stream buffering, character encoding, custom file detection logic, and various security limits for fields, files, and parts. ```javascript const Busboy = require('@fastify/busboy'); const busboy = new Busboy({ headers: req.headers, // Stream buffering highWaterMark: 64 * 1024, // 64 KB for Busboy stream fileHwm: 256 * 1024, // 256 KB for file streams // Encoding defCharset: 'utf-8', // Default to UTF-8 preservePath: false, // Security: no path traversal // Custom file detection isPartAFile: (fieldName, contentType, fileName) => { // Treat video/audio/images as files if (contentType && ( contentType.startsWith('video/') || contentType.startsWith('audio/') || contentType.startsWith('image/') )) { return true; } // Also files if they have a filename return fileName !== undefined; }, // Security limits limits: { fieldNameSize: 100, // Standard field names fieldSize: 1024 * 1024, // 1 MB per text field fields: 50, // Max 50 text fields fileSize: 100 * 1024 * 1024, // 100 MB per file files: 5, // Max 5 files parts: 100, // Max 100 total parts headerPairs: 2000, // Standard header pairs headerSize: 81920 // Standard header size } }); busboy.on('error', (err) => { console.error('Parse error:', err); }); busboy.on('partsLimit', () => { console.warn('Request has too many parts'); }); busboy.on('filesLimit', () => { console.warn('Too many files in request'); }); busboy.on('fieldsLimit', () => { console.warn('Too many fields in request'); }); ``` -------------------------------- ### Example BusboyHeaders with Additional Headers Source: https://github.com/fastify/busboy/blob/main/_autodocs/types.md Shows a valid BusboyHeaders object including the required 'content-type' and other common HTTP headers. ```typescript // Valid - with additional headers const headers: BusboyHeaders = { 'content-type': 'application/x-www-form-urlencoded', 'content-length': '1024', 'user-agent': 'curl/7.64.0' }; ``` -------------------------------- ### Basic File Reading and Size Calculation Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/file-stream.md This example demonstrates how to listen for the 'file' event, track the total size of received file data by summing chunk lengths, and log the final size upon stream completion. ```javascript busboy.on('file', (fieldname, file, filename) => { let size = 0; file.on('data', (chunk) => { size += chunk.length; }); file.on('end', () => { console.log(`${filename}: ${size} bytes received`); }); }); ``` -------------------------------- ### Manual Boundary Extraction with Dicer Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/dicer.md This example shows how to manually set the boundary for Dicer. It uses the `headerFirst: true` option and the `setBoundary` method, which is useful when the boundary is not in the initial headers. ```javascript const dicer = new Dicer({ headerFirst: true }); dicer.on('preamble', (preamble) => { // If using headerFirst, preamble contains pre-boundary data preamble.resume(); }); dicer.on('part', (part) => { part.on('header', (header) => { console.log(header); }); part.resume(); }); // Later, set boundary dicer.setBoundary('---boundary---'); ``` -------------------------------- ### Basic Multipart Parsing with Dicer Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/dicer.md This example demonstrates basic multipart parsing using the Dicer class. It sets up listeners for 'part', 'header', 'data', 'end', and 'finish' events to process incoming multipart data. ```javascript const { Dicer } = require('@fastify/busboy'); const dicer = new Dicer({ boundary: 'boundary123' }); dicer.on('part', (part) => { part.on('header', (header) => { console.log('Part headers:', header); }); part.on('data', (data) => { console.log('Part data:', data); }); part.on('end', () => { console.log('Part ended'); }); }); dicer.on('finish', () => { console.log('All parts parsed'); }); // Write multipart data dicer.write(multipartData); dicer.end(); ``` -------------------------------- ### Custom Charset Handling Example Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Demonstrates how to specify a custom default charset for parsing. This is useful when dealing with non-standard character encodings in your form data. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers, defCharset: 'iso-8859-1' // Specify custom default charset }); bb.on('file', (name, file, info) => { console.log('file: name: ' + name + ', encoding: ' + info.encoding + ', mimeType: ' + info.mimeType); file.on('data', (data) => { console.log('file data: ' + data); }); file.on('end', () => { console.log('file end'); }); }); bb.on('field', (name, val, info) => { console.log('field: name: ' + name + ', value: ' + val); }); bb.on('end', () => { console.log('end'); res.end(); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Track Upload Progress Using Bytes Read Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/file-stream.md This example calculates and logs the upload percentage based on the `bytesRead` property of the file stream relative to an expected total size. ```javascript busboy.on('file', (fieldname, file, filename) => { const totalSize = 1000000; // Expected size file.on('data', (chunk) => { const percentage = (file.bytesRead / totalSize * 100).toFixed(2); console.log(`${filename}: ${percentage}% uploaded`); }); }); ``` -------------------------------- ### Fastify Plugin for Multipart Handling Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md This example demonstrates how to use @fastify/busboy within a Fastify plugin to handle multipart requests. It iterates over parts, distinguishing between files and fields. ```javascript const Busboy = require('@fastify/busboy'); fastify.register(async (fastify) => { fastify.post('/upload', async (request, reply) => { const parts = request.multipart(); for await (const part of parts) { if (part.type === 'file') { // Handle file } else { // Handle field } } }); }); ``` -------------------------------- ### Handle File Size Limits and Truncation Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/file-stream.md This example listens for both the 'limit' event to detect size violations and the 'end' event to check the `truncated` property and `bytesRead` count if the file was truncated. ```javascript busboy.on('file', (fieldname, file, filename) => { file.on('limit', () => { console.log(`File ${filename} exceeded size limit`); }); file.on('end', () => { if (file.truncated) { console.log(`${filename} was truncated at ${file.bytesRead} bytes`); } }); }); ``` -------------------------------- ### Initialize Busboy with Manual Headers Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Manually construct the headers object for Busboy initialization, specifying the 'content-type' and boundary. Useful for testing or non-standard request setups. ```javascript const busboy = new Busboy({ headers: { 'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' } }); ``` -------------------------------- ### Basic File Stream Reading Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Shows how to read data from a file stream emitted by Busboy. This is the starting point for processing uploaded files. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers }); bb.on('file', (name, file, info) => { console.log('file: name: ' + name + ', encoding: ' + info.encoding + ', mimeType: ' + info.mimeType); file.on('data', (data) => { // Process file data chunks here console.log('Received ' + data.length + ' bytes'); }); file.on('end', () => { console.log('File upload finished.'); }); }); bb.on('end', () => { res.end('Upload complete!'); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Low-level Multipart Manipulation with Dicer Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/dicer.md This example illustrates low-level multipart manipulation, including piping part data to a file stream based on content type. It processes parts, checks content type, and either pipes data or resumes the part stream. ```javascript const { Dicer } = require('@fastify/busboy'); const { createWriteStream } = require('node:fs'); const dicer = new Dicer({ boundary: 'form-boundary' }); let partIndex = 0; dicer.on('part', (part) => { let contentType; part.on('header', (header) => { contentType = header['content-type']?.[0]; console.log(`Part ${partIndex}: ${contentType}`); }); if (contentType && contentType.startsWith('application/')) { part.pipe(createWriteStream(`part-${partIndex}.bin`)); } else { part.resume(); } part.on('end', () => { partIndex++; }); }); ``` -------------------------------- ### File Organization Structure Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md Overview of the directory structure for the Fastify Busboy project, indicating the location of API reference files, type definitions, configuration guides, and the main README. ```text /api-reference/ ├── busboy.md # Main Busboy class ├── file-stream.md # BusboyFileStream type ├── dicer.md # Dicer low-level parser ├── multipart-parser.md # Multipart form parser ├── urlencoded-parser.md # URL-encoded parser ├── decoder.md # URL decoder utility └── utilities.md # Helper functions /types.md # All type definitions /configuration.md # Configuration guide /errors.md # Error reference /README.md # This file ``` -------------------------------- ### URL-Encoded Parser Example Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Demonstrates the usage of the URL-encoded parser, which is designed to handle data submitted with the 'application/x-www-form-urlencoded' Content-Type. This parser is typically used internally by Busboy but can be used independently. ```javascript const UrlEncodedParser = require('busboy/lib/parsers/urlencoded'); const assert = require('assert'); // Example POST request body const body = 'key1=value1&key2=value2&key3=value%20with%20spaces'; const parser = new UrlEncodedParser(); parser.on('field', (key, value, info) => { console.log(`Field: ${key} = ${value}`); // Example assertions if (key === 'key1') assert.strictEqual(value, 'value1'); if (key === 'key2') assert.strictEqual(value, 'value2'); if (key === 'key3') assert.strictEqual(value, 'value with spaces'); }); parser.on('finish', () => { console.log('URL-encoded parsing finished.'); }); parser.write(body); parser.end(); ``` -------------------------------- ### Validate File Extension Before Saving Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/file-stream.md This example demonstrates how to validate the file extension against an allowed list. If the extension is not permitted, the file stream is resumed to discard its data; otherwise, it's piped to a write stream. ```javascript busboy.on('file', (fieldname, file, filename) => { const ext = path.extname(filename); const allowedExts = ['.jpg', '.png', '.gif']; if (!allowedExts.includes(ext)) { file.resume(); // Skip this file return; } file.pipe(fs.createWriteStream(`/uploads/${filename}`)); }); ``` -------------------------------- ### Custom File Detection Logic Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/busboy.md Use the 'isPartAFile' option to define custom logic for determining if a part of the multipart request should be treated as a file. This example treats all parts with a 'image/*' content type as files. ```javascript const busboy = new Busboy({ headers: req.headers, isPartAFile: (fieldName, contentType, fileName) => { // Treat all image/* as files, everything else as fields return contentType && contentType.startsWith('image/'); } }); ``` -------------------------------- ### Parse Multipart Form Data with Default Options Source: https://github.com/fastify/busboy/blob/main/README.md Handles POST requests to parse multipart form data. Logs file and field information. Requires Node.js http server setup. ```javascript const http = require('node:http'); const { inspect } = require('node:util'); const Busboy = require('@fastify/busboy'); http.createServer((req, res) => { if (req.method === 'POST') { const busboy = new Busboy({ headers: req.headers }); busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { console.log(`File [${fieldname}]: filename: ${filename}, encoding: ${encoding}, mimetype: ${mimetype}`); file.on('data', data => { console.log(`File [${fieldname}] got ${data.length} bytes`); }); file.on('end', () => { console.log(`File [${fieldname}] Finished`); }); }); busboy.on('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => { console.log(`Field [${fieldname}]: value: ${inspect(val)}`); }); busboy.on('finish', () => { console.log('Done parsing form!'); res.writeHead(303, { Connection: 'close', Location: '/' }); res.end(); }); req.pipe(busboy); } else if (req.method === 'GET') { res.writeHead(200, { Connection: 'close' }); res.end(`
`); } }).listen(8000, () => { console.log('Listening for requests'); }); // Example output, using http://nodejs.org/images/ryan-speaker.jpg as the file: // // Listening for requests // File [filefield]: filename: ryan-speaker.jpg, encoding: binary // File [filefield] got 11971 bytes // Field [textfield]: value: 'testing! :-)' // File [filefield] Finished // Done parsing form! ``` -------------------------------- ### URL-Encoded Form Content-Type Examples Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md Examples of Content-Type headers for URL-encoded forms, which only support text fields and do not support file uploads. ```text Content-Type: application/x-www-form-urlencoded ``` ```text Content-Type: application/x-www-form-urlencoded; charset=utf-8 ``` -------------------------------- ### TypeScript Configuration and File Handling Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md Demonstrates how to configure Busboy with TypeScript, including setting limits and type-safe event handling for uploaded files. Ensure you import the necessary types from '@fastify/busboy'. ```typescript import Busboy, { BusboyConfig, BusboyInstance } from '@fastify/busboy'; const config: BusboyConfig = { headers: req.headers, limits: { fileSize: 10 * 1024 * 1024, files: 5 } }; const busboy: BusboyInstance = new Busboy(config); busboy.on('file', (fieldname: string, stream, filename: string) => { // Type-safe event handling }); ``` -------------------------------- ### Instantiating Busboy Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/busboy.md Demonstrates how to create a new Busboy instance with the required headers option. Busboy can be instantiated with or without the 'new' keyword. ```javascript const busboy = new Busboy({ headers: req.headers }); const busboy = Busboy({ headers: req.headers }); ``` -------------------------------- ### Get Basename from Path Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Illustrates the `basename` utility function, which extracts the filename from a given path. This is commonly used when processing uploaded file information. ```javascript const { basename } = require('busboy/lib/utilities'); const path1 = '/path/to/some/file.txt'; const path2 = 'C:\\Users\\Documents\\report.docx'; const path3 = 'just_a_filename.jpg'; const path4 = '/path/with/trailing/slash/'; console.log(`Basename of '${path1}': ${basename(path1)}`); // Expected: file.txt console.log(`Basename of '${path2}': ${basename(path2)}`); // Expected: report.docx console.log(`Basename of '${path3}': ${basename(path3)}`); // Expected: just_a_filename.jpg console.log(`Basename of '${path4}': ${basename(path4)}`); // Expected: '' (or 'slash' depending on implementation details, usually empty for trailing slash) ``` -------------------------------- ### Busboy Constructor Usage Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md Demonstrates instantiating the Busboy class. It can be used with or without the 'new' keyword. ```javascript const Busboy = require('@fastify/busboy'); // Constructor const busboy = new Busboy({ headers: req.headers }); const busboy = Busboy({ headers: req.headers }); // Also works without 'new' ``` -------------------------------- ### Instantiating Busboy Constructor Source: https://github.com/fastify/busboy/blob/main/_autodocs/types.md Demonstrates how to instantiate the Busboy constructor using both direct call and the 'new' keyword, as defined by the BusboyConstructor type. ```typescript import Busboy, { BusboyConstructor } from '@fastify/busboy'; const ctor: BusboyConstructor = Busboy; // Both are valid: const b1 = ctor({ headers: req.headers }); const b2 = new ctor({ headers: req.headers }); ``` -------------------------------- ### Instantiate Decoder Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/decoder.md Creates a new Decoder instance. This is the initial step before using its decoding methods. ```javascript const Decoder = require('./lib/utils/Decoder'); const decoder = new Decoder(); ``` -------------------------------- ### Discard Uploaded File Data Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Demonstrates how to discard the data of an uploaded file, for example, if validation fails or the file is not needed. This prevents unnecessary disk writes or memory usage. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers }); bb.on('file', (name, file, info) => { // Decide whether to keep or discard the file based on some logic const shouldDiscard = true; // Example: always discard for this demo if (shouldDiscard) { console.log(`Discarding file: ${name}`); // To discard, simply do nothing with the file stream. // You might want to consume it to free up resources if necessary, // but often just ignoring it is sufficient. file.resume(); // Consume the stream to free resources } else { // Process the file normally, e.g., save to disk const saveTo = path.join(__dirname, 'uploads', name); file.pipe(fs.createWriteStream(saveTo)); } }); bb.on('end', () => { res.end('Upload processing finished.'); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Custom isPartAFile: Video and Audio Files Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Configure Busboy to treat parts with 'video/*' or 'audio/*' content types as files. This is useful for handling media uploads. ```javascript // Treat video/* and audio/* as files const busboy = new Busboy({ headers: req.headers, isPartAFile: (fieldName, contentType, fileName) => { return contentType && ( contentType.startsWith('video/') || contentType.startsWith('audio/') ); } }); ``` -------------------------------- ### Invalid Busboy Limit Values Source: https://github.com/fastify/busboy/blob/main/_autodocs/errors.md These examples demonstrate how providing non-numeric values (string, NaN, null) for Busboy limits will trigger a TypeError. This error is intentional to prevent silent fallback to defaults. ```javascript // ❌ All throw const busboy = new Busboy({ headers: { 'content-type': 'multipart/form-data; boundary=abc' }, limits: { fileSize: 'invalid' } // String instead of number }); ``` ```javascript const busboy = new Busboy({ headers: { 'content-type': 'multipart/form-data; boundary=abc' }, limits: { files: NaN } // NaN is not a valid number }); ``` ```javascript const busboy = new Busboy({ headers: { 'content-type': 'multipart/form-data; boundary=abc' }, limits: { fields: null } // null is not a number }); ``` ```javascript // ✅ These work const busboy = new Busboy({ headers: { 'content-type': 'multipart/form-data; boundary=abc' }, limits: { fileSize: 1024 * 1024 } }); ``` ```javascript const busboy = new Busboy({ headers: { 'content-type': 'multipart/form-data; boundary=abc' }, limits: { files: 5 } }); ``` -------------------------------- ### Setting Default Character Set Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/busboy.md Configure Busboy to use a specific default character set for parsing field values when the charset is not explicitly provided in the request headers. This example sets the default to 'latin1'. ```javascript const busboy = new Busboy({ headers: req.headers, defCharset: 'latin1' // Use latin1 as default if charset not specified }); ``` -------------------------------- ### Handle File Size Limits for Uploads Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Shows how to handle the 'limit' event on a file stream to gracefully manage uploads that exceed the configured file size limit. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers, limits: { fileSize: 1024 * 1024 // 1MB file size limit } }); bb.on('file', (name, file, info) => { file.on('data', (data) => { // Process file data chunks }); file.on('end', () => { console.log('File upload finished.'); }); file.on('limit', () => { console.log('File size limit exceeded!'); // Optionally, you can destroy the stream to stop further processing file.destroy(); }); }); bb.on('end', () => { res.end('Upload processing finished.'); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Initialize Decoder Instance Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/urlencoded-parser.md Instantiates a Decoder for processing percent-encoded sequences. ```javascript this.decoder = new Decoder() ``` -------------------------------- ### Handle Uploaded File Stream Source: https://github.com/fastify/busboy/blob/main/_autodocs/types.md Example of how to access file stream properties like `truncated` and `bytesRead` within the 'file' event handler. Use this to check for file truncation and log bytes read. ```typescript busboy.on('file', (fieldname, stream: BusboyFileStream, filename) => { if (stream.truncated) { console.log('File will be truncated'); } console.log(`Bytes: ${stream.bytesRead}`); }); ``` -------------------------------- ### Configure Busboy for High Performance Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Optimize performance by using larger buffer sizes for Busboy and files. Adjust limits for larger file sizes and a higher number of parts. ```javascript const busboy = new Busboy({ headers: req.headers, highWaterMark: 256 * 1024, // Large Busboy buffer fileHwm: 512 * 1024, // Large file buffer limits: { fileSize: 500 * 1024 * 1024, // 500 MB per file files: 100, parts: 500 } }); ``` -------------------------------- ### Handle Busboy Limits Source: https://github.com/fastify/busboy/blob/main/_autodocs/errors.md Configure and handle limits for files, fields, and parts using Busboy's options and corresponding events. This snippet demonstrates setting file size, file count, and field count limits, and responding to limit breaches. ```javascript const busboy = new Busboy({ headers: req.headers, limits: { fileSize: 10 * 1024 * 1024, // 10 MB per file files: 5, fields: 20 } }); busboy.on('filesLimit', () => { res.status(413).json({ error: 'Too many files' }); }); busboy.on('fieldsLimit', () => { res.status(413).json({ error: 'Too many fields' }); }); busboy.on('partsLimit', () => { res.status(413).json({ error: 'Request too large' }); }); busboy.on('file', (fieldname, file) => { file.on('limit', () => { console.warn(`File ${fieldname} truncated`); }); }); ``` -------------------------------- ### Multipart Parsing with Size Limits Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md Shows how to configure Busboy to enforce limits on file size and the number of files. This is crucial for preventing denial-of-service attacks. ```javascript const Busboy = require('busboy'); const http = require('http'); http.createServer((req, res) => { if (req.method === 'POST') { const bb = Busboy({ headers: req.headers, limits: { fileSize: 2 * 1024 * 1024, // 2MB file limit files: 5 // 5 file limit } }); bb.on('file', (name, file, info) => { console.log('file: name: ' + name + ', encoding: ' + info.encoding + ', mimeType: ' + info.mimeType); file.on('data', (data) => { console.log('file data: ' + data); }); file.on('end', () => { console.log('file end'); }); }); bb.on('field', (name, val, info) => { console.log('field: name: ' + name + ', value: ' + val); }); bb.on('partsLimit', () => { console.log('parts limit reached'); }); bb.on('filesLimit', () => { console.log('files limit reached'); }); bb.on('fieldsLimit', () => { console.log('fields limit reached'); }); bb.on('data', (data) => { console.log('chunk: ' + data); }); bb.on('end', () => { console.log('end'); res.end(); }); req.pipe(bb); } else { res.writeHead(404); res.end(); } }).listen(1337, () => { console.log('listening on 1337'); }); ``` -------------------------------- ### Handle 'file' Event Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/busboy.md Listen for the 'file' event to process uploaded files. Ensure the stream is handled to trigger the 'finish' event. ```javascript busboy.on('file', (fieldname, stream, filename, encoding, mimetype) => { // fieldname: string - name of the form field // stream: ReadableStream (BusboyFileStream) - file content stream // filename: string - original filename from upload // encoding: string - Content-Transfer-Encoding value // mimetype: string - Content-Type value }); ``` -------------------------------- ### Custom isPartAFile: Image Files Only Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Configure Busboy to treat only parts with 'image/*' content types as files. Other parts will be treated as fields. ```javascript // Only treat image/* as files, everything else as fields const busboy = new Busboy({ headers: req.headers, isPartAFile: (fieldName, contentType, fileName) => { return contentType && contentType.startsWith('image/'); } }); ``` -------------------------------- ### Multipart Parsing with Size and File Limits Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/busboy.md Configure Busboy with limits on file size, the number of files, and the number of fields to prevent excessive resource consumption. Event listeners for 'filesLimit' and 'fieldsLimit' are included to handle violations. ```javascript const busboy = new Busboy({ headers: req.headers, limits: { fileSize: 10 * 1024 * 1024, // 10 MiB max per file files: 5, // Max 5 files fields: 20, // Max 20 fields } }); busboy.on('filesLimit', () => { console.log('Too many files'); }); busboy.on('fieldsLimit', () => { console.log('Too many fields'); }); ``` -------------------------------- ### Handle Zero Byte in Encoding Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/decoder.md Demonstrates that the Decoder correctly handles percent-encoded zero bytes, including them as null characters in the output. ```javascript const decoder = new Decoder(); const result = decoder.write('%00'); // Includes null character in output ``` -------------------------------- ### Busboy Constructor and Events Source: https://github.com/fastify/busboy/blob/main/_autodocs/INDEX.md This section details the Busboy constructor, its parameters, and the events it emits, such as 'file', 'field', 'finish', and 'error'. It's the primary interface for parsing incoming request data. ```APIDOC ## Busboy Constructor and Events ### Description Provides the main interface for parsing multipart/form-data and urlencoded requests. It accepts a configuration object and emits events for files, fields, and completion. ### Method new Busboy(options) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Configuration Options - **options** (BusboyConfig) - Required - Configuration object for Busboy. - **headers** (object) - Required - The request headers. - **highWaterMark** (number) - Optional - The highWaterMark for the internal streams. - **fileHwm** (number) - Optional - The highWaterMark for file streams. - **defCharset** (string) - Optional - Default charset to use if not specified. - **preservePath** (boolean) - Optional - Whether to preserve the full path of uploaded files. - **isPartAFile** (function) - Optional - Custom function to determine if a part is a file. - **limits** (BusboyLimits) - Optional - Limits for parsing. ### Events - **file** (fieldname, file, filename, encoding, mimetype) - Emitted for each file part. - **field** (fieldname, value,fieldnameTruncated, valueTruncated) - Emitted for each non-file field. - **finish** () - Emitted when parsing is complete. - **error** (error) - Emitted when an error occurs. - **partsLimit** () - Emitted when the parts limit is reached. - **filesLimit** () - Emitted when the files limit is reached. - **fieldsLimit** () - Emitted when the fields limit is reached. ### Request Example ```javascript const busboy = new Busboy({ headers: req.headers }); busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { console.log('File:', fieldname, filename); file.pipe(fs.createWriteStream('/path/to/upload/' + filename)); }); busboy.on('field', (fieldname, value) => { console.log('Field:', fieldname, value); }); busboy.on('finish', () => { console.log('Done parsing'); res.end(); }); req.pipe(busboy); ``` ### Response #### Success Response (N/A - Event-driven) Busboy is event-driven and does not return a direct response. Events are emitted as data is parsed. #### Response Example N/A ``` -------------------------------- ### Configure files Limit and Handle Event Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Set the maximum number of file uploads to accept. Only applies to multipart forms. When exceeded, the 'filesLimit' event is emitted. The default is Infinity. ```javascript const busboy = new Busboy({ headers: req.headers, limits: { files: 10 // Max 10 files } }); busboy.on('filesLimit', () => { console.log('Too many files'); }); ``` -------------------------------- ### Initialize Busboy with Request Headers Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Instantiate Busboy using the 'content-type' header from an incoming request. This is the standard way to initialize Busboy for parsing. ```javascript const busboy = new Busboy({ headers: req.headers }); ``` -------------------------------- ### Busboy Constructor Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/busboy.md Instantiates a new Busboy parser instance. It can be used with or without the `new` keyword. The constructor takes a configuration object with options for parsing form data. ```APIDOC ## Busboy Constructor ### Description Instantiates a new Busboy parser instance. It can be used with or without the `new` keyword. The constructor takes a configuration object with options for parsing form data. ### Signature ```javascript new Busboy(options: BusboyConfig): BusboyInstance ``` ### Parameters #### options (object) - Required Configuration object containing form parsing options. - **headers** (object) - Required - HTTP headers object from the incoming request (must include `content-type`). - **highWaterMark** (number) - Optional - highWaterMark for the Busboy instance. - **fileHwm** (number) - Optional - highWaterMark for file streams. - **defCharset** (string) - Optional - Default character set when none is defined in headers. Defaults to 'utf8'. - **preservePath** (boolean) - Optional - Whether to preserve full paths in multipart filename fields. Defaults to false. - **isPartAFile** (function) - Optional - Custom function to determine if a part should be treated as a file. - **limits** (object) - Optional - Object containing various size and count limits. ### BusboyConfig Interface ```typescript interface BusboyConfig { headers: BusboyHeaders; highWaterMark?: number; fileHwm?: number; defCharset?: string; preservePath?: boolean; isPartAFile?: (fieldName: string | undefined, contentType: string | undefined, fileName: string | undefined) => boolean; limits?: BusboyLimits; } ``` ### BusboyHeaders Type ```typescript type BusboyHeaders = { 'content-type': string } & http.IncomingHttpHeaders ``` ### isPartAFile Function Signature ```javascript (fieldName: string | undefined, contentType: string | undefined, fileName: string | undefined) => boolean ``` ### BusboyLimits Interface ```typescript interface BusboyLimits { fieldNameSize?: number; // Default: 100 bytes fieldSize?: number; // Default: 1 MiB (1048576 bytes) fields?: number; // Default: Infinity fileSize?: number; // Default: Infinity files?: number; // Default: Infinity parts?: number; // Default: Infinity headerPairs?: number; // Default: 2000 (multipart only) headerSize?: number; // Default: 81920 bytes (multipart only) } ``` ``` -------------------------------- ### Decoder Constructor Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/decoder.md Creates a new Decoder instance for decoding URL-encoded strings. It is not directly exported but is documented for completeness. ```APIDOC ## Decoder() ### Description Creates a new Decoder instance for decoding URL-encoded strings. ### Parameters None ### Returns Decoder instance with `write()` and `reset()` methods. ### Example ```javascript const Decoder = require('./lib/utils/Decoder'); const decoder = new Decoder(); ``` ``` -------------------------------- ### Configure parts Limit and Handle Event Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Set the maximum total number of parts (fields + files combined). Only applies to multipart forms. When exceeded, the 'partsLimit' event is emitted. The default is Infinity. ```javascript const busboy = new Busboy({ headers: req.headers, limits: { parts: 100 // Max 100 total parts } }); busboy.on('partsLimit', () => { console.log('Request has too many parts'); }); ``` -------------------------------- ### Busboy Constructor Source: https://github.com/fastify/busboy/blob/main/README.md Creates a new Busboy instance to parse incoming multipart/form-data. It requires the HTTP request headers to be passed in the configuration. ```APIDOC ## Busboy Constructor ### Description Creates and returns a new Busboy instance. ### Method (constructor) ### Parameters #### Config Object - **headers** (object) - Required - The HTTP headers of the incoming request. - **autoDestroy** (boolean) - Optional - Whether this stream should automatically call .destroy() on itself after ending. (Default: false). - **highWaterMark** (integer) - Optional - highWaterMark to use for this Busboy instance (Default: WritableStream default). - **fileHwm** (integer) - Optional - highWaterMark to use for file streams (Default: ReadableStream default). - **defCharset** (string) - Optional - Default character set to use when one isn't defined (Default: 'utf8'). - **preservePath** (boolean) - Optional - If paths in the multipart 'filename' field shall be preserved. (Default: false). ``` -------------------------------- ### Configure Busboy for Legacy Systems Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Ensure compatibility with legacy systems by specifying legacy character encoding and allowing larger field names and sizes. Enable path preservation if needed. ```javascript const busboy = new Busboy({ headers: req.headers, defCharset: 'latin1', // Legacy encoding limits: { fieldNameSize: 200, // Larger field names fieldSize: 10 * 1024 * 1024 // 10 MB per field }, preservePath: true // Keep paths as-is }); ``` -------------------------------- ### Configure Busboy for Security Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Set strict limits on field size, file size, number of files, and fields to prevent abuse. Disable path traversal by setting preservePath to false. ```javascript const busboy = new Busboy({ headers: req.headers, limits: { fieldSize: 1024 * 100, // Small limit for text fields fileSize: 10 * 1024 * 1024, // 10 MB max per file files: 5, // Few files allowed fields: 20 // Few fields allowed }, preservePath: false // Prevent path traversal }); ``` -------------------------------- ### Parsing with Percent-Encoding Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/urlencoded-parser.md Demonstrates parsing of URL-encoded strings containing percent-encoded characters, such as spaces. ```text message=Hello%20World&plus%2Btest=value ``` -------------------------------- ### Listen for File Data Chunks Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/file-stream.md Use the 'data' event to process incoming chunks of file data as they are read from the stream. ```javascript file.on('data', (chunk: Buffer) => { // Process file chunk }); ``` -------------------------------- ### Configure fileSize Limit and Handle Event Source: https://github.com/fastify/busboy/blob/main/_autodocs/configuration.md Set the maximum size for individual uploaded files. Only applies to multipart forms. When exceeded, the file stream's 'truncated' property is set to true and a 'limit' event is emitted on the stream. The default is Infinity. ```javascript const busboy = new Busboy({ headers: req.headers, limits: { fileSize: 100 * 1024 * 1024 // 100 MiB per file } }); busboy.on('file', (fieldname, file) => { file.on('limit', () => { console.log(`${fieldname} exceeds limit`); }); }); ``` -------------------------------- ### TypeScript Named Exports Source: https://github.com/fastify/busboy/blob/main/_autodocs/README.md Shows how to import specific types and the Busboy constructor when using TypeScript. ```typescript import Busboy, { BusboyConfig, BusboyInstance, BusboyFileStream, BusboyEvents, Dicer } from '@fastify/busboy'; ``` -------------------------------- ### Dicer 'preamble' Event Source: https://github.com/fastify/busboy/blob/main/_autodocs/api-reference/dicer.md Emitted if `headerFirst` is true, containing data before the first boundary. ```javascript dicer.on('preamble', (stream: PartStream) => { // Preamble content stream }); ```