Dead-simple CORS handling for any itty-router API (test with Cloudflare Workers, but works anywhere)!

Overview

itty-cors

Version Bundle Size Build Status Coverage Status NPM Weekly Downloads Open Issues

Discord GitHub Repo stars Twitter

Simple CORS-handling for any itty-router API. Designed on Cloudflare Workers, but works anywhere.

Features

  • Tiny. Currently ~600 bytes, with zero-dependencies.
  • Fully Typed/TypeScript
  • Granular control over allowed methods, origins, etc.
  • handles OPTIONS preflight requests
  • response processor (corsify) can be used per-response, or globally downstream

!! Breaking API Changes (pre v1.x)!!

You're using an early-access package. Until itty-cors hits a stable v1.0 release, API changes will be broadcasted as minor version bumps.

  • v0.3.0 - preflight now MUST be included on the .all channel (all methods), rather than .options alone, to allow for origin-checking.
  • v0.2.0 - allowOrigins: string has been replaced with origins: string[] to accept an array of origins, and multi-origin support is now correctly implemented.
    // previously
    const { preflight, corsify } = createCors({ allowOrigin: '*' })
    
    // now
    const { preflight, corsify } = createCors({ origins: ['*'] })

Simple Usage

import { Router } from 'itty-router'
import { error, json, missing } from 'itty-router-extras'
import { createCors } from 'itty-cors'

// create CORS handlers
const { preflight, corsify } = createCors()

const router = Router()

// register v2 API plus all routes
router
  .all('*', preflight)                                  // handle CORS preflight/OPTIONS requests
  .get('/version', () => json({ version: '0.1.0' }))    // GET release version
  .get('/stuff', () => json(['foo', 'bar', 'baz']))     // GET some other random stuff
  .all('*', () => missing('Are you sure about that?'))  // 404 for all else

// CF ES6 module syntax
export default {
  fetch: (...args) => router
                        .handle(...args)
                        .catch(err => error(500, err.stack))
                        .then(corsify) // cors should be applied to error responses as well
}

CORS enabled on a single route (and advanced options)

import { Router } from 'itty-router'
import { error, json, missing } from 'itty-router-extras'
import { createCors } from 'itty-cors'

// create CORS handlers
const { preflight, corsify } = createCors({
  methods: ['GET', 'POST', 'DELETE'], // GET is included by default... omit this if only using GET
  origins: ['*'],                     // defaults to allow all (most common).  Restrict if needed.
  maxAge: 3600,
  headers: {
    'my-custom-header': 'will be injected with each CORS-enabled response',
  },
})

const router = Router()

// register v2 API plus all routes
router
  .all('*', preflight)                                  // handle CORS preflight/OPTIONS requests
  .get('/version', () => corsify(json({ version: '0.1.0' })))  // GET release version (CORS-enabled)
  .get('/stuff', () => json(['foo', 'bar', 'baz']))     // GET some other random stuff (no CORS allowed)
  .all('*', () => missing('Are you sure about that?'))  // 404 for all else

// CF ES6 module syntax
export default {
  fetch: (...args) => router
                        .handle(...args)
                        .catch(err => error(500, err.stack))
}

API

createCors(options?) => { preflight: function, corsify: function }

Returns an object with two properties, preflight (a preflight OPTIONS middleware), and corsify (a response-handling function).

Option Type(s) Default Description
origins string[] ['*'] By default, all origins are allowed (most common). Modify this to restrict to specific origins.
maxAge number 3600 Set the expiry of responses
methods string[] ['GET'] Define which methods are allowed. OPTIONS will be automatically added.
headers object {} Add any custom headers to be injected with CORS-enabled responses.

preflight(request: Request) => Response

This is the preflight middleware to be injected upstream on options requests.

router.options('*', preflight) // that's it!

corsify(response: Response) => Response

This wrapper injects CORS headers into a response, if not already set (upstream). Use this at the end of the router.handle Promise chain to CORS-enable all responses/the entire API, or wrap any response generator (e.g. json() from itty-router-extras) to make a single CORS-enabled response.

You might also like...

Lightweight universal Cloudflare API client library for Node.js, Browser, and CF Workers

Cloudflare API Client Lightweight universal HTTP client for Cloudflare API based on Fetch API that works in Node.js, browser, and CF Workers environme

Nov 13, 2022

A URL shortener that runs on Cloudflare Workers

ITP Works A URL shortener that runs on Cloudflare Workers. It stores the rules in Cloudflare KV storage and sends a 301 redirect when a matched pathna

Mar 4, 2022

Starting template for building a Remix site with CloudFlare Workers (ES Modules Syntax)

Starting template for building a Remix site with CloudFlare Workers (ES Modules Syntax)

May 20, 2022

Remix + Cloudflare Workers + DO + Turborepo

Remix + Cloudflare Workers + DO + Turborepo A starter to get you up and going with Remix on Cloudflare with all the latest and greatest. What's inside

Dec 12, 2022

Remix + Cloudflare Workers + Wrangler2 + Tailwind + ESLint + Prettier + Vitest + Playwright

