@davaux/cors

Handles Cross-Origin Resource Sharing headers for your Davaux application. Supports configurable allowed origins, automatic OPTIONS preflight handling, and dynamic per-request origin validation.

Installation

npm install @davaux/cors

Basic usage

// davaux.config.ts
import { defineConfig } from 'davaux/config'
import { cors } from '@davaux/cors'

export default defineConfig({
  middleware: [
    cors({
      origin: 'https://app.example.com',
    }),
  ],
})

Options

OptionTypeDefaultDescription
originstring | string[] | ((origin: string) => boolean)'*'Allowed origins
credentialsbooleanfalseWhether to include Access-Control-Allow-Credentials: true
methodsstring[]['GET','HEAD','PUT','PATCH','POST','DELETE']Allowed HTTP methods
allowedHeadersstring[]Reflects request Access-Control-Request-HeadersHeaders allowed in requests
exposedHeadersstring[][]Headers browsers can read from the response
maxAgenumber86400Preflight cache duration in seconds

Origin as a string

Allow a single origin:

cors({ origin: 'https://app.example.com' })

Use '*' to allow all origins (cannot be combined with credentials: true):

cors({ origin: '*' })

Origin as an array

Allow multiple specific origins:

cors({
  origin: [
    'https://app.example.com',
    'https://admin.example.com',
    'http://localhost:3001',
  ],
  credentials: true,
})

The middleware echoes the matched origin back in the Access-Control-Allow-Origin response header and adds Vary: Origin to prevent incorrect caching.

Origin as a function

For dynamic validation — such as allowing all subdomains of a domain:

cors({
  origin: (origin) => {
    return origin.endsWith('.example.com') || origin === 'https://example.com'
  },
  credentials: true,
})

The function receives the value of the Origin request header and returns true to allow it or false to deny it.

Preflight requests

OPTIONS preflight requests are handled automatically. When a browser sends a preflight, the middleware responds with the appropriate CORS headers and a 204 No Content status — no route handler is invoked.

Credentials

To allow cookies and Authorization headers in cross-origin requests, set credentials: true:

cors({
  origin: 'https://app.example.com',  // must be a specific origin, not '*'
  credentials: true,
})

This adds Access-Control-Allow-Credentials: true to the response. Per the CORS spec, you cannot use a wildcard origin with credentials enabled.

API-only CORS

If you only want CORS on your API routes and not on page routes, use scoped middleware instead of config-level middleware:

// src/routes/api/_middleware.ts
import { defineMiddleware } from 'davaux'
import { cors } from '@davaux/cors'

const allowedOrigins = ['https://app.example.com']

export default defineMiddleware(async (ctx, next) => {
  const corsMiddleware = cors({ origin: allowedOrigins, credentials: true })
  return corsMiddleware(ctx, next)
})

Response headers set

On a matched origin:

  • Access-Control-Allow-Origin: <origin>
  • Vary: Origin
  • Access-Control-Allow-Credentials: true (if credentials: true)

On preflight:

  • All of the above
  • Access-Control-Allow-Methods: <methods>
  • Access-Control-Allow-Headers: <headers>
  • Access-Control-Max-Age: <maxAge>