or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

content-parsing.mddecoration.mderror-handling.mdhooks.mdindex.mdplugins.mdrouting.mdschema.mdserver-lifecycle.mdtesting.md
tile.json

content-parsing.mddocs/

Content Type Parsing

Customizable content type parsing system for handling different request body formats.

Capabilities

Content Type Parser Management

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

Default Parsers

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

Parser Configuration Options

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

Advanced Parsing Examples

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

Parser Error Handling

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

Content Type Detection

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

Parser Utilities

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