diff --git a/packages/core/src/server.js b/packages/core/src/server.js index ac8f238c5..780a60cc3 100644 --- a/packages/core/src/server.js +++ b/packages/core/src/server.js @@ -7,7 +7,11 @@ async function getReply(routes, request) { // cors preflight if (request.method === 'OPTIONS') { - reply = [204, { 'Access-Control-Allow-Methods': 'GET,POST' }]; + reply = [204, {}]; + reply[1]['Access-Control-Allow-Methods'] = 'GET,POST,OPTIONS'; + reply[1]['Access-Control-Request-Headers'] = 'Vary'; + let allowed = request.headers['access-control-request-headers']; + if (allowed?.length) reply[1]['Access-Control-Allow-Headers'] = allowed; } else { reply = await Promise.resolve() .then(() => routes.middleware?.(request)) diff --git a/packages/core/test/server.test.js b/packages/core/test/server.test.js index 2de9717b8..857380168 100644 --- a/packages/core/test/server.test.js +++ b/packages/core/test/server.test.js @@ -123,17 +123,28 @@ describe('Snapshot Server', () => { it('accepts preflight cors checks', async () => { let called = false; + let response; await percy.start(); percy.snapshot = async () => (called = true); - let response = await fetch('http://localhost:1337/percy/snapshot', { + response = await fetch('http://localhost:1337/percy/snapshot', { method: 'OPTIONS' }); expect(response.status).toBe(204); expect(response.headers.get('Access-Control-Allow-Origin')).toBe('*'); - expect(response.headers.get('Access-Control-Allow-Methods')).toBe('GET,POST'); + expect(response.headers.get('Access-Control-Allow-Methods')).toBe('GET,POST,OPTIONS'); + expect(response.headers.get('Access-Control-Request-Headers')).toBe('Vary'); + expect(called).toBe(false); + + response = await fetch('http://localhost:1337/percy/snapshot', { + headers: { 'Access-Control-Request-Headers': 'Content-Type' }, + method: 'OPTIONS' + }); + + expect(response.status).toBe(204); + expect(response.headers.get('Access-Control-Allow-Headers')).toBe('Content-Type'); expect(called).toBe(false); });