This blog post is part of the Mixmax 2016 Advent Calendar. The previous post on December 3rd was about Node 6 features.
The Error
|
This error is probably why you are here. You are looking for a fix. Or maybe you're just curious to learn more about CORS. Whatever the reason, you've come to the right place. Read on to learn more about CORS or skip to the end to figure out how to fix your dilemma.
What is CORS?
CORS or Cross-Origin Resource Sharing is a method for allowing a web page to access resources outside the domain from which the page is being loaded. You might ask why this is needed; why can't I just load arbitrary JavaScript from random places on the internet? One good reason is cookies.
When a browser makes a request to a server in a domain, it sends the cookies that it has for that domain. This means that if I am logged into www.myUnsecureBank.com
and I load www.myMaliciousWebsite.com
in another tab, the malicious website can fetch data from my bank on my behalf. This works because the malicious site can contain JavaScript that makes AJAX requests outside the malicious website's domain and the browser will happily send cookies with that request. So the malicious website can call the www.myUnsecureBank.com/api/myBankDetails
and the server will respond because the browser will send the cookies that identify you as being logged in.
Fortunately, because of SOP
or Same Origin Policy, the browser will block this outbound request. This is where CORS comes in. CORS is a method that will allow us to make these types of requests, under the right circumstances.
How does it work?
Essentially, there are two types of cross origin requests: Simple and Preflighted. Simple requests are typically GET
, HEAD
, and POST
requests with specific headers and allowed values for Content-Type
. You can learn more about them here. Preflighted requests are, well, any request that is not a Simple Request (we will learn more about why they are called preflighted
in a bit).
For a Simple request, the browser will send the request with an Origin
header and the server will reply with an Access-Control-Allow-Origin
header. If the two don't match, the browser will produce a CORS error and not allow the request to complete.
For a Preflighted request, the browser will send an OPTIONS
request, before making the main request (which is why it is called a preflighted
request). The server will reply with Access-Control-Allow-Origin
but also with a Access-Control-Allow-Methods
header. This header specifies the type of requests the client is able to make (POST
, PATCH
, ...). If the main request does not match both headers, then the browser will produce a CORS error and not make main the request.
How do I play by the rules?
In order to make CORS work, you need server side changes. For simple requests, you simply have to make your server respond with the appropriate Access-Control-Allow-Origin
header.
For preflighted requests, however, you have to also respond with the correct Access-Control-Allow-Methods
header for the browser's OPTIONS
request. At Mixmax we like to use the cors package for handling these.
We have a Contacts service that runs under the domain contacts.mixmax.com
. We also have our main web app which runs under the domain app.mixmax.com
. Because our App makes all types of requests to our Contacts service, we have to handle CORS on the Contacts side.
This is what our router looks like on our Contacts service:
|
Conclusion
CORS is a feature, not a problem. It allows the modern web to exist by allowing web applications to use all sorts of APIs from different domains. Next time you see The Error, think about how it brings safety to your users and how CORS is an elegant way to handle the situation.
Enjoy building elegant APIs? Drop us a line.