Ajouter le support CORS à votre application TypeScript + Express

April 07, 2021
Rédigé par
Mia Adjei
Twilion
Révisé par

Ajouter le support CORS à votre application TypeScript + Express

Imaginez : vous venez de construire une excellente API à l'aide de Node.js, Express et TypeScript. Vous avez également créé une application Web côté client et tout est prêt pour la lancer dans votre navigateur, la mettre en relation avec votre serveur et, espérons-le, la partager avec le monde entier.

Ouvrez une fenêtre de navigateur et accédez à l'emplacement où votre application est exécutée, puis ouvrez la console dans vos outils de développement. Votre application effectue son premier appel d'API à votre serveur... mais au lieu des données auxquelles vous vous attendez, une erreur comme celle ci-dessous s'affiche dans votre console :

Access to fetch at 'http://localhost:5000/rooms' 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.

La tuile ! Cette erreur est due au CORS (Cross-Origin Resource Sharing, ou partage de ressources entre origines multiples). Bien que cela puisse être frustrant, c'est une situation que rencontrent bon nombre de devs.

Mais qu'est-ce qu'un CORS ? Comment contourner ce message d'erreur et récupérer les données de votre serveur dans votre application ? Ce tutoriel vous explique comment ajouter le support CORS à votre API TypeScript + Express, pour continuer à avancer dans vos projets passionnants.

Qu'est-ce que le CORS ?

Le CORS, ou Cross-Origin Resource Sharing (partage de ressources d'origines multiples) est un protocole de sécurité dans les navigateurs modernes qui permet ou empêche le partage de ressources entre différentes origines, selon l'origine qui a lancé la requête HTTP.

Une origine décrit l'endroit depuis lequel une requête est lancée. Les origines comportent deux parties obligatoires, scheme (schéma) et hostname (nom d'hôte), et une partie facultative, port, comme illustré ci-dessous :

https://www.twilio.com
  ^       ^
  |       |
scheme hostname


http://localhost:5000
  ^       ^       ^
  |       |       |
scheme hostname  port

Le navigateur ajoute un en-tête Origin (Origine) à toutes les requêtes qu'il effectue. Lorsqu'une requête arrive sur le serveur, si son origine est incluse dans la liste des origines autorisées à récupérer des ressources de ce serveur, ce dernier ajoute un en-tête Access-Control-Allow-Origin à sa réponse pour informer le navigateur que le contenu est accessible à cette origine spécifique.

Par exemple, la ligne suivante montre que toutes les origines sont autorisées à demander des ressources :

Access-Control-Allow-Origin : *

Cependant, l'en-tête ci-dessous indique au navigateur que seules les requêtes de https://www.twilio.com sont des ressources autorisées :

Access-Control-Allow-Origin : https://www.twilio.com

Vous utilisez probablement différents ports au cours de votre travail de développement local. Si vous examinez l'exemple de message d'erreur de l'introduction de ce post, vous pouvez y voir que l'application est diffusée dans localhost:3000, mais tente de récupérer des données à partir de localhost:5000. Comme les deux ports sont différents, cela signifie qu'ils proviennent de différentes origines. Par défaut, le navigateur refuse cette requête :

Access to fetch at 'http://localhost:5000/rooms' 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.

Pour résoudre ce problème et permettre aux données de circuler entre votre serveur et votre client, vous pouvez ajouter le support CORS à votre serveur. Pour ce tutoriel, vous utiliserez le package npm cors pour ajouter un middleware qui définit l'en-tête Access-Control-Allow-Origin et spécifie les domaines autorisés à accéder aux ressources de votre serveur.

Si vous souhaitez en savoir plus sur le CORS, consultez la documentation Mozilla à ce sujet.

Configuration du CORS dans votre serveur Express

Pour commencer, vous aurez besoin des éléments suivants :

Les informations CORS de ce tutoriel peuvent être utilisées pour n'importe quel projet Express. Toutefois, dans le cadre de cet exemple, vous pouvez suivre avec le code du projet Express indiqué ci-dessus. Cette API vidéo est conçue avec Express et TypeScript, ce qui en fait un excellent exemple de projet.

Si vous suivez l'exemple de projet, suivez les instructions du fichier‌README.md‌du répertoire pour être opérationnel.

Une fois que vous avez exécuté la commande npm run start, vous devriez voir une instruction log sur votre terminal vous indiquant que votre serveur s'exécute sur le port 5000 :

Express server listening on port 5000

Si vous utilisez plutôt votre propre API Express, c'est bon aussi ! Vos requêtes cURL seront probablement différentes, alors remplacez les paramètres qui sont adaptés à votre projet.

Exécuter une simulation avec une commande cURL

Si vous utilisez l'exemple de code du répertoire ci-dessus, ouvrez une deuxième fenêtre de terminal et essayez d'exécuter la commande cURL suivante :

curl -H "Origin: http://localhost:3000" --head http://localhost:5000/rooms

Avec cette commande cURL, vous simulez la manière dont le navigateur émet une requête. Dans ce cas, votre serveur s'exécute sur http://localhost:5000 et votre application s'exécute sur localhost:3000, d'où elle effectue une requête. Dans cet exemple, votre « application » tente de demander une liste de salles de conversations vidéo.

La réponse qui s'affiche dans la fenêtre de votre terminal sera semblable à celle ci-dessous :

HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin
Content-Type: application/json; charset=utf-8
Content-Length: 52
ETag: <ETag>
Date: Tue, 30 Mar 2021 16:45:54 GMT
Connection: keep-alive
Keep-Alive: timeout=5

