diff --git a/index.js b/index.js index c5197e3..26b1ba9 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,13 @@ const R = require('ramda'); +const getAllowedOrigin = (origin, allowedOrigins) => { + if (R.includes('*', allowedOrigins)) { + return origin; + } + + return R.find((allowedOrigin) => allowedOrigin === origin, allowedOrigins); +}; + const getCorsHeaders = ( { allowedOrigins, exposeHeaders, maxAge, credentials, allowMethods, allowHeaders } = {}, event @@ -7,13 +15,10 @@ const getCorsHeaders = ( const headers = {}; if (allowedOrigins) { - const isOriginAllowed = R.find( - (allowedOrigin) => allowedOrigin === R.path(['headers', 'origin'], event), - allowedOrigins - ); + const origin = getAllowedOrigin(R.path(['headers', 'origin'], event), allowedOrigins); - if (isOriginAllowed) { - headers['access-control-allow-origin'] = isOriginAllowed; + if (origin) { + headers['access-control-allow-origin'] = origin; } } diff --git a/index.test.js b/index.test.js index 95ef084..ddb0c97 100644 --- a/index.test.js +++ b/index.test.js @@ -108,6 +108,49 @@ test('Adds CORS headers on success from allowed origin', async () => { }); }); +test('Adds CORS headers on success when all origins allowed', async () => { + const handler = middy(async () => ({ + statusCode: 200, + body: JSON.stringify({ foo: 'bar' }), + headers: { + someHeader: 'someValue', + }, + })); + + handler.use( + middleware({ + allowedOrigins: ['*'], + exposeHeaders: ['x-my-header'], + maxAge: 2628000, // 1 month + credentials: true, + allowMethods: ['GET', 'POST'], + allowHeaders: ['Content-Type', 'Accept', 'X-Forwarded-For'], + }) + ); + + const response = await handler( + { + headers: { + origin: 'https://www.tek.no', + }, + }, + {} + ); + expect(response).toEqual({ + statusCode: 200, + headers: { + 'access-control-allow-credentials': true, + 'access-control-allow-headers': 'Content-Type, Accept, X-Forwarded-For', + 'access-control-allow-methods': 'GET, POST', + 'access-control-allow-origin': 'https://www.tek.no', + 'access-control-expose-headers': 'x-my-header', + 'access-control-max-age': 2628000, + someHeader: 'someValue', + }, + body: JSON.stringify({ foo: 'bar' }), + }); +}); + test('Adds CORS headers on error from disallowed origin', async () => { const handler = middy(async () => { throw new createError.InternalServerError('whoops'); @@ -189,6 +232,47 @@ test('Adds CORS headers on error from allowed origin', async () => { ); }); +test('Adds CORS headers on error when all origins allowed', async () => { + const handler = middy(async () => { + throw new createError.InternalServerError('whoops'); + }); + + handler.use( + middleware({ + allowedOrigins: ['*'], + exposeHeaders: ['x-my-header'], + maxAge: 2628000, // 1 month + credentials: true, + allowMethods: ['GET', 'POST'], + allowHeaders: ['Content-Type', 'Accept', 'X-Forwarded-For'], + }) + ); + + await expect( + handler( + { + headers: { + origin: 'https://www.tek.no', + }, + }, + {} + ) + ).rejects.toEqual( + expect.objectContaining({ + response: { + headers: { + 'access-control-allow-credentials': true, + 'access-control-allow-headers': 'Content-Type, Accept, X-Forwarded-For', + 'access-control-allow-methods': 'GET, POST', + 'access-control-allow-origin': 'https://www.tek.no', + 'access-control-expose-headers': 'x-my-header', + 'access-control-max-age': 2628000, + }, + }, + }) + ); +}); + test('Keep headers already present in the response on error from disallowed origin', async () => { const handler = middy(async () => { throw new createError.InternalServerError('whoops'); diff --git a/package-lock.json b/package-lock.json index a54d286..8745ad0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@schibsted/middy-cors", - "version": "0.2.0", + "version": "0.2.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 325012b..3221e22 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@schibsted/middy-cors", - "version": "0.2.0", + "version": "0.2.1", "description": "Middy middleware for adding CORS headers to success response and errors", "main": "index.js", "engines": {