0.3.6 • Published 1 year ago

@noahsaso/itty-cors v0.3.6

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

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).

OptionType(s)DefaultDescription
originsstring[]['*']By default, all origins are allowed (most common). Modify this to restrict to specific origins.
maxAgenumber3600Set the expiry of responses
methodsstring[]['GET']Define which methods are allowed. OPTIONS will be automatically added.
headersobject{}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.