CORS
Handle Cross-Origin Resource Sharing in Nhost Functions
CORS cross-origin serverless functions Access-Control preflight OPTIONSNhost Functions inject a small set of default CORS headers so simple cross-origin GET and POST requests work without extra code. The defaults only fill in headers your function doesn’t set. Anything you set yourself (directly or via middleware like cors) is preserved as-is. Other methods, custom headers, or credentials are your responsibility.
Default Headers
Section titled “Default Headers”Unless your function sets them itself, every response includes:
| Header | Value |
|---|---|
Access-Control-Allow-Origin | * |
Access-Control-Allow-Headers | origin,Accept,Authorization,Content-Type |
Access-Control-Allow-Methods and Access-Control-Allow-Credentials are not set. Requests that need them won’t work until you set them yourself.
Disabling Default CORS
Section titled “Disabling Default CORS”If you want to block cross-origin access, return an empty Access-Control-Allow-Origin and/or Access-Control-Allow-Headers:
res.setHeader('Access-Control-Allow-Origin', '')res.setHeader('Access-Control-Allow-Headers', '')Customizing
Section titled “Customizing”Use the cors npm package for the cleanest setup:
npm install corsnpm install -D @types/corsimport type { Request, Response } from 'express'import cors from 'cors'
const corsMiddleware = cors({ origin: ['https://myapp.com', 'http://localhost:5173'], methods: ['GET', 'POST', 'PUT', 'DELETE'],})
export default (req: Request, res: Response) => { corsMiddleware(req, res, () => { res.status(200).json({ message: 'Hello from a CORS-enabled function!' }) })}Or set headers manually:
import type { Request, Response } from 'express'
export default (req: Request, res: Response) => { res.setHeader('Access-Control-Allow-Origin', 'https://myapp.com') res.status(200).json({ message: 'Hello!' })}Any CORS header you set takes precedence over the default; headers you leave untouched keep the default value. The snippet above covers simple requests only — see Preflight Requests for anything else.
Credentials
Section titled “Credentials”If your frontend sends cookies or authorization headers with credentials: 'include', you need Access-Control-Allow-Credentials: true. The CORS spec forbids combining that with Access-Control-Allow-Origin: *, so you must also override the origin to a specific value:
res.setHeader('Access-Control-Allow-Origin', 'https://myapp.com')res.setHeader('Access-Control-Allow-Credentials', 'true')Preflight Requests
Section titled “Preflight Requests”Browsers send a preflight OPTIONS request before the actual request when:
- The request uses a method other than GET, HEAD, or POST
- The request includes custom headers beyond the defaults above
- The request uses
Content-Typeother thanapplication/x-www-form-urlencoded,multipart/form-data, ortext/plain
The runtime does not respond to OPTIONS on your behalf — the request reaches your function. Either use the cors package (it handles preflight automatically) or handle OPTIONS manually:
import type { Request, Response } from 'express'
export default (req: Request, res: Response) => { if (req.method === 'OPTIONS') { res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE') return res.status(204).end() }
res.status(200).json({ message: 'Hello!' })}