CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fastify

Fast and low overhead web framework for Node.js with powerful plugin architecture

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

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

docs

content-parsing.md

decoration.md

error-handling.md

hooks.md

index.md

plugins.md

routing.md

schema.md

server-lifecycle.md

testing.md

tile.json