Apigee Response CORS Headers using Javascript

on Monday, February 26, 2018

Apigee provides a quick “Add CORS Headers” to responses when creating a new API Proxy. It’s straight forward and will get you started to add CORS headers to the replies from your first API endpoints. The problem with that is that CORS headers are used in “preflight” and aren’t that useful after the call has successfully completed. Apigee OPTIONS Response for Preflight/CORS can help you set up preflight responses.

But, it’s still useful to add in CORS headers to your responses in order to ensure that your endpoints are communicating their security requirements. To do this you can use javascript to inspect the responses and add in missing CORS headers. This sample javascript will:

  • Ensure Access-Control-Allow-Origin is defined. Sets the default value to ‘*’.
  • Ensure Access-Control-Allow-Headers is defined. Sets the default value to ‘origin, x-requested-with, accept, my-api-key, my-api-version, authorization, content-type’.
    • my-api-key and my-api-version are custom headers specific to the Apigee endpoints this script is used with. If the Resource Service doesn’t return these headers, then they will be added in.
  • Ensure Access-Control-Max-Age is defined. Sets the default value to ‘3628800’ seconds (42 days … I have no idea why that was chosen.)
  • Ensure Access-Control-Allow-Methods is defined. Sets the default value to ‘GET, PUT, POST, DELETE’. This should really be set by the Resource Service, so use it only if you feel comfortable.

This should be created as a Shared Flow and applied to Proxy Endpoint's Postflow.

//  Access-Control-Allow-Origin
var accessControlAllowOrigin = context.getVariable("response.header.Access-Control-Allow-Origin.values").toString();
if(accessControlAllowOrigin.startsWith('[')) { accessControlAllowOrigin = accessControlAllowOrigin.substring(1, accessControlAllowOrigin.length() - 1); }
if(accessControlAllowOrigin.endsWith('[')) { accessControlAllowOrigin = accessControlAllowOrigin.substring(0, accessControlAllowOrigin.length() - 1); }
if(accessControlAllowOrigin.length() === 0) {
    accessControlAllowOrigin = "*";
}
context.setVariable("response.header.Access-Control-Allow-Origin", accessControlAllowOrigin);

//  Access-Control-Allow-Headers
var accessControlAllowHeaders = context.getVariable("response.header.Access-Control-Allow-Headers.values").toString();
if(accessControlAllowHeaders.startsWith('[')) { accessControlAllowHeaders = accessControlAllowHeaders.substring(1, accessControlAllowHeaders.length() - 1); }
if(accessControlAllowHeaders.endsWith('[')) { accessControlAllowHeaders = accessControlAllowHeaders.substring(0, accessControlAllowHeaders.length() - 1); }
if(accessControlAllowHeaders.length() === 0) {
    accessControlAllowHeaders = "origin, x-requested-with, accept, my-api-key, my-api-version, authorization, content-type";
}
if(accessControlAllowHeaders.indexOf("my-api-key") === -1) {
    accessControlAllowHeaders += ", my-api-key";
}
if(accessControlAllowHeaders.indexOf("my-api-version") === -1) {
    accessControlAllowHeaders += ", my-api-version";
}
context.setVariable("response.header.Access-Control-Allow-Headers", accessControlAllowHeaders);

//  Access-Control-Max-Age
var accessControlMaxAge = context.getVariable("response.header.Access-Control-Max-Age.values").toString();
if(accessControlMaxAge.startsWith('[')) { accessControlMaxAge = accessControlMaxAge.substring(1, accessControlMaxAge.length() - 1); }
if(accessControlMaxAge.endsWith('[')) { accessControlMaxAge = accessControlMaxAge.substring(0, accessControlMaxAge.length() - 1); }
if(accessControlMaxAge.length() === 0) {
    accessControlMaxAge = "3628800";
}
context.setVariable("response.header.Access-Control-Max-Age", accessControlMaxAge);

//  Access-Control-Allow-Methods
var accessControlAllowMethods = context.getVariable("response.header.Access-Control-Allow-Methods.values").toString();
if(accessControlAllowMethods.startsWith('[')) { accessControlAllowMethods = accessControlAllowMethods.substring(1, accessControlAllowMethods.length() - 1); }
if(accessControlAllowMethods.endsWith('[')) { accessControlAllowMethods = accessControlAllowMethods.substring(0, accessControlAllowMethods.length() - 1); }
if(accessControlAllowMethods.length() === 0) {
    accessControlAllowMethods = "GET, PUT, POST, DELETE";
}
context.setVariable("response.header.Access-Control-Allow-Methods", accessControlAllowMethods);

0 comments:

Post a Comment


Creative Commons License
This site uses Alex Gorbatchev's SyntaxHighlighter, and hosted by herdingcode.com's Jon Galloway.