Fast and low overhead web framework for Node.js with powerful plugin architecture
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Customizable content type parsing system for handling different request body formats.
Add, check, and remove custom content type parsers.
/**
* Add custom content type parser
* @param contentType - Content type string or string array
* @param options - Parser configuration options
* @param parser - Parser function
* @returns FastifyInstance for method chaining
*/
addContentTypeParser(
contentType: string | string[],
options: { parseAs?: 'string' | 'buffer'; bodyLimit?: number },
parser: (request: FastifyRequest, body: string | Buffer, done: (err: Error | null, parsed?: any) => void) => void
): FastifyInstance;
addContentTypeParser(
contentType: string | string[],
parser: (request: FastifyRequest, body: string | Buffer, done: (err: Error | null, parsed?: any) => void) => void
): FastifyInstance;
/**
* Check if content type parser exists
* @param contentType - Content type to check
* @returns Boolean indicating if parser exists
*/
hasContentTypeParser(contentType: string): boolean;
/**
* Remove content type parser
* @param contentType - Content type to remove
* @returns FastifyInstance for method chaining
*/
removeContentTypeParser(contentType: string): FastifyInstance;
/**
* Remove all content type parsers
* @returns FastifyInstance for method chaining
*/
removeAllContentTypeParsers(): FastifyInstance;Usage Examples:
// XML parser
fastify.addContentTypeParser('application/xml', { parseAs: 'string' }, (req, body, done) => {
try {
const parsed = xmlParser.parse(body);
done(null, parsed);
} catch (err) {
done(err);
}
});
// CSV parser
fastify.addContentTypeParser('text/csv', { parseAs: 'string' }, (req, body, done) => {
const rows = body.split('\n').map(row => row.split(','));
done(null, { rows });
});
// Custom binary parser
fastify.addContentTypeParser('application/octet-stream', { parseAs: 'buffer' }, (req, body, done) => {
// Process binary data
const processed = processBinary(body);
done(null, processed);
});Access and customize built-in parsers.
/**
* Get default JSON parser
* @returns Default JSON parsing function
*/
getDefaultJsonParser(): Function;
/**
* Default text parser for plain text content
* @param req - Fastify request object
* @param body - Request body as buffer
* @param done - Callback function
*/
defaultTextParser(req: FastifyRequest, body: Buffer, done: (err: Error | null, parsed?: string) => void): void;Usage Examples:
// Extend default JSON parser
const defaultJsonParser = fastify.getDefaultJsonParser();
fastify.addContentTypeParser('application/json', (req, body, done) => {
// Add custom processing before JSON parsing
if (body.length > 1024 * 1024) { // 1MB limit
done(new Error('JSON payload too large'));
return;
}
defaultJsonParser(req, body, done);
});
// Use default text parser with modifications
fastify.addContentTypeParser('text/plain', (req, body, done) => {
fastify.defaultTextParser(req, body, (err, text) => {
if (err) {
done(err);
return;
}
// Process text before setting as body
const processed = text.trim().toLowerCase();
done(null, processed);
});
});Configure parsing behavior and limits.
// Parser with custom body limit
fastify.addContentTypeParser('application/large-json', {
parseAs: 'string',
bodyLimit: 10 * 1024 * 1024 // 10MB limit
}, (req, body, done) => {
try {
const parsed = JSON.parse(body);
done(null, parsed);
} catch (err) {
done(new Error('Invalid JSON'));
}
});
// Multiple content types with same parser
fastify.addContentTypeParser(['text/yaml', 'application/yaml'], {
parseAs: 'string'
}, (req, body, done) => {
try {
const parsed = yaml.parse(body);
done(null, parsed);
} catch (err) {
done(new Error('Invalid YAML'));
}
});Complex parsing scenarios and use cases.
// Form data parser
fastify.addContentTypeParser('application/x-www-form-urlencoded',
{ parseAs: 'string' },
(req, body, done) => {
try {
const parsed = querystring.parse(body);
done(null, parsed);
} catch (err) {
done(err);
}
}
);
// Multipart form parser (requires multipart plugin)
fastify.addContentTypeParser('multipart/form-data', (req, done) => {
// Handle with multipart plugin
done();
});
// Protocol buffer parser
fastify.addContentTypeParser('application/x-protobuf', {
parseAs: 'buffer'
}, (req, body, done) => {
try {
const message = MyProtoMessage.decode(body);
done(null, message.toJSON());
} catch (err) {
done(new Error('Invalid Protocol Buffer'));
}
});
// Conditional parser based on headers
fastify.addContentTypeParser('application/json', (req, body, done) => {
const version = req.headers['api-version'];
if (version === '2.0') {
// Use v2 parsing logic
parseJsonV2(body, done);
} else {
// Use default parsing
JSON.parse(body.toString(), done);
}
});Handle parsing errors gracefully.
// Parser with comprehensive error handling
fastify.addContentTypeParser('application/custom', (req, body, done) => {
try {
if (!body || body.length === 0) {
done(new Error('Empty body'));
return;
}
if (body.length > req.server.initialConfig.bodyLimit) {
done(new Error('Body too large'));
return;
}
const parsed = customParser(body);
if (!isValidFormat(parsed)) {
done(new Error('Invalid format'));
return;
}
done(null, parsed);
} catch (err) {
req.log.error(err, 'Custom parser error');
done(new Error('Parsing failed'));
}
});
// Async parser using promises
fastify.addContentTypeParser('application/async', (req, body, done) => {
asyncParser(body)
.then(result => done(null, result))
.catch(err => done(err));
});Handle content type variations and charset.
// Handle charset in content type
fastify.addContentTypeParser('application/json', (req, body, done) => {
const contentType = req.headers['content-type'];
const charset = /charset=([^;]+)/.exec(contentType)?.[1] || 'utf8';
try {
const text = body.toString(charset);
const parsed = JSON.parse(text);
done(null, parsed);
} catch (err) {
done(err);
}
});
// Wildcard content type matching
fastify.addContentTypeParser('text/*', { parseAs: 'string' }, (req, body, done) => {
const contentType = req.headers['content-type'];
if (contentType.includes('text/csv')) {
// Handle CSV
parseCSV(body, done);
} else if (contentType.includes('text/xml')) {
// Handle XML
parseXML(body, done);
} else {
// Default text handling
done(null, body);
}
});Helper functions for common parsing tasks.
// Reusable parser utility
function createBufferParser(processor) {
return (req, body, done) => {
try {
const result = processor(body);
done(null, result);
} catch (err) {
done(err);
}
};
}
// Use utility
fastify.addContentTypeParser('image/jpeg', {
parseAs: 'buffer'
}, createBufferParser((buffer) => {
return {
size: buffer.length,
metadata: extractImageMetadata(buffer)
};
}));
// Stream parser for large payloads
fastify.addContentTypeParser('application/stream', (req, payload, done) => {
const chunks = [];
payload.on('data', chunk => chunks.push(chunk));
payload.on('end', () => {
const body = Buffer.concat(chunks);
const processed = processLargeData(body);
done(null, processed);
});
payload.on('error', done);
});