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);
});