or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-fastify--cors

Fastify plugin that provides Cross-Origin Resource Sharing (CORS) support with configurable origin validation, preflight handling, and header management.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@fastify/cors@11.1.x

To install, run

npx @tessl/cli install tessl/npm-fastify--cors@11.1.0

index.mddocs/

@fastify/cors

@fastify/cors is a Fastify plugin that provides Cross-Origin Resource Sharing (CORS) support for web applications. It enables secure cross-origin HTTP requests by managing CORS headers including Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers with configurable options for origin validation, credential handling, and preflight request processing.

Package Information

  • Package Name: @fastify/cors
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install @fastify/cors

Core Imports

import fastifyCors from '@fastify/cors';

For CommonJS:

const fastifyCors = require('@fastify/cors');

Named imports:

const { fastifyCors } = require('@fastify/cors');
// or
const cors = require('@fastify/cors');

TypeScript imports (types):

import type {
  FastifyCorsOptions,
  FastifyCorsOptionsDelegate,
  FastifyCorsOptionsDelegateCallback,
  FastifyCorsOptionsDelegatePromise,
  OriginFunction,
  AsyncOriginFunction,
  FastifyPluginOptionsDelegate
} from '@fastify/cors';

Basic Usage

import Fastify from 'fastify';
import cors from '@fastify/cors';

const fastify = Fastify();

// Register with default options (allows all origins)
await fastify.register(cors);

