Skip to content

Commit

Permalink
Configure CORS headers #610
Browse files Browse the repository at this point in the history
  • Loading branch information
anatol-sialitski committed Oct 18, 2023
1 parent bc34407 commit cd6b825
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 13 deletions.
20 changes: 13 additions & 7 deletions src/main/resources/api/api.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/* global log, Java */

const eventLib = require('/lib/xp/event');
const corsLib = require('/lib/cors');

const graphQLApi = __.newBean('com.enonic.app.guillotine.graphql.GraphQLApi');
const syncExecutor = __.newBean('com.enonic.app.guillotine.Synchronizer');

const CORS_HEADERS = {
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Origin': '*'
};

let schema;

eventLib.listener({
Expand Down Expand Up @@ -40,6 +35,17 @@ function getSchema() {
return schema;
}

function getHeaders(req) {
return corsLib.resolveHeaders(app.config, req);
}

exports.options = function (req) {
return {
status: 204,
headers: getHeaders(req),
}
};

exports.get = function (req) {
return {
status: 404
Expand All @@ -51,7 +57,7 @@ exports.post = function (req) {

return {
contentType: 'application/json',
headers: CORS_HEADERS,
headers: getHeaders(req),
body: JSON.stringify(__.toNativeObject(graphQLApi.execute(getSchema(), input.query, __.toScriptValue(input.variables))))
};
}
6 changes: 0 additions & 6 deletions src/main/resources/api/api.xml

This file was deleted.

30 changes: 30 additions & 0 deletions src/main/resources/lib/cors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
exports.resolveHeaders = function (config, req) {
if (config['cors.enabled'] === 'false') {
return {};
}

const headers = {};

if (config['cors.origin']) {
headers['access-control-allow-origin'] = config['cors.origin'];
headers['vary'] = 'Origin';
} else if (req.getHeader('Origin')) {
headers['access-control-allow-origin'] = req.getHeader('Origin');
headers['vary'] = 'Origin';
} else {
headers['access-control-allow-origin'] = '*';
}

if ((config['cors.credentials'] || '') === 'true') {
headers['access-control-allow-credentials'] = 'true';
}

headers['access-control-allow-headers'] = config['cors.allowedHeaders'] || 'Content-Type';
headers['access-control-allow-methods'] = config['cors.methods'] || 'POST, OPTIONS';

if (config['cors.maxAge']) {
headers['access-control-max-age'] = config['cors.maxAge'];
}

return headers;
};
72 changes: 72 additions & 0 deletions src/test/java/com/enonic/app/guillotine/CorsHeadersTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package com.enonic.app.guillotine;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.junit.jupiter.api.Test;

import com.enonic.xp.testing.ScriptTestSupport;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class CorsHeadersTest
extends ScriptTestSupport
{
@Test
public void testResolveWhenCorsHeadersDisabled()
{
Map<String, String> config = new HashMap<>();
config.put( "cors.enabled", "false" );

HttpServletRequest request = mock( HttpServletRequest.class );
runFunction( "lib/test-cors.js", "testResolveWhenCorsHeadersDisabled", config, request );
}

@Test
public void testResolveDefaultCorsHeaders()
{
Map<String, String> config = new HashMap<>();
config.put( "cors.enabled", "true" );

HttpServletRequest request = mock( HttpServletRequest.class );
when( request.getHeader( "Origin" ) ).thenReturn( null );

runFunction( "lib/test-cors.js", "testResolveDefaultCorsHeaders", config, request );
}

@Test
public void testResolveCorsHeaders()
{
Map<String, String> config = new HashMap<>();
config.put( "cors.enabled", "true" );
config.put( "cors.origin", "http://test-cors.com:3000" );
config.put( "cors.credentials", "true" );
config.put( "cors.allowedHeaders", "Content-Type, Authorization" );
config.put( "cors.methods", "POST, OPTIONS, GET" );
config.put( "cors.maxAge", "1200" );

HttpServletRequest request = mock( HttpServletRequest.class );

runFunction( "lib/test-cors.js", "testResolveCorsHeaders", config, request );
}

@Test
public void testResolveCorsHeadersWithOriginFromRequest()
{
Map<String, String> config = new HashMap<>();
config.put( "cors.enabled", "true" );
config.put( "cors.credentials", "true" );
config.put( "cors.allowedHeaders", "Content-Type, Authorization" );
config.put( "cors.methods", "POST, OPTIONS" );
config.put( "cors.maxAge", "600" );

HttpServletRequest request = mock( HttpServletRequest.class );
when( request.getHeader( "Origin" ) ).thenReturn( "http://test-cors.com:3000" );

runFunction( "lib/test-cors.js", "testResolveCorsHeadersWithOriginFromRequest", config, request );
}

}
42 changes: 42 additions & 0 deletions src/test/resources/lib/test-cors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const testingLib = require('/lib/xp/testing');
const corsLib = require('/lib/cors');

exports.testResolveWhenCorsHeadersDisabled = function (config, req) {
const headers = corsLib.resolveHeaders(config, req);
testingLib.assertJsonEquals({}, headers);
};

exports.testResolveDefaultCorsHeaders = function (config, req) {
const headers = corsLib.resolveHeaders(config, req);
testingLib.assertJsonEquals({
'access-control-allow-origin': '*',
'access-control-allow-headers': 'Content-Type',
'access-control-allow-methods': 'POST, OPTIONS',
}, headers);
};

exports.testResolveCorsHeaders = function (config, req) {
const headers = corsLib.resolveHeaders(config, req);
testingLib.assertJsonEquals({
'access-control-allow-origin': 'http://test-cors.com:3000',
'vary': 'Origin',
'access-control-allow-credentials': 'true',
'access-control-allow-headers': 'Content-Type, Authorization',
'access-control-allow-methods': 'POST, OPTIONS, GET',
'access-control-max-age': '1200',
}, headers);
};

exports.testResolveCorsHeadersWithOriginFromRequest = function (config, req) {
const headers = corsLib.resolveHeaders(config, req);
testingLib.assertJsonEquals({
'access-control-allow-origin': 'http://test-cors.com:3000',
'vary': 'Origin',
'access-control-allow-credentials': 'true',
'access-control-allow-headers': 'Content-Type, Authorization',
'access-control-allow-methods': 'POST, OPTIONS',
'access-control-max-age': '600',
}, headers);
};


0 comments on commit cd6b825

Please sign in to comment.