Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,20 +116,34 @@ fastify.register(async function (fastify) {
fastify.listen({ port: 3000 })
```

### Disabling CORS for a specific route
### Route-Level CORS Overrides

CORS can be disabled at the route level by setting the `cors` option to `false`.
You can override or disable CORS on a per-route basis using the `config.cors` option:.

```js
const fastify = require('fastify')()

fastify.register(require('@fastify/cors'), { origin: '*' })
fastify.register(require('@fastify/cors'), { origin: 'https://example.com' })

fastify.get('/cors-enabled', (_req, reply) => {
reply.send('CORS headers')
reply.send('CORS headers applied')
})

fastify.get('/cors-disabled', { config: { cors: false } }, (_req, reply) => {
fastify.get('/cors-allow-all', {
config: {
cors: {
origin: '*', // Allow all origins for this route
},
},
}, (_req, reply) => {
reply.send('Custom CORS headers applied')
})

fastify.get('/cors-disabled', {
config: {
cors: false, // Disable CORS for this route
},
}, (_req, reply) => {
reply.send('No CORS headers')
})

Expand Down
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,9 @@ function normalizeCorsOptions (opts, dynamic) {
return corsOptions
}

function addCorsHeadersHandler (fastify, options, req, reply, next) {
function addCorsHeadersHandler (fastify, globalOptions, req, reply, next) {
const options = { ...globalOptions, ...req.routeOptions.config?.cors }

if ((typeof options.origin !== 'string' && options.origin !== false) || options.dynamic) {
// Always set Vary header for non-static origin option
// https://fetch.spec.whatwg.org/#cors-protocol-and-http-caches
Expand Down
72 changes: 72 additions & 0 deletions test/cors.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1050,3 +1050,75 @@ test('Should allow routes to disable CORS individually', async t => {
t.assert.strictEqual(res.statusCode, 200)
t.assert.strictEqual(res.headers['access-control-allow-origin'], undefined)
})

test('Should support route-level config', async t => {
t.plan(9)

const fastify = Fastify()
fastify.register(cors, {
origin: 'https://default-example.com'
})

// ✅ Route with default CORS (inherits plugin config)
fastify.get('/cors-enabled', (_req, reply) => {
reply.send('CORS headers applied')
})

// 🌍 Route with custom CORS origin
fastify.get('/cors-allow-all', {
config: {
cors: {
origin: '*'
}
}
}, (_req, reply) => {
reply.send('Custom CORS headers applied')
})

// 🚫 Route with CORS disabled
fastify.get('/cors-disabled', {
config: {
cors: false
}
}, (_req, reply) => {
reply.send('No CORS headers')
})

await fastify.ready()

// ✅ Default CORS
const resDefault = await fastify.inject({
method: 'GET',
url: '/cors-enabled',
headers: {
origin: 'https://default-example.com'
}
})
t.assert.ok(resDefault)
t.assert.strictEqual(resDefault.statusCode, 200)
t.assert.strictEqual(resDefault.headers['access-control-allow-origin'], 'https://default-example.com')

// 🌍 Custom CORS
const resCustom = await fastify.inject({
method: 'GET',
url: '/cors-allow-all',
headers: {
origin: 'https://example.com'
}
})
t.assert.ok(resCustom)
t.assert.strictEqual(resCustom.statusCode, 200)
t.assert.strictEqual(resCustom.headers['access-control-allow-origin'], '*')

// 🚫 CORS disabled
const resDisabled = await fastify.inject({
method: 'GET',
url: '/cors-disabled',
headers: {
origin: 'https://example.com'
}
})
t.assert.ok(resDisabled)
t.assert.strictEqual(resDisabled.statusCode, 200)
t.assert.strictEqual(resDisabled.headers['access-control-allow-origin'], undefined)
})