// Register with specific options
await fastify.register(cors, {
  origin: ['https://example.com', 'https://app.example.com'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  credentials: true
});

fastify.get('/', async (request, reply) => {
  return { hello: 'world' };
});

await fastify.listen({ port: 3000 });

Architecture

@fastify/cors is built around several key components:

  • Plugin Registration: Integrates with Fastify's plugin system using fastify-plugin
  • Hook Integration: Attaches to Fastify lifecycle hooks (default: onRequest) for request processing
  • Origin Validation: Supports static, dynamic, and function-based origin validation patterns
  • Preflight Handling: Automatic OPTIONS route registration for CORS preflight requests
  • Vary Header Management: Intelligent Vary header handling with caching for performance
  • Route-Level Control: Per-route CORS disabling via route configuration

Capabilities

Plugin Registration

Core plugin registration function that adds CORS support to a Fastify instance.

/**
 * Main CORS plugin for Fastify applications
 * @param {FastifyInstance} fastify - Fastify instance
 * @param {FastifyCorsOptions | FastifyCorsOptionsDelegate} options - CORS configuration options
 * @param {Function} next - Fastify callback function
 */
function fastifyCors(fastify, options, next);

/**
 * Alternative export patterns for different import styles
 */
const _fastifyCors; // Default export
const fastifyCors; // Named export
const default; // ES module compatibility

Static Configuration

Configure CORS with fixed options that apply to all requests.

interface FastifyCorsOptions {
  /** Configures Access-Control-Allow-Origin header */
  origin?: string | boolean | RegExp | string[] | RegExp[] | OriginFunction | AsyncOriginFunction;
  /** Configures Access-Control-Allow-Methods header */
  methods?: string | string[];
  /** Configures Access-Control-Allow-Headers header */
  allowedHeaders?: string | string[];
  /** Configures Access-Control-Expose-Headers header */
  exposedHeaders?: string | string[];
  /** Configures Access-Control-Allow-Credentials header */
  credentials?: boolean;
  /** Configures Access-Control-Max-Age header */
  maxAge?: number;
  /** Configures Cache-Control header for preflight responses */
  cacheControl?: number | string;
  /** Pass preflight response to route handler */
  preflightContinue?: boolean;
  /** Status code for successful OPTIONS requests */
  optionsSuccessStatus?: number;
  /** Enable/disable preflight handling */
  preflight?: boolean;
  /** Enforce strict preflight header requirements */
  strictPreflight?: boolean;
  /** Fastify lifecycle hook to use */
  hook?: FastifyCorsHook;
  /** Hide OPTIONS route from documentation */
  hideOptionsRoute?: boolean;
  /** Log level for internal OPTIONS route */
  logLevel?: LogLevel;
  /** Dynamic CORS configuration function */
  delegator?: FastifyCorsOptionsDelegate;
}

type FastifyCorsHook = 'onRequest' | 'preParsing' | 'preValidation' | 'preHandler' | 'preSerialization' | 'onSend';

Usage Examples:

// Allow all origins (default)
await fastify.register(cors);

// Allow specific origins
await fastify.register(cors, {
  origin: 'https://example.com'
});

// Allow multiple origins
await fastify.register(cors, {
  origin: ['https://example.com', 'https://app.example.com']
});

// Use RegExp for origin matching
await fastify.register(cors, {
  origin: /^https:\/\/.*\.example\.com$/
});

// Configure methods and headers
await fastify.register(cors, {
  origin: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
  credentials: true
});

Dynamic Origin Validation

Configure origin validation using functions for dynamic logic.

/**
 * Callback-based origin validation function
 * @param {string | undefined} origin - Request origin header value
 * @param {OriginCallback} callback - Callback function with signature (error, result)
 */
type OriginFunction = (origin: string | undefined, callback: OriginCallback) => void;

/**
 * Promise-based origin validation function
 * @param {string | undefined} origin - Request origin header value
 * @returns {Promise<ValueOrArray<OriginType>>} Promise resolving to origin validation result
 */
type AsyncOriginFunction = (origin: string | undefined) => Promise<ValueOrArray<OriginType>>;

/**
 * Origin validation callback signature
 * @param {Error | null} error - Error if validation failed
 * @param {ValueOrArray<OriginType>} result - Validation result
 */
type OriginCallback = (error: Error | null, result: ValueOrArray<OriginType>) => void;

type OriginType = string | boolean | RegExp;
type ValueOrArray<T> = T | T[];

Usage Examples:

// Callback-based validation
await fastify.register(cors, {
  origin: (origin, callback) => {
    const hostname = new URL(origin).hostname;
    if (hostname === 'localhost') {
      callback(null, true);
      return;
    }
    callback(new Error('Not allowed'), false);
  }
});

// Promise-based validation
await fastify.register(cors, {
  origin: async (origin) => {
    if (!origin) return false;
    const allowed = await checkOriginInDatabase(origin);
    return allowed;
  }
});

// Access Fastify instance via 'this'
await fastify.register(cors, {
  origin: function(origin, callback) {
    this.log.info(`Validating origin: ${origin}`);
    callback(null, origin === 'https://trusted.com');
  }
});

Dynamic Configuration

Configure CORS options dynamically per request using delegate functions.

/**
 * Callback-based delegate function for dynamic CORS options
 * @param {FastifyRequest} request - Fastify request object
 * @param {Function} callback - Callback with signature (error, options)
 */
interface FastifyCorsOptionsDelegateCallback {
  (req: FastifyRequest, cb: (error: Error | null, corsOptions?: FastifyCorsOptions) => void): void;
}

/**
 * Promise-based delegate function for dynamic CORS options
 * @param {FastifyRequest} request - Fastify request object
 * @returns {Promise<FastifyCorsOptions>} Promise resolving to CORS options
 */
interface FastifyCorsOptionsDelegatePromise {
  (req: FastifyRequest): Promise<FastifyCorsOptions>;
}

type FastifyCorsOptionsDelegate = FastifyCorsOptionsDelegateCallback | FastifyCorsOptionsDelegatePromise;

/**
 * Factory function returning delegate functions
 * @param {FastifyInstance} instance - Fastify instance
 * @returns {FastifyCorsOptionsDelegate} Delegate function
 */
type FastifyPluginOptionsDelegate<T = FastifyCorsOptionsDelegate> = (instance: FastifyInstance) => T;

Usage Examples:

// Register with callback delegate
await fastify.register(cors, (instance) => {
  return (req, callback) => {
    const corsOptions = {
      origin: true
    };
    
    // Disable CORS for localhost requests
    if (/^localhost$/m.test(req.headers.origin)) {
      corsOptions.origin = false;
    }
    
    callback(null, corsOptions);
  };
});

// Register with promise delegate
await fastify.register(cors, {
  delegator: async (req) => {
    const userAgent = req.headers['user-agent'];
    return {
      origin: userAgent.includes('MyApp') ? true : false,
      credentials: true
    };
  }
});

// Register with hook option and delegate
await fastify.register(cors, {
  hook: 'preHandler',
  delegator: (req, callback) => {
    callback(null, {
      origin: req.url.startsWith('/api/') ? '*' : false
    });
  }
});

Route-Level Control

Disable CORS for specific routes using route configuration.

/**
 * Route configuration option to disable CORS
 */
interface RouteOptions {
  config?: {
    cors?: boolean;
  };
}

Usage Examples:

// Enable CORS globally
await fastify.register(cors, { origin: '*' });

// Route with CORS enabled (default)
fastify.get('/api/public', async (request, reply) => {
  return { data: 'public' };
});

// Route with CORS disabled
fastify.get('/api/internal', { 
  config: { cors: false }
}, async (request, reply) => {
  return { data: 'internal' };
});

Hook Customization

Configure which Fastify lifecycle hook handles CORS processing.

type FastifyCorsHook = 
  | 'onRequest'
  | 'preParsing' 
  | 'preValidation'
  | 'preHandler'
  | 'preSerialization'
  | 'onSend';

Usage Examples:

// Use preHandler hook instead of default onRequest
await fastify.register(cors, {
  hook: 'preHandler',
  origin: 'https://example.com'
});

// Use onSend hook for late CORS header injection
await fastify.register(cors, {
  hook: 'onSend',
  origin: '*'
});

Preflight Configuration

Control CORS preflight request handling behavior.

interface PreflightOptions {
  /** Enable/disable preflight handling (default: true) */
  preflight?: boolean;
  /** Pass preflight response to route handler (default: false) */
  preflightContinue?: boolean;
  /** Status code for successful OPTIONS requests (default: 204) */
  optionsSuccessStatus?: number;
  /** Enforce strict preflight header requirements (default: true) */
  strictPreflight?: boolean;
  /** Hide OPTIONS route from documentation (default: true) */
  hideOptionsRoute?: boolean;
  /** Log level for internal OPTIONS route */
  logLevel?: LogLevel;
}

Usage Examples:

// Disable preflight handling
await fastify.register(cors, {
  origin: '*',
  preflight: false
});

// Custom preflight status for legacy browsers
await fastify.register(cors, {
  origin: '*',
  optionsSuccessStatus: 200
});

// Allow preflight to continue to route handler
await fastify.register(cors, {
  origin: '*',
  preflightContinue: true
});

// Disable strict preflight header validation
await fastify.register(cors, {
  origin: '*',
  strictPreflight: false
});

Request Decoration

The plugin decorates the Fastify request object with a property to track preflight handling state.

interface DecoratedFastifyRequest extends FastifyRequest {
  /** Indicates if CORS preflight is enabled for this request */
  corsPreflightEnabled: boolean;
}

Usage Example:

fastify.addHook('onRequest', async (request, reply) => {
  // Access the CORS preflight state
  console.log('Preflight enabled:', request.corsPreflightEnabled);
});

Types

/**
 * Main plugin callback type
 */
type FastifyCorsPlugin = FastifyPluginCallback<
  NonNullable<FastifyCorsOptions> | FastifyCorsOptionsDelegate
>;

/**
 * Generic value or array type
 */
type ValueOrArray<T> = T | ArrayOfValueOrArray<T>;

/**
 * Array interface for recursive value or array types
 */
interface ArrayOfValueOrArray<T> extends Array<ValueOrArray<T>> {}

Error Handling

The plugin handles various error conditions and validation failures:

// Invalid hook option
// Throws: TypeError('@fastify/cors: Invalid hook option provided.')

// Invalid origin option in delegator
// Throws: Error('Invalid CORS origin option')

// Invalid preflight request (when strictPreflight: true)
// Returns: 400 status with 'Invalid Preflight Request'

// Route not found for preflight when CORS disabled
// Calls: reply.callNotFound()

Error Handling Examples:

// Handle origin validation errors
await fastify.register(cors, {
  origin: (origin, callback) => {
    try {
      const url = new URL(origin);
      if (url.protocol !== 'https:') {
        callback(new Error('Only HTTPS origins allowed'), false);
        return;
      }
      callback(null, true);
    } catch (error) {
      callback(new Error('Invalid origin URL'), false);
    }
  }
});

// Handle delegator errors
await fastify.register(cors, {
  delegator: async (req) => {
    try {
      const config = await loadCorsConfig(req.headers.host);
      return config;
    } catch (error) {
      throw new Error('Failed to load CORS configuration');
    }
  }
});