CORS stands for Cross-Origin Resource Sharing and represents a method of accessing/sharing resources across domains. These resources can be anything from web fonts to APIs. The CORS standard is only implemented in browsers, since this is the only place where it makes sense. While this is the preferred method of sharing resources, it has a few rough edges.
In the following we’ll refer to the response headers, since the request headers are automatically set by the browser.
A special header defined in the CORS specification must be sent by the server in each response to allow access to a resource:
To allow any domain to access resources the header can be set to a wildcard:
This is the bare minimum and it will suffice for sharing static resources such as web fonts. But once we throw in authentication, which is needed by most APIs, things get messy.
Authentication, with either cookies or HTTP auth, requires an additional response header:
var req = new XMLHttpRequest(); req.open('GET', url); req.withCredentials = true; req.onreadystatechange = handler; req.send();
A few notes on authentication:
- We cannot use domain wildcards for the
Access-Control-Allow-Originheader when allowing credentials. The domain must be explicitly stated. This is a feature to prevent CSRF.
- Credentials are not allowed with synchronous requests in some browsers, since these requests cannot be pre-flighted.
- IE and Opera were slow to adopt CORS; only IE 10 and Opera 12 support it properly.
Some cross-origin requests are pre-flighted, meaning that an
OPTIONS request is automatically sent by the browser before each request, to query the server for allowed HTTP methods, allowed headers or to check whether credentials are allowed.
OPTIONS requests are only sent if any of the following conditions are met:
- The request method is other than
- The request Content-Type is other than
- Custom headers are set.
OPTIONS before each real request has a bit of overhead. Fortunately, there is a header that tells the browser to cache these requests:
Allowing methods and headers
In order to create RESTful APIs we need to use more than the
Servers can inform the clients of the allowed HTTP methods by using another type of CORS header:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Any number of HTTP verbs can be listed here.
Allowed headers can be set with:
Access-Control-Allow-Headers: Origin, X-Reqested-With, Accept
X-Reqested-With is needed for asynchronous requests.
All these headers except
Access-Control-Allow-Origin are commonly included only in the pre-flight response.
As always, IE chooses to hit developers with a crowbar.
Instead of extending
XMLHttpRequest, IE 8 introduces another interface named
XDomainRequest, with a similar interface, which supports CORS, but not its full set of features.
Luckily IE 10 fixes this and adds support for CORS within the standard XMLHttpRequest.