Skip to content

CORS Middleware

There are many use cases of Cloudflare Workers as Web APIs and calling them from external front-end application. For them we have to implement CORS, let's do this with middleware as well.

Import

ts
import { Hono } from 'hono'
import { cors } from 'hono/cors'

Usage

ts
const app = new Hono()

app.use('/api/*', cors())
app.use(
  '/api2/*',
  cors({
    origin: 'http://example.com',
    allowHeaders: ['X-Custom-Header', 'Upgrade-Insecure-Requests'],
    allowMethods: ['POST', 'GET', 'OPTIONS'],
    exposeHeaders: ['Content-Length', 'X-Kuma-Revision'],
    maxAge: 600,
    credentials: true,
  })
)

app.all('/api/abc', (c) => {
  return c.json({ success: true })
})
app.all('/api2/abc', (c) => {
  return c.json({ success: true })
})

Multiple origins:

ts
app.use(
  '/api3/*',
  cors({
    origin: ['https://example.com', 'https://example.org'],
  })
)

// Or you can use "function"
app.use(
  '/api4/*',
  cors({
    // `c` is a `Context` object
    origin: (origin, c) => {
      return origin.endsWith('.example.com')
        ? origin
        : 'http://example.com'
    },
  })
)

Options

optional origin: string | string[] | (origin:string, c:Context) => string

The value of "Access-Control-Allow-Origin" CORS header. You can also pass the callback function like origin: (origin) => (origin.endsWith('.example.com') ? origin : 'http://example.com'). The default is *.

optional allowMethods: string[]

The value of "Access-Control-Allow-Methods" CORS header. The default is ['GET', 'HEAD', 'PUT', 'POST', 'DELETE', 'PATCH'].

optional allowHeaders: string[]

The value of "Access-Control-Allow-Headers" CORS header. The default is [].

optional maxAge: number

The value of "Access-Control-Max-Age" CORS header.

optional credentials: boolean

The value of "Access-Control-Allow-Credentials" CORS header.

optional exposeHeaders: string[]

The value of "Access-Control-Expose-Headers" CORS header. The default is [].

Environment-dependent CORS configuration

If you want to adjust CORS configuration according to the execution environment, such as development or production, injecting values from environment variables is convenient as it eliminates the need for the application to be aware of its own execution environment. See the example below for clarification.

ts
app.use('*', async (c, next) => {
  const corsMiddlewareHandler = cors({
    origin: c.env.CORS_ORIGIN,
  })
  return corsMiddlewareHandler(c, next)
})

Released under the MIT License.