UNPKG

@fastify/cors

Version:
489 lines (433 loc) 14.1 kB
'use strict' const { test } = require('node:test') const Fastify = require('fastify') const cors = require('../') test('Should reply to preflight requests', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) }) test('Should add access-control-allow-headers to response if preflight req has access-control-request-headers', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-headers': 'x-requested-with', 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], 'access-control-allow-headers': res.headers['access-control-allow-headers'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', 'access-control-allow-headers': 'x-requested-with', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) }) test('Should reply to preflight requests with custom status code', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors, { optionsSuccessStatus: 200 }) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 200) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) }) test('Should be able to override preflight response with a route', async t => { t.plan(5) const fastify = Fastify() await fastify.register(cors, { preflightContinue: true }) fastify.options('/', (_req, reply) => { reply.send('ok') }) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 200) t.assert.strictEqual(res.payload, 'ok') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'] } t.assert.deepStrictEqual(actualHeaders, { // Only the base cors headers and no preflight headers 'access-control-allow-origin': '*' }) t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should reply to all options requests', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors) const res = await fastify.inject({ method: 'OPTIONS', url: '/hello', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) }) test('Should support a prefix for preflight requests', async t => { t.plan(6) const fastify = Fastify() await fastify.register((instance, _opts, next) => { instance.register(cors) next() }, { prefix: '/subsystem' }) let res = await fastify.inject({ method: 'OPTIONS', url: '/hello' }) t.assert.ok(res) t.assert.strictEqual(res.statusCode, 404) res = await fastify.inject({ method: 'OPTIONS', url: '/subsystem/hello', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) }) test('hide options route by default', async t => { t.plan(2) const fastify = Fastify() fastify.addHook('onRoute', (route) => { if (route.method === 'OPTIONS' && route.url === '*') { t.assert.strictEqual(route.schema.hide, true) } }) await fastify.register(cors) const ready = await fastify.ready() t.assert.ok(ready) }) test('show options route', async t => { t.plan(2) const fastify = Fastify() fastify.addHook('onRoute', (route) => { if (route.method === 'OPTIONS' && route.url === '*') { t.assert.strictEqual(route.schema.hide, false) } }) await fastify.register(cors, { hideOptionsRoute: false }) const ready = await fastify.ready() t.assert.ok(ready) }) test('Allow only request from with specific methods', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors, { methods: ['GET', 'POST'] }) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) const actualHeaders = { 'access-control-allow-methods': res.headers['access-control-allow-methods'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-methods': 'GET, POST' }) t.assert.notStrictEqual(res.headers.vary, 'Origin') }) test('Should reply with 400 error to OPTIONS requests missing origin header when default strictPreflight', async t => { t.plan(3) const fastify = Fastify() await fastify.register(cors) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET' } }) t.assert.ok(res) t.assert.strictEqual(res.statusCode, 400) t.assert.strictEqual(res.payload, 'Invalid Preflight Request') }) test('Should reply with 400 to OPTIONS requests when missing Access-Control-Request-Method header when default strictPreflight', async t => { t.plan(3) const fastify = Fastify() await fastify.register(cors, { strictPreflight: true }) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { origin: 'example.com' } }) t.assert.ok(res) t.assert.strictEqual(res.statusCode, 400) t.assert.strictEqual(res.payload, 'Invalid Preflight Request') }) test('Should reply to all preflight requests when strictPreflight is disabled', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors, { strictPreflight: false }) const res = await fastify.inject({ method: 'OPTIONS', url: '/' // No access-control-request-method or origin headers }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) }) test('Default empty 200 response with preflightContinue on OPTIONS routes', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors, { preflightContinue: true }) const res = await fastify.inject({ method: 'OPTIONS', url: '/doesnotexist', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 200) t.assert.strictEqual(res.payload, '') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers' }) }) test('Can override preflight response with preflightContinue', async t => { t.plan(4) const fastify = Fastify() await fastify.register(cors, { preflightContinue: true }) fastify.options('/', (_req, reply) => { reply.send('ok') }) const res = await fastify.inject({ method: 'OPTIONS', url: '/', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 200) t.assert.strictEqual(res.payload, 'ok') const actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers' }) }) test('Should support ongoing prefix ', async t => { t.plan(12) const fastify = Fastify() await fastify.register(async (instance) => { instance.register(cors) }, { prefix: '/prefix' }) // support prefixed route let res = await fastify.inject({ method: 'OPTIONS', url: '/prefix', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') let actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) // support prefixed route without / continue res = await fastify.inject({ method: 'OPTIONS', url: '/prefixfoo', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) // support prefixed route with / continue res = await fastify.inject({ method: 'OPTIONS', url: '/prefix/foo', headers: { 'access-control-request-method': 'GET', origin: 'example.com' } }) t.assert.ok(res) delete res.headers.date t.assert.strictEqual(res.statusCode, 204) t.assert.strictEqual(res.payload, '') actualHeaders = { 'access-control-allow-origin': res.headers['access-control-allow-origin'], 'access-control-allow-methods': res.headers['access-control-allow-methods'], vary: res.headers.vary, 'content-length': res.headers['content-length'] } t.assert.deepStrictEqual(actualHeaders, { 'access-control-allow-origin': '*', 'access-control-allow-methods': 'GET,HEAD,POST', vary: 'Access-Control-Request-Headers', 'content-length': '0' }) })