CORS Library
Contents
Introduction
| Versions 2.x target XP 8+. |
A library for handling CORS (Cross-Origin Resource Sharing) headers in Enonic XP controllers and filters.
CORS lets browsers safely make cross-origin requests. This library reads your application’s .cfg file and produces the correct Access-Control-* response headers, including full preflight (OPTIONS) handling with origin matching, method validation, and header validation.
Installation
Add the dependency to your build.gradle file:
dependencies {
include "com.enonic.lib:lib-cors:${libVersion}"
}
Usage
Import the library in a controller or filter:
var corsLib = require('/lib/enonic/cors');
Controller
Handle preflight requests with respondOptions and attach CORS headers to regular responses with getHeaders:
var corsLib = require('/lib/enonic/cors');
// Preflight (OPTIONS) — returns 204 with CORS headers, or 403 on rejection
exports.options = function (req) {
return corsLib.respondOptions(req);
};
// Regular request — merge CORS headers into the response
exports.post = function (req) {
return {
contentType: 'application/json',
headers: corsLib.getHeaders(req),
body: JSON.stringify({ result: 'ok' }),
};
};
Both getHeaders and respondOptions read configuration from app.config automatically.
Filter
Use the library as an XP filter to apply CORS headers across multiple controllers from a single place:
var corsLib = require('/lib/enonic/cors');
exports.filter = function (req, next) {
if (req.method === 'OPTIONS') {
return corsLib.respondOptions(req);
}
var response = next(req);
var corsHeaders = corsLib.getHeaders(req);
response.headers = response.headers || {};
for (var key in corsHeaders) {
if (corsHeaders.hasOwnProperty(key)) {
response.headers[key] = corsHeaders[key];
}
}
return response;
};
Register the filter in your site.xml (or equivalent descriptor) as described in the XP filter documentation.
Explicit configuration
Pass a config map directly with resolveHeaders or resolveOptionsResponse instead of relying on app.config:
var corsLib = require('/lib/enonic/cors');
var config = {
'cors.origin': 'https://example.com',
'cors.credentials': 'true',
};
exports.options = function (req) {
return corsLib.resolveOptionsResponse(config, req);
};
exports.post = function (req) {
return {
contentType: 'application/json',
headers: corsLib.resolveHeaders(config, req),
body: JSON.stringify({ result: 'ok' }),
};
};
Configuration
Add a configuration file for the consuming application (e.g. com.example.myapp.cfg) to the XP configuration folder:
cors.origin = https://example.com, https://admin.example.com
cors.credentials = true
cors.allowedHeaders = Content-Type, Authorization
cors.methods = POST, GET
cors.exposedHeaders = X-Request-Id
cors.maxAge = 3600
| Key | Default | Description |
|---|---|---|
|
|
(not set) |
Allowed origin(s). When omitted, CORS is disabled and no headers are added. See Origin matching below. |
|
|
|
Set to |
|
|
(not set) |
Value for |
|
|
|
Value for |
|
|
(not set) |
Comma-separated list of extra response headers to expose to the browser via |
|
|
(not set) |
Preflight cache duration in seconds ( |
Origin matching
The cors.origin property supports several formats:
-
* -
Responds with
Access-Control-Allow-Origin: *for every request. Cannot be combined withcors.credentials = true. - Literal origin
-
A plain
https://example.comvalue. The incomingOriginheader is compared against each entry in the comma-separated list. On a match, the request origin is reflected back andVary: Originis set. On no match, onlyVary: Originis returned. -
~-prefixed regex -
A pattern starting with
~is treated as a regular expression anchored to the full origin string. For example,~https://.*\.example\.commatches any subdomain ofexample.com. Multiple patterns can be mixed with literals in the same comma-separated list. -
~.* -
Reflects any origin back verbatim. Unlike
*, this variant is compatible withcors.credentials = true.
# Literal origins
cors.origin = https://example.com, https://admin.example.com
# Regex: any subdomain of example.com
cors.origin = ~https://.*\.example\.com
# Mixed: literal and regex
cors.origin = https://example.com, ~https://.*\.dev\.example\.com
# Reflect any origin (supports credentials)
cors.origin = ~.*
API
The library exposes four functions:
getHeaders(req)
Returns CORS headers derived from app.config for use in regular (non-preflight) responses.
Parameters
| Name | Type | Description |
|---|---|---|
|
|
object |
Incoming XP request object (must expose a |
Returns
object — Key/value map of CORS headers to merge into the response headers field. Returns an empty object when CORS is disabled or the origin does not match.
Example
exports.get = function (req) {
return {
contentType: 'application/json',
headers: corsLib.getHeaders(req),
body: JSON.stringify({ result: 'ok' }),
};
};
respondOptions(req)
Returns a complete preflight response derived from app.config.
Parameters
| Name | Type | Description |
|---|---|---|
|
|
object |
Incoming XP request object (must expose a |
Returns
object — { status: 204, headers: { … } } on success, or { status: 403, headers: {} } when the preflight requests a disallowed method or header.
Example
exports.options = function (req) {
return corsLib.respondOptions(req);
};
resolveHeaders(config, req)
Low-level variant of getHeaders that accepts an explicit config map instead of reading app.config.
Parameters
| Name | Type | Description |
|---|---|---|
|
|
object |
Key/value map of configuration properties (same keys as the |
|
|
object |
Incoming XP request object (must expose a |
Returns
object — Key/value map of CORS headers.
Example
var config = { 'cors.origin': '~.*', 'cors.credentials': 'true' };
exports.get = function (req) {
return {
contentType: 'application/json',
headers: corsLib.resolveHeaders(config, req),
body: JSON.stringify({ result: 'ok' }),
};
};
resolveOptionsResponse(config, req)
Low-level variant of respondOptions that accepts an explicit config map.
Parameters
| Name | Type | Description |
|---|---|---|
|
|
object |
Key/value map of configuration properties. |
|
|
object |
Incoming XP request object (must expose a |
Returns
object — { status: 204, headers: { … } } on success, or { status: 403, headers: {} } on rejection.
Example
var config = { 'cors.origin': 'https://example.com', 'cors.methods': 'GET, POST' };
exports.options = function (req) {
return corsLib.resolveOptionsResponse(config, req);
};