Improve Article
Save Article
Improve Article
Save Article
CORS, also known as Cross-Origin Resource Sharing, should be enabled if you want to make a request between your client and server when they are on different URLs.
Let us consider client to be on http://localhost:5500 and the server on http://localhost:5000. Now if you try to make a request from your client to the server you will get the error stating that blocked by the CORS policy.
How To Enable CORS?
We will use cors, a node.js package to enable CORS in express Node.js Project.
Project Setup and Module Installation:
-
Step 1: Create a Node.js application and name it gfg-cors using the following command.
mkdir gfg-cors && cd gfg-cors npm init
- Step 2: Install the dependency modules using the following command.
npm i express cors
-
Step 3: Create client directory and server.js file in the root directory. Then create index.html and script.js in the client directory.
Project Directory: It will look like this.
Example:Write down the following code in the index.html, script.js, and server.js files.
index.html
<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
http-equiv
=
"X-UA-Compatible"
content
=
"IE=edge"
>
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<
title
>gfg-cors</
title
>
<
script
src
=
"script.js"
></
script
>
</
head
>
<
body
>
</
body
>
</
html
>
script.js
server.js
const express = require(
'express'
);
const cors = require(
'cors'
);
const app = express();
app.use(cors());
app.get(
'/gfg-articles'
,
(req, res) => res.json(
'gfg-articles'
));
const port = 5000;
app.listen(port, () => `Server running on port ${port}`);
Note: If you want to allow the selected origins to access your site then you need to configure cors as shown below.
server.js
const express = require(
'express'
);
const cors = require(
'cors'
);
const app = express();
let corsOptions = {
};
app.get(
'/gfg-articles'
,cors(corsOptions),
(req,res) => res.json(
'gfg-articles'
))
const port = 5000;
app.listen(port, () => `Server running on port ${port}`);
If you just want to allow a particular origin to access your site, then corsOptions will be as follows:
let corsOptions = { origin: 'http://localhost:5500' };
Step to run the application: Run the server.js using the following command.
node server.js
Output: Open index.html and then check the following output in the console.
Table of Contents
In the previous article, I have explained how to deploy a Node.js application to Heroku.
In this tutorial, we will be making use of the endpoint created there and see if we can use it in our React project.
Project Setup
Let’s create a React project using the following command:
1npx create-react-app react-cors
Now update the App.js
with the following code:
App.js
1import { useEffect, useState } from "react"
2import "./App.css"
3
4function App() {
5 const [message, setMessage] = useState("")
6 useEffect(() => {
7 fetch("https://nodejs-using-github.herokuapp.com/")
8 .then(response => response.json())
9 .then(data => {
10 setMessage(data.message)
11 })
12 .catch(err => console.log(err))
13 }, [])
14 return <div className="App">{message ? message : "Loading.."}</div>
15}
16
17export default App
Here we have a local state called message
, which we show to the user.
If the message is empty, then we display them with a loading text.
When the component is mounted (useEffect), we make a call to the API endpoint and fetch the message.
Now let’s run this and see if it works:
You will see that only «Loading..» text is displayed and the message never loads.
If we inspect the page and see the console, we will see the following error:
Access to fetch at 'https://nodejs-using-github.herokuapp.com/' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
In the next sections, we will see what is CORS and how to fix this error.
What is CORS (Cross-Origin Resource Sharing)?
CORS stands for Cross-Origin Resource Sharing,
which is an HTTP header based mechanism that helps the server to tell the browser,
from which all domain requests can be made (except the same domain).
That is, in our case, the Node.js server hosted at https://nodejs-using-github.herokuapp.com/
,
does not tell the browser that request can be made from http://localhost:3000
.
When this happens, your browser will throw an error as seen earlier.
Why CORS (Cross-Origin Resource Sharing)?
The next question that would come to your mind is why do we really need this mechanism.
Imagine you are logged into your bank account or any social media website, then you visit a malicious website.
This malicious website could run some scripts in the background to make API calls to your banking or social media to get your personal details.
To prevent this, your browser checks if the request to the banking or social media server can be made from the malicious website and throws the CORS error.
So CORS exists to share certain resources between trusted third-parties (across different origins/domains), hence the name Cross-Origin Resource Sharing.
How to configure CORS in Node.js
Since we are clear about what and why is CORS required, let’s see how to enable CORS in the Node.js application.
You may clone the Node.js code from this repo.
Once the project is cloned, open it in your code editor and install cors package.
Now open index.js
and update it with the following code:
index.js
1const express = require("express")
2const cors = require("cors")
3const app = express()
4const port = process.env.PORT || 3000
5
6const whitelist = ["http://localhost:3000"]
7const corsOptions = {
8 origin: function (origin, callback) {
9 if (!origin || whitelist.indexOf(origin) !== -1) {
10 callback(null, true)
11 } else {
12 callback(new Error("Not allowed by CORS"))
13 }
14 },
15 credentials: true,
16}
17app.use(cors(corsOptions))
18
19app.get("/", (req, res) => {
20 res.send({ message: "Hello World!" })
21})
22
23app.listen(port, () => {
24 console.log(`Example app listening at Port: ${port}`)
25})
Here we check if the origin (client’s domain) is in the whitelist, then we tell the clients that requests can be made.
If it is not in the list then we throw an error saying the client is not allowed to make CORS requests to this server.
The domain should not have any trailing slashes (/)
We can deploy the changes to Heroku and see if this works.
Now if you reload your page, you should be able to see the message.
You will also see that a response header called Access-Control-Allow-Origin
has been added with the value http://localhost:3000
.
Making CORS domains configurable
If you have multiple client origins to be connected to you, and you want them to be configurable, you can do so by using environment variables:
index.js
1const express = require("express")
2const cors = require("cors")
3const app = express()
4const port = process.env.PORT || 3000
5
6const domainsFromEnv = process.env.CORS_DOMAINS || ""
7
8const whitelist = domainsFromEnv.split(",").map(item => item.trim())
9
10const corsOptions = {
11 origin: function (origin, callback) {
12 if (!origin || whitelist.indexOf(origin) !== -1) {
13 callback(null, true)
14 } else {
15 callback(new Error("Not allowed by CORS"))
16 }
17 },
18 credentials: true,
19}
20app.use(cors(corsOptions))
21
22app.get("/", (req, res) => {
23 res.send({ message: "Hello World!" })
24})
25
26app.listen(port, () => {
27 console.log(`Example app listening at Port: ${port}`)
28})
Testing environment variables locally
To test environment variables locally, you can install the package called dotenv
:
Now create a file called .env
in the root directory of your project with the domains:
1CORS_DOMAINS = http://localhost:3000, http://localhost:3001, https://example.com
Update index.js
to use the dotenv
package:
index.js
1const express = require("express")
2const cors = require("cors")
3const app = express()
4const port = process.env.PORT || 3000
5
6if (process.env.NODE_ENV !== "production") {
7 require("dotenv").config()
8}
9
10const domainsFromEnv = process.env.CORS_DOMAINS || ""
11
12const whitelist = domainsFromEnv.split(",").map(item => item.trim())
13
14const corsOptions = {
15 origin: function (origin, callback) {
16 if (!origin || whitelist.indexOf(origin) !== -1) {
17 callback(null, true)
18 } else {
19 callback(new Error("Not allowed by CORS"))
20 }
21 },
22 credentials: true,
23}
24app.use(cors(corsOptions))
25
26app.get("/", (req, res) => {
27 res.send({ message: "Hello World!" })
28})
29
30app.listen(port, () => {
31 console.log(`Example app listening at Port: ${port}`)
32})
Here we made sure that .env
files are loaded only in non-production environments.
It is recommended to store the configurations in the server host rather than in .env files for production.
Remember to add
.env*
to the.gitignore
file so that you don’t accidentally push them to the repo.
Configuring environment files in heroku
With our latest code, we can configure environment files in the heroku settings:
Go to your project settings and click on «Reveal Config Vars». Now you can provide the key and values here and click on «Add»
Once added, you can push your changes and see if the changes work.
If you have liked article, stay in touch with me by following me on twitter.
Содержание
- How to solve CORS error in Node.js and React applications
- Table of Contents
- Project Setup
- What is CORS (Cross-Origin Resource Sharing)?
- Why CORS (Cross-Origin Resource Sharing)?
- Simple Steps to Fix CORS Error While Connecting a Front-End App to a Node.js/Express.js App
- Step 1:
- Step 2:
- Step 3:
- Additional Resources:
- CORS: просто и понятно говорим про ошибки кроссдоменных запросов
- How to use CORS in Node.js with Express
- Prerequisites
- What is CORS?
- How CORS works
- Setting up CORS with Express
- Creating a simple Express GET request
- Performing more requests
- Use case
- Conclusion
How to solve CORS error in Node.js and React applications
Table of Contents
In the previous article, I have explained how to deploy a Node.js application to Heroku. In this tutorial, we will be making use of the endpoint created there and see if we can use it in our React project.
Project Setup
Let’s create a React project using the following command:
Now update the App.js with the following code:
Here we have a local state called message , which we show to the user. If the message is empty, then we display them with a loading text. When the component is mounted (useEffect), we make a call to the API endpoint and fetch the message.
Now let’s run this and see if it works:
You will see that only «Loading..» text is displayed and the message never loads. If we inspect the page and see the console, we will see the following error:
Access to fetch at ‘https://nodejs-using-github.herokuapp.com/’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
In the next sections, we will see what is CORS and how to fix this error.
What is CORS (Cross-Origin Resource Sharing)?
CORS stands for Cross-Origin Resource Sharing, which is an HTTP header based mechanism that helps the server to tell the browser, from which all domain requests can be made (except the same domain).
That is, in our case, the Node.js server hosted at https://nodejs-using-github.herokuapp.com/ , does not tell the browser that request can be made from http://localhost:3000 .
When this happens, your browser will throw an error as seen earlier.
Why CORS (Cross-Origin Resource Sharing)?
The next question that would come to your mind is why do we really need this mechanism. Imagine you are logged into your bank account or any social media website, then you visit a malicious website. This malicious website could run some scripts in the background to make API calls to your banking or social media to get your personal details.
To prevent this, your browser checks if the request to the banking or social media server can be made from the malicious website and throws the CORS error.
So CORS exists to share certain resources between trusted third-parties (across different origins/domains), hence the name Cross-Origin Resource Sharing.
Источник
Simple Steps to Fix CORS Error While Connecting a Front-End App to a Node.js/Express.js App
Ever came across this error?
Access to XMLHttpRequest at ‘ http://localhost:8000/users/’ from origin ‘ http://localhost:3000′ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The ‘Access-Control-Allow-Origin’ header has a value ‘ http://localhost:3000/’ that is not equal to the supplied origin.
If yes, here are simple steps that you need to follow in order to address this issue. First things first, if you wanna know about CORS policy and its advantages, please refer to this link. In short, CORS helps in making the application more secure.
Note: I presume that your Node.js app is already built and I will only be providing some steps to fix the error.
Step 1:
Open your Node.js application in your favorite IDE and go to the root directory. Open the terminal and type:
and press enter. Cors will be installed on your app.
Step 2:
Now let’s configure the cors module. In your Node.js app, go to the folder containing the file in which all the routes are defined. In the same folder(not necessarily, but only for convenience), create a new file and name it ‘cors.js’. Now add the following code to cors.js:
In the snippet given above, you may notice a constant named ‘allowedOrigins’ which contains all the URLs which may access the back-end app. In our case, we need to mention the URL where our front-end app is hosted, which is usually localhost during development. Make sure that you mention correct port (3000 in the example). Also, don’t forget to add the second URL in which you need to mention your computer’s name.
Don’t know what your computer’s name is? Not a problem, just open the command prompt and type “ hostname” and press enter. The name of your computer will be displayed.
Step 3:
Now we need to configure the routes. Let us say we want to access the sign up API from front-end app. Firstly, we will update our app.js(or index.js whichever is the starting point of your app). Please add following lines of code to your app.js
Similary modify the authRoutes.js file as shown below:
What have we done here? Firstly, we have required the cors.js file which we had created earlier. Then we have defined the sign-up endpoint beginning with options() which simply takes care of CORS preflight. I have used POST method to sign-up but many developers prefer using PUT, and it is your call which you wanna go with. The corsWithOptions function makes sure that the request is originated from one of the sources which are listed in allowedOrigins (in cors.js). Similarly, you may modify all the route endpoints by adding CORS policy just as we did for sign-up. Three major points to keep in mind are:
- Require cors from cors.js
- Use options at the beginning of each end-point
- For each type of request, you need to use corsWithOptions. You may also use cors.cors() in place of cors.corsWithOptions() if you wanna allow the requests originating from all origins.
The back-end app is now ready to serve the client app. The sign-up endpoint can be accessed at ‘ http://localhost:/auth/users/signup’.
Additional Resources:
You might wanna refer to a few links in case you like going deep into the topic.
Источник
CORS: просто и понятно говорим про ошибки кроссдоменных запросов
Меня зовут Радик, я frontend developer компании Creative. И сегодня я хочу поднять тему, которая касается и фронта и бэка, и окружает нас с вами каждый день. Речь пойдёт об ошибках CORS и как их можно обойти.
Уверен, что многим разрабам знакома ситуация, когда ты работаешь над приложением, оно запущено локально, и тебе нужно сделать из него запросы к различным удалённым ресурсам. В этот момент «что-то идёт не так», и ты видишь на своём экране миллион ошибок в консоли браузера. Почему они появляются? Давайте разбираться вместе. В этой статье расскажу о средствах защиты браузера и о том, что он может от вас скрывать в процессе кроссдоменных запросов. Фича: об ошибках будем говорить в картинках 🙂
SOP – Same Origin Policy
Рассмотрим кейс. Мы заходим на какой-то незнакомый сайт, созданный потенциальным злоумышленником. Внешне пока не видим ничего подозрительного, но пока мы находимся на этом сайте, злобный скрипт уже готовит запрос к серверу банка, в котором мы залогинены, и пытается получить наши данные:
Как же браузер пытается нас от этого защитить? Он использует Политику одинакового источника: Same Origin Policy (SOP).
В тех случаях, когда запрос отправляется на ресурс, у которого отличается домен / порт / протокол, – браузер по умолчанию понимает, что он кроссдоменный и применяет политику безопасности:
CORS – Cross Origin Resource Sharing
Что же делать в том случае, когда нам необходимо разрешить для браузера взаимодействие между различными ресурсами?
Браузер должен отправить в запросе заголовок:
Сервер проверит, откуда к нему пришёл запрос, и (если этот домен разрешён) в ответе вернёт заголовок:
Браузер может запретить доступ к некоторым заголовкам ответа из кода, ничего не сообщив при этом разработчику.
Так получается, потому что по умолчанию при кроссдоменных запросах браузер разрешает чтение только следующих заголовков ответа:
Поэтому в network вкладке браузера мы видим абсолютно все интересующие нас заголовки, а из кода JS они будут нам недоступны.
Источник
How to use CORS in Node.js with Express
May 6, 2021
Node.js is an open-source and cross-platform runtime used when executing JavaScript code on the server-side. One of the popular Node.js server frameworks is Express. Implementing CORS in Node.js helps you access numerous functionalities on the browser.
Express allows you to configure and manage an HTTP server to access resources from the same domain.
The three parts that form an origin are protocal, domain, and port.
Today, there are many applications that depend on APIs to access different resources. Some of the popular APIs include weather, time, and fonts. There are also servers that host these APIs and ensure that information is delivered to websites and other end points. Therefore, making cross-origin calls, is a popular use case for the modern web application.
Let’s say accessing images, videos, iframes, or scripts from another server. This means that the website is accessing resources from a different origin or domain. When building an application to serve up these resources with Express, a request to such external origins may fail. This is where CORS comes in to handle cross-origin requests.
This guide will help you learn how to configure CORS with Express.
Prerequisites
To follow this article along, prior knowledge of Node.js and Express is essential.
What is CORS?
CORS stands for Cross-Origin Resource Sharing . It allows us to relax the security applied to an API. This is done by bypassing the Access-Control-Allow-Origin headers, which specify which origins can access the API.
In other words, CORS is a browser security feature that restricts cross-origin HTTP requests with other servers and specifies which domains access your resources.
Check this guide to learn more about the CORS policy.
How CORS works
An API is a set procedure for two programs to communicate. This means that API resources are consumed by other clients and servers.
Here are two scenarios:
The client and the server have the same origin. In this example, accessing resources will be successful. You’re trying to access resources on your server, and the same server handles the request.
The client and server have a different origin from each other, i.e., accessing resources from a different server. In this case, trying to make a request to a resource on the other server will fail.
This is a security concern for the browser. CORS comes into play to disable this mechanism and allow access to these resources. CORS will add a response header access-control-allow-origins and specify which origins are permitted. CORS ensures that we are sending the right headers.
Therefore, a public server handling a public API will add a CORS related header to the response. The browser on the client machine will look at this header and decide whether it is safe to deliver that response to the client or not.
Setting up CORS with Express
Let’s create a very basic Express HTTP server endpoint that serves a GET response.
Make sure you have Node.js runtime installed and run npm init -y to start your simple express server project. To use CORS within a Node.js application, you need the cor package provided by the Node.js NPM registry. Go ahead and install CORS alongside the following other packages using the below command.
Creating a simple Express GET request
Below is a simple index.js express server.
The code above depicts a simple HTTP server using Express. Check this guide and learn how to create one.
Run the server with npm nodemon . Navigate to http://localhost:6069/ingredients on your browser. You will be served with these ingredients text items.
In this example, cross-origin is allowed because you’re currently on the same domain, and you are executing this request from the same domain.
Let’s now try to get the ingredients using the fetch command.
I am going to execute that same request but from another site instead. In this case, I used https://www.section.io .
Open https://www.section.io on your browser and execute the following fetch request from the browser’s console using a Fetch API.
Make sure the server is up and running before performing the request above.
We are fetching the ingredients information from another origin domain. The origin of this URL is not the one allowed to receive this response from this server. Therefore, it will throw the below CORS error.
To solve this error, we need to add the CORS header to the server and give https://www.section.io access to the server response.
Include the following in your index.js file.
If you now perform the fetch command, it should work fine.
However, if a fetch request is made from another web page, it will fail and throw the following error.
This means that you only have access to our server’s resources. You can have an array of these multiple origins, as shown below.
Nevertheless, the API can be public, and any cross-origin APIs and servers can access these resources. The code block below will ensure any page can access the ingredient resources.
The Asterisk symbol will create the CORS header, and any origin can, therefore, get the response of this localhost server.
Since a specific origin is not defined here, app.use(cors()) will also get this done.
You can also have dynamic origins. These are whitelisted origins that have access to your API. This could be used to pull resources from a database.
Let’s say you have different accounts, i.e. developer accounts, and you might want them to access the API. To have this dynamic whitelisting, use this origin function which returns these domains individually.
Performing more requests
An express server has many specific ways of managing CORS to determine what other servers and APIs can be accessed.
For example, a server is comprised of several methods. However, not every method should be exposed to other origins. Thus, within CORS middleware, you can specify which methods can be accessed by the CORS policy.
These methods include GET , POST , DELETE , UPDATE , and OPTIONS .
You can even specify which routes of your server can be accessed.
Use case
Let’s say you’re using React to build a front-end application. Eventually, you’ll be connecting it to a back-end API. The app might run into an issue if CORS is not set up. Simply because both the front end and the back end are from different origins from each other.
CORS goes hand in hand with APIs. A good use case scenario of CORS is when developing RESTful APIs. For example, creating a Node.js RESTful API, similar to this RESTful Web API in Node.js using PostgresSQL and Express.
Conclusion
When you deploy an application on the server, you should not accept requests from every domain. Instead, you should specify which origin can make requests to your server.
This way, you are able to block users who attempt to clone your site or make requests from an unauthorized servers. This is important an security measure. Check this CORS NPM registry and learn more on where to use CORS in your Express application.
Источник
Всем привет!
Меня зовут Радик, я frontend developer компании Creative. И сегодня я хочу поднять тему, которая касается и фронта и бэка, и окружает нас с вами каждый день. Речь пойдёт об ошибках CORS и как их можно обойти.
Уверен, что многим разрабам знакома ситуация, когда ты работаешь над приложением, оно запущено локально, и тебе нужно сделать из него запросы к различным удалённым ресурсам. В этот момент «что-то идёт не так», и ты видишь на своём экране миллион ошибок в консоли браузера. Почему они появляются? Давайте разбираться вместе. В этой статье расскажу о средствах защиты браузера и о том, что он может от вас скрывать в процессе кроссдоменных запросов. Фича: об ошибках будем говорить в картинках
SOP – Same Origin Policy
Рассмотрим кейс. Мы заходим на какой-то незнакомый сайт, созданный потенциальным злоумышленником. Внешне пока не видим ничего подозрительного, но пока мы находимся на этом сайте, злобный скрипт уже готовит запрос к серверу банка, в котором мы залогинены, и пытается получить наши данные:
Как же браузер пытается нас от этого защитить? Он использует Политику одинакового источника: Same Origin Policy (SOP).
В тех случаях, когда запрос отправляется на ресурс, у которого отличается домен / порт / протокол, – браузер по умолчанию понимает, что он кроссдоменный и применяет политику безопасности:
CORS – Cross Origin Resource Sharing
Что же делать в том случае, когда нам необходимо разрешить для браузера взаимодействие между различными ресурсами?
Браузер должен отправить в запросе заголовок:
**origin: htttps://good-website.com**
Сервер проверит, откуда к нему пришёл запрос, и (если этот домен разрешён) в ответе вернёт заголовок:
**access-control-allow-origin: htttps://good-website.com**
ACAH – Access-Control-Allow-Headers
Браузер может запретить доступ к некоторым заголовкам ответа из кода, ничего не сообщив при этом разработчику.
Так получается, потому что по умолчанию при кроссдоменных запросах браузер разрешает чтение только следующих заголовков ответа:
-
Cache-Control
- Content-Language
- Content-Length
- Content-Type
- Expires
- Last-Modified
- Pragma
Поэтому в network вкладке браузера мы видим абсолютно все интересующие нас заголовки, а из кода JS они будут нам недоступны.
Для того чтобы браузер разрешил доступ к этим заголовкам, в ответе должен быть указан заголовок Access-Control-Allow-Headers.
В нём нужно перечислить заголовки, доступ к которым разрешён браузером:
Специальное значение * позволяет разрешить для использования любые заголовки, но только в том случае, если в изначальном запросе нет cookie или данных аутентификации. В противном случае оно будет рассматриваться как буквальное имя заголовка «*».
Proxy как одно из возможных решений проблемы при локальной разработке
Рассмотрим ещё один кейс. Нам нужно сделать кроссдоменный запрос из приложения, которое развёрнуто локально. Но такой запрос в нужный нам момент не обрабатывается должным образом на сервере. Картинка для понимания.
Как быть? Можно запустить локальный proxy сервер, который будет пересылать данные между нашим приложением и сервером, добавляя необходимые заголовки:
Можно сделать простой proxy сервер на Node.js для решения проблемы с кроссдоменными запросами:
- Для этого переходим в директорию, в которой вы хотите создать прокси сервер
- Инициализируем Node.js проект командой npm init
- Устанавливаем необходимые пакеты командой npm install cors express http-proxy-middleware
- Создаём файл index.js со следующим содержимым:
-
Запускаем proxy сервер командой node index.js
- Теперь мы можем использовать адрес и порт, указанный в proxy сервере в приложении во время разработки.
На этом всё. Мы рассмотрели причины возникновения ошибки CORS и одно из возможных решений при локальной разработке на фронте. Надеюсь, мой материал будет вам полезен. Буду рад продолжить обсуждение темы в комментариях. Всем хорошего дня и поменьше ошибок CORS!
6 min read
You’ve created an API with Express and you’re busy adding some JavaScript to your front end which will make requests to it. Everything is going great until you load up the front end in your browser and you see a weird error like this in the console:
Access to fetch at 'https://your-api.com/user/1234' from origin 'https://your-website.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Perhaps you’ve then tried setting the request’s mode to no-cors
as the error message suggests, but the request to the API still doesn’t work. Even after a bunch of Googling, it’s hard to wrap your head around why this is happening or how to get around it.
The good news is that there’s a library for Express which you can use to help fix these CORS errors, but before we look at fixing them, what do they actually mean? In order to understand these errors, let’s take a look at what CORS is.
What is CORS and why is it ruining your day?
CORS stands for Cross-Origin Resource Sharing, and it’s something which is supported by all modern browsers. It’s a bit of a mouthful, so we’re going to break it down first, and then we can learn about what it actually does.
What is a «resource»?
A resource is the content which is available at a specific URL e.g. an HTML web page, an image, or a JSON API response. It’s effectively the «stuff» which makes up the world wide web.
What is an «origin»?
The origin for a resource is the protocol + domain + port e.g. for the URL https://your-api.com:8080/user/1234
the origin is https://your-api.com:8080
. If the URL doesn’t contain a port, then the origin will just be the protocol + domain.
What does Cross-Origin Resource Sharing actually do?
Cross-Origin Resource Sharing is the way in which a web browser ensures that the front end JavaScript of a website (origin A) can only access resources from another origin (origin B) if that origin explicitly allows it to. If it does allow it, then the resource is shared – you guessed it – cross-origin! Phew, we got there in the end.
CORS can help prevent malicious websites from accessing and using data from places that they shouldn’t be. When you see those annoying CORS errors in your browser, it’s actually your web browser doing its best to protect you from what it has identified as a potentially malicious request.
How does CORS work?
The way in which a web browser figures out whether a resource is allowed to be shared cross-origin is by setting an Origin
header on requests made by front end JavaScript. The browser then checks for CORS headers set on the resource response. The headers it will check for on the response depend on the type of request which the browser has made, but the response must at least have the Access-Control-Allow-Origin
header set to an allowed value for the web browser to make the response available to the front end JavaScript which requested it.
An example CORS request
An example of a cross-origin request would be a GET
request made with fetch from the front end JavaScript on your web page – which is hosted on one domain (origin A) – to an API endpoint which you host on a different domain (origin B).
The request made by the browser from the JavaScript on your web page at https://your-website.com/user-profile
would contain this information:
> GET /user/1234 HTTP/1.1
> Host: your-api.com
> Origin: https://your-website.com
The Origin
request header is automatically set by the web browser – for security reasons you are not able to set its value when you make the request with fetch
.
In order for the example CORS request above to work correctly, the response from your API would need to look like this:
< HTTP/1.1 200 OK
< Access-Control-Allow-Origin: https://your-website.com
< Vary: Origin
< Content-Type: application/json; charset=utf-8
<
{"name":"Existing Person"}
Notice how the value of the Access-Control-Allow-Origin
response header matches the value of the Origin
response: https://your-website.com
. The web browser will see this CORS response header and determine that it has permission to share the response content with the front end JavaScript on your web page.
Now we have a better idea of what CORS is and what it does, it’s time to set some CORS headers and fix the errors you’re getting on your web page.
How to set CORS headers and get rid of those annoying errors
As you saw in the example above, it’s important for the web browser to send the Origin
header in the request that it makes to your API, but it’s your API which needs to send the all important Access-Control-*
headers in the response. These CORS headers are what will tell the web browser whether or not it is allowed to make the response from your API available to your front end JavaScript.
The library you’re going to use to help fix the CORS errors you’ve been battling is the cors middleware package. Head to the directory containing your Express application in your terminal, and let’s get it installed:
npm install cors
Note: In this blog post I’m linking to the
cors
package on GitHub instead of npm as at the time of writing the documentation for this package is out-of-date on on npm.
Once it’s installed, you need to require it in your application (directly after you require express
is fine):
const cors = require("cors");
If you call the cors
middleware in your Express application without passing any configuration options, by default it will add the CORS response header Access-Control-Allow-Origin: *
to your API’s responses. This means that any origin — i.e. a web page on any domain — can make requests to your API. Unless you’re building an API for the general public to use, this is not the behaviour you want, so let’s jump right in to configuring the cors
middleware so that only your website can make CORS requests to your API:
/**
* These options will be used to configure the cors middleware to add
* these headers to the response:
*
* Access-Control-Allow-Origin: https://your-website.com
* Vary: Origin
*/
const corsOptions = {
origin: "https://your-website.com"
};
/**
* This configures all of the following routes to use the cors middleware
* with the options defined above.
*/
app.use(cors(corsOptions));
app.get("/user/:id", (request, response) => {
response.json({ name: "Existing Person" });
});
app.get("/country/:id", (request, response) => {
response.json({ name: "Oceania" });
});
app.get("/address/:id", (request, response) => {
response.json({ street: "Gresham Lane", city: "Lakeville" });
});
Typically you’ll want to enable CORS for all of the routes in your Express application as in the example above, but if you only want to enable CORS for specific routes you can configure the cors middleware like this:
/**
* These options will be used to configure the cors middleware to add
* these headers to the response:
*
* Access-Control-Allow-Origin: https://your-website.com
* Vary: Origin
*/
const corsOptions = {
origin: "https://your-website.com"
};
// This route is using the cors middleware with the options defined above.
app.get("/user/:id", cors(corsOptions), (request, response) => {
response.json({ name: "Existing Person" });
});
// This route is using the cors middleware with the options defined above.
app.get("/country/:id", cors(corsOptions), (request, response) => {
response.json({ name: "Oceania" });
});
/**
* We never want this API route to be requested from a browser,
* so we don't configure the route to use the cors middleware.
*/
app.get("/address/:id", (request, response) => {
response.json({ street: "Gresham Lane", city: "Lakeville" });
});
Enabling «complex» CORS requests
The examples above configure CORS for simple GET requests. For many other types of CORS requests, a CORS «preflight» request will be made by web browsers before the actual CORS request. This preflght request uses the OPTIONS
HTTP method and it helps the browser determine whether it will be allowed to make the CORS request.
The cors
middleware provides instructions for Enabling CORS Pre-Flight, and allows you to configure the headers that you want to send in the response to a preflight request.
Fear CORS no more
Hopefully this article has helped you understand what CORS is all about, but there will always be times where it’s difficult to figure out how you need to configure things for a CORS request to work. Here are some things that have helped me out along the way:
- Will it CORS? — This fantastic tool will ask you about what you want to do, and then tell you the exact CORS response headers that you need to send for the CORS request to work correctly.
- CORS HTTP headers — A handy reference which lists all of the CORS headers which you can use.
- Simple requests and Preflighted requests — The CORS documentation on the Mozilla Developer Network has great explanations of the different types of CORS requests.
- Path of an XMLHttpRequest(XHR) through CORS — This flowchart on Wikipedia is a helpful visual tool for understanding when a CORS request is considered «complex».
- Fetch standard: HTTP extensions — This documentation covers the nitty gritty details of how CORS is implemented in the browser Fetch API.
Happy cross-origin resource sharing!