Processing CORS with Node.js

Processing CORS with Node.js

Front-end Pioneer

// Daily Front End Night Talk No. 415
// Main body: 1,900 words
// Estimated reading time: 8 minutes

Processing CORS with Node.js

In this article, we will study how to configure CORS with Express and customize CORS middleware as needed.

What is CORS


CORS is short for "cross-domain resource sharing". It is a mechanism that allows or restricts requests for resources on the Web server, depending on where the HTTP request is made.

This strategy is used to protect a specific Web server from other websites or domains. Only allowed domains can access files on the server, such as style sheets, images, or scripts.

Assuming that you are currently using http://example.com/page1, and you are citing pictures from http://image.com/myimage.jpg , then unless http://image.com allows the connection with http:/ /example.com is shared across domains, otherwise the image cannot be obtained.

There is a header named origin in every HTTP request header. It defines the source of the domain request. You can use the information in this header to restrict references to resources on your server.

❝By
default, requests from any other source will be restricted by the browser.

For example, if you use a front-end library such as React or Vue during development, the front-end application will run on http://localhost:3000 . At the same time, your Express server may be running on other ports, such as http:// localhost:2020. At this time, CORS needs to be allowed between these servers .

If you see errors like the picture below in the browser console. The problem may be the CORS limitation:

Processing CORS with Node.js
chrome cors
if we need to provide a common API and want to control access and use of certain resources, CORS can play a significant role.

In addition, if you want to use your own API or files on other web pages, you can also simply configure CORS to allow you to cite it yourself, while keeping others out.

Configure CORS with Express


First create a new project and create a directory structure, then run npm init with default settings:


$ mkdir myapp
$ cd myapp
$ npm init -y

Next install the required modules. We will use express and cors middleware:


$ npm i --save express
$ npm i --save cors

Then, start to create a simple web application with two routes to demonstrate how CORS works.

First create a file named index.js to act as a web server and implement several request processing functions:


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

const app = express();

app.get('/', (req, res) => {
    res.json({
        message: 'Hello World'
    });
});

app.get('/:name', (req, res) => {
    let name = req.params.name;

    res.json({
        message: `Hello ${name}`
    });
});

app.listen(2020, () => {
    console.log('server is listening on port 2020');
});

Run the server:


$ node index.js

Visit http://localhost:2020/ and the server should return a JSON message:


{
  "message": "Hello World"
}

Visit http://localhost:2020/something and you should be able to see:


{
  "message": "Hello something"
}

Enable all CORS requests


If you want to enable CORS for all requests, you can simply use the cors middleware before configuring routing:


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

const app = express();

app.use(cors())

......

If required, this will allow access to all routes from anywhere on the network. So in this example, each domain can access two routes.

For example, if our server runs on http://www.example.com and serves content such as pictures, then we allow other domains like http://www.differentdomain.com from http://www .example.com is cited.

So the webpage on http://www.differentdomain.com can use our domain as the source of the image:


<img src="http://www.example.com/img/cat.jpg">

Enable CORS for a single route


If you only need one of these routes, you can configure cors as middleware in a certain route:


app.get('/', cors(), (req, res) => {
    res.json({
        message: 'Hello World'
    });
});

This will allow any domain to access a particular route. In the current situation, other domains can only be accessed/routed. Only requests initiated in the same domain as the API (http://localhost:2020 in this example) can access the /:name route.

If you try to send a request to / path from another source, it will succeed and you will receive Hello World as a response:


fetch('http://localhost:2020/')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(err => console.error(err));

Run the above code, you will see that the response from the server has been successfully output to the console:


{
    message: 'Hello World'
}

If you visit a path other than the root path, such as http://localhost:2020/name or http://localhost:2020/img/cat.png, the request will be blocked by the browser :


fetch('http://localhost:2020/name/janith')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

If you run the code in other web applications, you should see the following error:
Processing CORS with Node.js

Console error

Configure CORS with options


You can also configure CORS with custom options. You can configure the allowed HTTP methods, such as GET and POST, as needed.

Here is how to allow single domain access through CORS option:


var corsOptions = {
    origin: 'http://localhost:8080',
    optionsSuccessStatus: 200 // For legacy browser support
}

app.use(cors(corsOptions));

If you configure the domain name in the source-the server will allow CORS from the configured domain. Therefore, in our example, the API can be accessed from http://localhost:8080 and other domains are prohibited from using it.

If you send a GET request, any path should be accessible because these options are applied at the program level.

Run the following code to send the request from http://localhost:8080 to http://localhost:2020 :


//
fetch('http://localhost:2020/')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

//
fetch('http://localhost:2020/name/janith')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(err => console.error(err));

You can see that you are allowed to obtain information from the program and domain.

You can also configure the allowed HTTP methods as needed:


var corsOptions = {
    origin: 'http://localhost:8080',
    optionsSuccessStatus: 200 // 对于旧版浏览器的支持
    methods: "GET, PUT"
}

app.use(cors(corsOptions));

If you send a POST request from http://localhost:8080 , the browser will block it because only GET and PUT are supported:


fetch('http://localhost:2020', {
  method: 'POST',
  body: JSON.stringify({name: "janith"}),
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err));

Configure dynamic CORS sources with functions


If the configuration does not meet your requirements, you can also create functions to customize CORS.

For example, suppose you want to allow http://something.com and http://example.com to share .jpg files with CORS:


const allowlist = ['http://something.com', 'http://example.com'];

    const corsOptionsDelegate = (req, callback) => {
    let corsOptions;

    let isDomainAllowed = whitelist.indexOf(req.header('Origin')) !== -1;
    let isExtensionAllowed = req.path.endsWith('.jpg');

    if (isDomainAllowed && isExtensionAllowed) {
        // 为此请求启用 CORS
        corsOptions = { origin: true }
    } else {
        // 为此请求禁用 CORS
        corsOptions = { origin: false }
    }
    callback(null, corsOptions)
}

app.use(cors(corsOptionsDelegate));

The callback function accepts two parameters, the first is the error of passing null, and the second is the option of passing {origin: false }. The second parameter can be more options constructed with Express's request object.

So the web application on http://something.com or http://example.com will be able to refer to the image with the extension .jpg from the server according to the custom configuration.

This can successfully reference the resource file:


<img src="http://yourdomain.com/img/cat.jpg">

But the following files will be blocked:


<img src="http://yourdomain.com/img/cat.png">

Load the list of allowed sources from the data source


You can also use a whitelist stored in the database or any kind of data source to allow CORS:


var corsOptions = {
    origin: function (origin, callback) {
        // 从数据库加载允许的来源列表
        // 例如:origins = ['http://example.com', 'http//something.com']
        database.loadOrigins((error, origins) => {
            callback(error, origins);
        });
    }
}

app.use(cors(corsOptions));

Guess you like

Origin blog.51cto.com/15077562/2609584