Si vous examinez ce résultat, vous remarquerez qu'il n'y a pas d'en-tête Access-Control-Allow-Origin dans cette réponse. S'il s'agissait d'une réponse véritablement reçue par un navigateur, celui-ci bloquerait la requête.

Il est temps de mettre à jour votre serveur afin qu'il réponde avec l'en-tête Access-Control-Allow-Origin pour les requêtes spécifiques d'origines multiples.

Ajout du package npm cors à votre projet Express

Dans la fenêtre de votre terminal, accédez à la racine de votre projet. Si vous suivez l'exemple de code, la racine du projet est le répertoire express-video-api.

Installez le package cors et ses types TypeScript en exécutant les commandes suivantes :

npm install cors
npm install --save-dev @types/cors

Si vous examinez le fichier package.json, vous verrez que cors a été ajouté en tant que dependency (dépendance) et que @types/cors a été ajouté à devDependencies.

Configuration des options CORS

Ouvrez ensuite le fichier qui constitue le point d'entrée de votre application. Si vous suivez l'exemple de code, ce fichier s'appelle src/index.ts.

Dans votre éditeur de code, sous la ligne où vous avez importé express, importez également cors :

import cors from 'cors';

Ajoutez la ligne suivante au-dessus de app.use(express.json()); pour permettre à votre serveur Express d'utiliser le middleware cors :

app.use(cors); /* NEW */

app.use(express.json());

Ajoutez ensuite la liste des origines que vous souhaitez autoriser à accéder aux ressources sur votre serveur et transmettez cette liste à vos options CORS. Dans ce tutoriel, vous allez ajouter localhost:3000 comme origine que vous souhaitez autoriser :

// Add a list of allowed origins.
// If you have more origins you would like to add, you can add them to the array below.
const allowedOrigins = ['http://localhost:3000'];

const options: cors.CorsOptions = {
  origin: allowedOrigins
};

Transmettez ensuite ces options comme argument pour votre middleware cors :

app.use(cors(options));

Votre serveur Express remarquera les modifications et la mise à jour.

À ce stade, si vous suivez l'exemple de projet, votre code doit ressembler à celui ci-dessous :

import express from 'express';
import cors from 'cors';
import config from './config';
import roomsRouter from './routes/room';
import { Twilio } from 'twilio';

// Initialize Twilio client
const getTwilioClient = () => {
  if (!config.TWILIO_ACCOUNT_SID || !config.TWILIO_API_KEY || !config.TWILIO_API_SECRET) {
    throw new Error(`Unable to initialize Twilio client`);
  }
  return new Twilio(config.TWILIO_API_KEY, config.TWILIO_API_SECRET, { accountSid: config.TWILIO_ACCOUNT_SID })
}

export const twilioClient = getTwilioClient();

const app = express();

// Add a list of allowed origins.
// If you have more origins you would like to add, you can add them to the array below.
const allowedOrigins = ['http://localhost:3000'];

const options: cors.CorsOptions = {
  origin: allowedOrigins
};

// Then pass these options to cors:
app.use(cors(options));

app.use(express.json());

// Forward requests for the /rooms URI to our rooms router
app.use('/rooms', roomsRouter);

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

 

Test du bon fonctionnement du CORS

Maintenant que vous avez configuré les options CORS sur votre serveur, essayez à nouveau d'exécuter la simulation de commande cURL suivante dans votre terminal :

curl -H "Origin: http://localhost:3000" --head http://localhost:5000/rooms

Si vous vérifiez la réponse, vous remarquerez qu'il y a désormais un en-tête Access-Control-Allow-Origin avec l'origine http:://localhost:3000 ! Cela signifie que, lorsque vous exécutez votre application côté client sur localhost:3000, l'application est en mesure de récupérer des ressources à partir de votre serveur.

HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Content-Type: application/json; charset=utf-8
Content-Length: 52
ETag: <ETag>
Date: Tue, 30 Mar 2021 16:46:39 GMT
Connection: keep-alive
Keep-Alive: timeout=5

Pour un autre test, essayez également d'exécuter la commande cURL suivante :

curl -H "Origin: http://localhost:4000" --head http://localhost:5000/rooms

Notez que, dans cette commande, vous avez modifié l'origine de votre requête pour afficher http://localhost:4000, qui ne figurait pas dans votre liste d'origines autorisées. La réponse renvoyée n'a pas l'en-tête Access-Control-Allow-Origin :

HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin
Content-Type: application/json; charset=utf-8
Content-Length: 52
ETag: <ETag>
Date: Tue, 30 Mar 2021 16:40:47 GMT
Connection: keep-alive
Keep-Alive: timeout=5

Cela signifie que, si quelqu'un tente d'accéder à votre serveur à partir d'une application exécutée sur localhost:4000, il ne pourra pas accéder aux ressources. Au lieu de cela, une erreur CORS semblable à la précédente s'affiche dans sa console.

Quelle est la prochaine étape de votre projet Express API ?

Si vous souhaitez consulter l'intégralité de l'exemple de code mis à jour dans ce tutoriel, vous le trouverez dans la branche added-cors (CORS ajouté) de ce répertoire sur GitHub. Si vous souhaitez simplement accéder à un aide-mémoire sur la façon d'implémenter le CORS dans votre application, consultez le gist.

Maintenant que vous savez comment ajouter le support CORS à votre serveur de TypeScript + Express, vous avez tout ce qu'il faut pour connecter votre serveur à une application côté client. À quel type d'application pensez-vous ? J'ai hâte de voir ce que vous allez construire !

Mia Adjei est développeuse de logiciels au sein de l'équipe Developer Voices. Son rôle consiste à aider les devs à créer de nouveaux projets et à connaître de grands moments de satisfaction. Vous pouvez contacter Mia à l'adresse : madjei [at] twilio.com.