Processing CORS in Express

How to allow cross-site requests by setting CORS

A JavaScript application running in a browser can usually only access HTTP resources from the same domain (source) that provides the service for it.

It is always possible to load images or scripts/styles from the same source. In addition, use@font-faceThe "same source" policy is set by default. And other less popular things (such as WebGL textures anddrawImageResources loaded in the Canvas API).

However, XHR and Fetch calls to external third-party servers will fail. Unless the third-party server implements a mechanism that allows the establishment of a connection and allows the requested resource to be downloaded and used.

This mechanism is calledCORS,Cross-domain resource sharing.

One very important thing that requires CORS isES module, Recently introduced in modern browsers.

If you have not set a CORS policyOn the serverTo make it available to serve third-party sources, the request will fail.

Get examples:

Fetch failed because of CORS policy

XHR example:

XHR request failed because of CORS policy

Cross-domain resources will fail in the following situations:

  • anotherfield
  • anotherSubdomains
  • anotherport
  • anotherprotocol

CORS can ensure your safety to prevent malicious users from taking advantage of any web platform you happen to be using.

If you control two servers at the same timewithFor customers, you know that both parties are trustworthy, so there are good reasons to allow resource sharing.

how is it?

It depends on your server-side stack.

Browser support

Pretty good (basically everything except IE <10):

CORS browser support

Express example

If you use Node.js and Express as the framework, please useCORS middleware package.

This is a simple implementation of the Express Node.js server:

const express = require('express')
const app = express()

app.get(’/without-cors’, (req, res, next) => { res.json({ msg: ‘😞 no CORS, no party!’ }) })

const server = app.listen(3000, () => { console.log(‘Listening on port %s’, server.address().port) })

If you hit/without-corsIf you get the request from other sources, it will cause CORS problems.

All you need to do is to make things go smoothly,corsThe package linked above, and pass it as a middleware function to the endpoint request handler:

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

app.get(’/with-cors’, cors(), (req, res, next) => { res.json({ msg: ‘WHOAH with CORS it works! 🔝 🎉’ }) })

/* the rest of the app */

I made a simple Glitch example, and here is its code:https://glitch.com/edit/#!/flavio-cors-client.

This is the Node.js Express server:https://glitch.com/edit/#!/flaviocopes-cors-example-express

Please note how to still receive requests that failed due to the server not processing CORS headers correctly. As you can see in the "Network" panel, you can see the messages sent by the server:

No response from CORS

Only allow certain sources

However, this example has a problem: the server will accept any request as a cross-domain.

As you can see in the "Network" panel, the passed request has a response headeraccess-control-allow-origin: *:

The CORS response header

You need to configure the server to allow only one source service and block all other sources.

Use the samecorsNode library, the method is as follows:

const cors = require('cors')

const corsOptions = { origin: https://yourdomain.com, }

app.get(’/products/:id’, cors(corsOptions), (req, res, next) => { //… })

You can also provide more services:

const whitelist = ['http://example1.com', 'http://example2.com']
const corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  },
}

Before the flight

Some requests are handled in a "simple" way. AllGETThe request belongs to this group.

alsosome POSTwithHEADThe same is true for requests.

POSTIf the request meets the requirements for using Content-Type, the request also belongs to this group

  • application/x-www-form-urlencoded
  • multipart/form-data
  • text/plain

All other requests must go through a pre-approval stage called a pre-check. The browser determines whether it is authorized to perform the operation by issuing the following command:OPTIONSClaim.

The preflight request contains some headers, which the server will use to check permissions (ignoring irrelevant fields):

OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://your-origin.com

The server will respond with something like this (irrelevant fields omitted):

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://your-origin.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE

We checked for POST, but the server tells us we can also issue other HTTP request types for that particular resource.

Following the Node.js Express example above, the server must also handle the OPTIONS request:

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

//allow OPTIONS on just one resource app.options(’/the/resource/you/request’, cors())

//allow OPTIONS on all resources app.options(’*’, cors())

Download my free Express.js Handbook


More express tutorials: