CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fastify--cors

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

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

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

docs

index.md

tile.json