Setting CORS Headers in your Requests

What is CORS?

When your application tries making a cross domain request (a request from another website other than your domain) using a script, then for security reasons your browser prevents such a request and gives you an error.

-> Same origin requests are always allowed

-> Cross domain requests are controlled by HTTP CORS.

To mitigate risks, browsers use CORS in an API container like such as XMLHttpRequest (of AJAX fame) or Fetch (this is still quite new).

The Cross-Origin Resource Sharing standard works by adding new HTTP headers that allow servers to describe the set of origins that are permitted to read that information using a web browser.

The best resource for reading more about HTTP Access Control (CORS) is the Mozilla Developer Guides. You can also check out the W3C spec on the same.

Understanding the CORS Error

  • XMLHttpRequest cannot load < insert wonky url >
  • Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
  • Origin < another url > is therefore not allowed access.

Along with the Mozilla guides, this tutorial by HTML5Rocks really helped me understand different the different aspects of CORS.
Some of the interesting concepts were: Pre-flight requests & simple requests, Origin Headers, the related headers.


1: Configuring your Dev Tools

It's easier to have your localhost accept the requisite headers. You can turn off CORS in chrome. Or actually list the name of the domain in your mainfest.json file.

Here is a StackOverflow answer on how to turn off CORS in your browser.

You can also use a browser plugin like Allow-Control-Allow-Origin.

This will only affect your local development.

2: Setting crossOrigin to true.
``` let request = { method: options.method || 'GET', url: options.url, contentType: "application/json; charset=utf-8", dataType: "json", crossOrigin: true, beforeSend: function(request) { request.setRequestHeader('Authorization', token); }, success(data) { resolve(data); }, error(jqXHR, status, error) { reject(error); } }; ```

A standard request object, where crossOrigin is set to true. Written for promises compatible.

3: Setting your header
``` header('Access-Control-Allow-Origin: *'); ``` You have access to this HTTP request from your server.
4: Via jQuery
  type: 'GET',
  url: 'http://example/.com',
  contentType: 'text/plain',
  xhrFields: {
    withCredentials: false
  headers: {
   // custom header
  success: function() {
    // successful response.
  error: function() {
    //  an error response.

Can read in more detail in the tutorial linked above.

4: Node Packages

You can use the Node.js CORS middleware via $ npm install cors

The documentation here mentions how simple it is to implement:

var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: '',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for only'})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
5: Enabling CORS API in Hapi.js endpoints

There are a few places you can implement your CORS headers. In fact, the documentation mentions the different options.
I prefer at the request level making it a part of the reply:

return reply(null, {}).header('Access-Control-Allow-Origin', '*');

But I have seen different implementations which apparently work as well:

server.connection({ routes: { cors: true } })

Or implement it as part of the config object:

    config: {
        cors: {
            origin: ['*'],
            additionalHeaders: ['cache-control', 'x-requested-with']

I also came across an npm package that helps with the same.