/** * > [!NOTE] * > Install using `bunx shadcn@latest add @remix-utils/cors`. * * The CORS function let you implement CORS headers on your loaders and actions so you can use them as an API for other client-side applications. * * There are two main ways to use the `cors` function. * * 1. Use it on each loader/action where you want to enable it. * 2. Use it globally on entry.server handleRequest and handleDataRequest export. * * If you want to use it on every loader/action, you can do it like this: * * ```ts * import { cors } from "remix-utils/cors"; * * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * let response = json(data); * return await cors(request, response); * } * ``` * * You could also do the `json` and `cors` call in one line. * * ```ts * import { cors } from "remix-utils/cors"; * * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * return await cors(request, json(data)); * } * ``` * * And because `cors` mutates the response, you can also call it and later return. * * ```ts * import { cors } from "remix-utils/cors"; * * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * let response = json(data); * await cors(request, response); // this mutates the Response object * return response; // so you can return it here * } * ``` * * If you want to setup it globally once, you can do it like this in `entry.server` * * ```tsx * import { cors } from "remix-utils/cors"; * * const ABORT_DELAY = 5000; * * export default function handleRequest( * request: Request, * responseStatusCode: number, * responseHeaders: Headers, * remixContext: EntryContext, * ) { * let callbackName = isbot(request.headers.get("user-agent")) ? "onAllReady" : "onShellReady"; * * return new Promise((resolve, reject) => { * let didError = false; * * let { pipe, abort } = renderToPipeableStream( * , * { * [callbackName]: () => { * let body = new PassThrough(); * * responseHeaders.set("Content-Type", "text/html"); * * cors( * request, * new Response(body, { * headers: responseHeaders, * status: didError ? 500 : responseStatusCode, * }), * ).then((response) => { * resolve(response); * }); * * pipe(body); * }, * onShellError: (err: unknown) => { * reject(err); * }, * onError: (error: unknown) => { * didError = true; * * console.error(error); * }, * }, * ); * * setTimeout(abort, ABORT_DELAY); * }); * } * * export let handleDataRequest: HandleDataRequestFunction = async (response, { request }) => { * return await cors(request, response); * }; * ``` * * * Additionally, the `cors` function accepts a `options` object as a third optional argument. These are the options. * * - `origin`: Configures the **Access-Control-Allow-Origin** CORS header. * Possible values are: * - `true`: Enable CORS for any origin (same as "\*") * - `false`: Don't setup CORS * - `string`: Set to a specific origin, if set to "\*" it will allow any origin * - `RegExp`: Set to a RegExp to match against the origin * - `Array`: Set to an array of origins to match against the * string or RegExp * - `Function`: Set to a function that will be called with the request origin * and should return a boolean indicating if the origin is allowed or not. * The default value is `true`. * - `methods`: Configures the **Access-Control-Allow-Methods** CORS header. * The default value is `["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"]`. * - `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. * - `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. * - `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. * - `maxAge`: Configures the **Access-Control-Max-Age** CORS header. * * @author [Sergio Xalambrí](https://sergiodxa.com) * @module Server/CORS */ import type { Promisable } from "type-fest"; /** * @private You should not use this class directly, use the `cors` function instead, or the `createCorsMiddleware` */ export declare class CORS { private options; constructor(options: cors.Options); exec(request: Request, response: Response): Promise; private resolveOrigin; private configureMaxAge; private configureExposedHeaders; private configureAllowedHeaders; private configureCredentials; private configureMethods; private configureOrigin; private isOriginAllowed; private isString; private isNumber; } /** * Setup CORS for a giving Request and Response objects pair using the specified * options. * * The default options are: * - origin: true * - methods: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"] * - allowedHeaders: [] * - exposedHeaders: [] * - credentials: false * - maxAge: 0 * * @param request The Request object * @param response The Response object * @param options Optional configuration for CORS * @returns The same Response object mutated * * @example * // Create a response, then setup CORS for it * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * let response = json(data); * return await cors(request, response); * } * @example * // Create response and setup CORS in a single line * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * return await cors(request, json(data)); * } * @example * // Setup for any data request * export let handleDataRequest: HandleDataRequestFunction = async ( * response, * { request } * ) => { * return await cors(request, response); * }; * @example * // Pass a configuration object to setup CORS * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * return await cors(request, json(data), { * origin: "https://example.com" * }); * } * @example * // Mutate response and then return it * export async function loader({ request }: Route.LoaderArgs) { * let data = await getData(request); * let response = json(data); * await cors(request, response); // this mutates the Response object * return response; * } */ export declare function cors(request: Request, response: Response, options?: cors.Options): Promise; export declare namespace cors { type Origin = boolean | string | RegExp | Array; interface Options { /** * Configures the **Access-Control-Allow-Origin** CORS header. * * Possible values: * - true: Enable CORS for any origin (same as "*") * - false: Don't setup CORS * - string: Set to a specific origin, if set to "*" it will allow any origin * - RegExp: Set to a RegExp to match against the origin * - Array: Set to an array of origins to match against the * string or RegExp * - Function: Set to a function that will be called with the request origin * and should return a boolean indicating if the origin is allowed or not. * @default true */ origin?: Origin | ((origin: string) => Promisable); /** * Configures the **Access-Control-Allow-Methods** CORS header. * @default ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"] */ methods?: Array; /** * Configures the **Access-Control-Allow-Headers** CORS header. * @default [] */ allowedHeaders?: string[]; /** * Configures the **Access-Control-Expose-Headers** CORS header. * @default [] */ exposedHeaders?: string[]; /** * Configures the **Access-Control-Allow-Credentials** CORS header. * @default false */ credentials?: boolean; /** * Configures the **Access-Control-Max-Age** CORS header. * @default 0 */ maxAge?: number; } }