Welcome to Remix! Remix Docs Development You will be running two processes during development: The Miniflare server (miniflare is a local environment

Dec 19, 2022

Server-side rendering blog runs on Cloudflare workers

Serverside rendered blog I have tried something completely against to current web trends. What are these? I am using the React as backend framework wi

Jun 24, 2022

A collection of useful tools for building web apps on Cloudflare Workers.

Keywork is a batteries-included, magic-free, library for building web apps on Cloudflare Workers. Features 💪 Written in TypeScript 📚 Modules Support

Dec 22, 2022

Abusing Cloudflare Workers to establish persistence and exfiltrate sensitive data at the edge.

Abusing Cloudflare Workers This repository contains companion code for the blog post MITM at the Edge: Abusing Cloudflare Workers. malicious-worker/ c

Sep 16, 2022

A starter template for Remix + Cloudflare Workers + DO + KV + Turborepo

Remix + Cloudflare Workers starter with Turborepo 🚀 Starter to get going with Remix and Cloudflare Workers. This template is based on the starter cre

Jan 2, 2023
Comments
  • Support missing response

    Support missing response

    The corsify function throws a TypeError if the function is called without a response.

    Instead, I believe the handler should check if the response exists first and if not throw an appropriate error.

    Cloudflare workers throws:

    [mf:err] POST /nada: FetchError [ERR_NO_RESPONSE]: No fetch handler responded and no upstream to proxy to specified.
    Make sure you're returning a `Response` in your handler.
    
    opened by danew 0
  • add websocket

    add websocket

    add webSocket to response, or corsify will fail.

    RangeError: init["status"] must be in the range of 200 to 599, inclusive.
    Web Socket request did not return status 101 Switching Protocols response with Web Socket
    
    opened by oseau 0
  • add support to multiple set-cookie headers

    add support to multiple set-cookie headers

    Hi,

    Currently multiple set-cookie headers is folded into one header, eg:

    'set-cookie': 'a=aValue; Max-Age=86400; Path=/w; HttpOnly; Secure; SameSite=None, b=bValue; Max-Age=86400; Path=/w; HttpOnly; Secure; SameSite=None',

    However the correct header should be:

    'set-cookie': [
        'a=aValue; Max-Age=86400; Path=/w; HttpOnly; Secure; SameSite=None',
        'b=bValue; Max-Age=86400; Path=/w; HttpOnly; Secure; SameSite=None'
      ],
    

    I made a quick fix according to the info here https://developers.cloudflare.com/workers/runtime-apis/headers/#differences

    Thanks for this awesome lib.

    opened by oseau 1
Owner
Kevin R. Whitley
I write things to make your code shorter and more readable. Recently focused on making serverless API development a joyful experience! :)
Kevin R. Whitley
Functional-style Cloudflare Durable Objects with direct API calls from Cloudflare Workers and TypeScript support.

durable-apis Simplifies usage of Cloudflare Durable Objects, allowing a functional programming style or class style, lightweight object definitions, a

Dabble 12 Jan 2, 2023
Subscribe to rss feeds from anywhere, receive notifications from anywhere.

INK RSS 管理订阅,接收通知 示例网页 · 示例群组 · 报告Bug 介绍 特点 项目背景 TODO 注意事项 部署 额外附赠 使用建议 调查 贡献 作者 协议 介绍 INK RSS 提供及时且多样的 rss 通知服务,借助现有的接口你可以在任意位置订阅,并使用任意方式接收通知,并且所有服务均

null 253 Dec 28, 2022
Avoid CORS issues by using API Routes from Next.js

CORS Demo Avoid CORS issues by using API Routes from Next.js. Get Started Clone the repo git clone [email protected]:gregrickaby/cors-demo.git CD into co

Greg Rickaby 2 Sep 30, 2022
💀 A bare-minimum solution to solve CORS problem via proxy API

?? CORS Hijacker A bare-minimum solution to solve CORS problem via proxy API Base URL https://cors-hijacker.vercel.app/ Get Get Basic HTML Endpoint: $

Irfan Maulana 35 Nov 4, 2022
An itty library to handle common time-related things for your API needs.

Tiny (~500 bytes) time math library for making date handling and TTLs within your APIs beautiful. Features Tiny @ ~500 bytes gzipped total, and tree-s

Kevin R. Whitley 8 Jan 2, 2023
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
基于 gh-proxy + Jsdelivr+ cnpmjs + cloudflare workers 的 GitHub Serverless API 工具。

better-github-api Better, Eazy, Access Anywhere 介绍 基于 gh-proxy + Jsdelivr + cnpmjs + cloudflare workers 的 GitHub Serverless API 工具。 cdn.js:仅含 gh-proxy

One Studio 11 Nov 23, 2022
Google-Drive-Directory-Index | Combining the power of Cloudflare Workers and Google Drive API will allow you to index your Google Drive files on the browser.

?? Google-Drive-Directory-Index Combining the power of Cloudflare Workers and Google Drive will allow you to index your Google Drive files on the brow

Aicirou 127 Jan 2, 2023