CORS Filter

Tips and Tricks

Detecting CORS support in a browser

The following JavaScript snipped can be used to detect CORS support in the browser:

function browserSupportsCors() {
	if ("withCredentials" in new XMLHttpRequest())
		return true;
	else if (typeof XDomainRequest == "object")
		return true;
	else
		return false;
}

The XDomainRequest object is specific to IE 8+, the other browsers extend the existing XMLHttpRequest.

Keep all your responses as text/plain

If you want your cross-domain web service to support as many browser types as possible set the content-type of all your responses to text/plain.

Content-Type: text/plain

Internet Explorer's CORS implementation, via the XDomainRequest object, imposes a number of limitations on cross-domain calls, including a rule that only "text/plain" responses are accepted. If your service returns any other content type, e.g. "application/json", the response will be silently discarded.

Check out the following post for more information:

XDomainRequest - Restrictions, Limitations and Workarounds

CORS and browser cookies

Users occasionally report that browser cookies don't work as expected in a cross-domain setting.

Does your filter take care of sessions? For each CORS request I get a different JSESSIONID.

In order for a Java web application or service to get at a cookie, both the CORS Filter in front of it as well as the requesting JavaScript must explicitly allow this form of credential:

First, the JavaScript that initiates the XHR call must set its "withCredentials" flag to true. If not the browser will prevent the passing of cookies during the cross-domain call.

var xhr = new XMLHttpRequest();
var url = 'http://bar.other/resources/credentialed-content/';

xhr.open('GET', url, true);
xhr.withCredentials = true;
xhr.onreadystatechange = handler;
xhr.send();

Second, the CORS Filter must also expressly state to the browser that cookies are permitted. This is advertised during the so called "pre-flight" request that the browser makes before an actual request that may involve credentials, such as cookies. The CORS Filter ships with a default configuration where credentials, such as cookies, are marked as allowed when responding to preflight requests. To restrict this edit the cors.supportsCredentials configuration parameter.

The Java CORS filter itself doesn't access the cookie headers in any way, nor does it interface to the JSESSIONID.

So, to sum up, both the calling script on the browser side as well as the CORS Filter on the server side must expressly have the credentials flag enabled for cookies to pass through.

There is a snag however and it has to do with Internet Explorer. Its XDomainRequest implementation of CORS doesn't allow cookies to be passed at all, for security reasons says Microsoft. Which is probably a good thing. So if you wish to achieve wider browser support for your cross-domain application or service you will have to use an alternative mean to cookies for storing session IDs, such as passing the token as an URL parameter.

FireBug is your friend

The versatile FireBug add-on is an excellent mean for debugging cross-domain calls. Yes, that's another reason to get FireFox :-)

Firebug has an excellent network activity monitor which can be used to reveal the CORS-specific conversation between browser and server during a cross-domain XHR. This is great for understanding how the protocol works, particularly the behaviour of simple/actual vs. pre-flight CORS requests.

To observe a CORS request in action you need a relatively recent version of Firebug (e.g. 1.6). Click on the "Net" tab and then on the "XHR" tab, then launch your cross-domain request.

Firebug XHR
How to load the Firebug Network Monitor

For a simple/actual CORS request Firebug will then display the following headers:

Simple request
Debugging a simple/actual CORS request

Note the Origin header which the browser inserted to identify the domain from which the HTML page originated. The server checks the Origin value and responds accordingly, by either allowing or denying the request.

Simple request
Debugging a simple CORS response

If the server allowed the origin it replies with an Access-Control-Allow-Origin header that contains a verbatim copy of the Origin header value or * (meaning any origin). The server may also include optional CORS response headers, such as Access-Control-Allow-Credentials (to tell the browser that it accepts cookies) or Access-Control-Expose-Headers (to tell the browser which custom headers are safe to expose to the requesting script).

CORS also has the so-called preflight request which browsers can send using HTTP OPTIONS prior to the actual CORS request to query the CORS settings of a particular HTTP server, such as the supported HTTP methods, custom headers, etc.

How to test CORS requests with a single web server

How to simulate a cross-domain request if you have just a single HTTP server to play with: Create a host alias of your web server and reload the requesting page using the alias URL.