Il y a 3 ans -
Temps de lecture 7 minutes
Gérer les problématiques de Cross Domain (CORS) en développement avec Parcel
Introduction
Parcel, au même titre que Webpack, permet de packager une application web afin de la distribuer pour la production, avec une promesse zéro configuration.
Démarrage rapide
Le but de ce chapitre, n’est pas d’entrer en détail dans le fonctionnement de Parcel, mais de montrer comment démarrer rapidement un projet avec Parcel.
Pour ce faire, il existe plusieurs boilerplates sur Github, mais avec l’application createapp, le bootstraping d’un projet est facilité. On va simplement préciser ce dont on a besoin et cliquer sur « Download » pour télécharger une archive contenant la base de notre application.
Installer les dépendances en lançant la commande suivante :
[bash]$ npm install[/bash]
Pour démarrer l’application il suffit de lancer la commande :
[bash]$ npm start[/bash]
Cette commande est configurée dans le package.json
:
[js]{
…
"scripts": {
"start": "parcel src/index.html",
…
},
}[/js]
Pour lancer le server en https, il suffit juste d’ajouter l’option --https
:
[js]{
…
"scripts": {
"start": "parcel src/index.html –https",
…
},
}[/js]
Cette option va générer automatiquement des certificats auto-signés et lancer le serveur de développement en https.
Proxy
Maintenant que nous avons vu comment démarrer rapidement un projet Parcel, et comment le lancer en https, entrons dans le vif du sujet.
Pourquoi utiliser un proxy ?
Pendant la phase de développement, lorsqu’une application front hébergée sur un certain domaine tente de faire des appels API vers un autre domaine, ces requêtes seront bloquées par la “Cross Domain Policy”.
Il est possible avec les CORS (Cross-Origin Resource Sharing), d’autoriser, côté API, les requêtes venant d’un ou plusieurs domaines. Mais pendant cette phase de développement, il est fastidieux de devoir jouer avec ce type de configuration. D’autant plus que si un développeur décide de changer le port de son application pour une raison ou une autre, ses appels API seront bloqués. Utiliser un proxy dans ce cas, permet donc de manière transparente de transmettre une requête spécifique vers une URL spécifique.
Ce proxy ne sera évidemment applicable qu’en développement et ne devra pas être utilisé en production.
Proxy avec Express
Pour faire fonctionner le proxy avec Parcel, il est nécessaire à l’heure actuelle, d’utiliser le framework Express et d’ajouter le package parcel-bundler
en tant que middleware. Nous allons également utiliser le package http-proxy-middleware
pour définir le proxy.
Dans un premier temps, créons un fichier bootstrap : setupProxy.js
[js]// setupProxy.js
const proxy = require(‘http-proxy-middleware’)
const Bundler = require(‘parcel-bundler’)
const express = require(‘express’)
const bundler = new Bundler(‘src/index.html’);
const app = express();
app.use(proxy(‘/api’, { target: ‘http://localhost:8080’, pathRewrite: { ‘^/api’: » } }));
app.use(bundler.middleware());
app.listen(1234);[/js]
Ceci nous permet de définir un proxy sur le chemin ayant pour racine /api
vers l’url http://localhost:8080
. L’option pathRewrite
telle qu’elle est définie ici, va simplement supprimer le /
api
de la requête qui sera faite à l’API.
Nous allons, par la suite, utiliser ce script comme point d’entrée de notre application. La commande devient donc :
[js]// package.json
{
…
"scripts": {
…,
"start": "node setupProxy.js",
}
}[/js]
Dans notre cas, tous les appels d’API que nous ferons dans notre application devront donc commencer par le préfixe /api
:
[js]import axios from ‘axios’;
async function getFoo() {
try {
const result = await axios.get(‘/api/foo-path’);
// Handle result
} catch (error) {
// Do error handling
}
}[/js]
La requête de cet appel sera :
[text]GET http://localhost:8080/foo-path[/text]
Et hop ! Notre application peut désormais faire des requêtes à notre API sans avoir à configurer les cross origins dans celle-ci.
Activer SSL
Voyons maintenant comment activer https tout en gardant le proxy que nous avons mis en place.
Nous allons utiliser le module https
de NodeJS pour créer un serveur. La méthode qui nous permet de créer ce serveur est la suivante :
[js]https.createServer([options][, requestListener])[/js]
Parmis les options que nous allons passer à la méthode createServer
, celles qui vont nous intéresser sont key
pour la clé privée et cert
pour le certificat. On va utiliser des certificats auto-signés, cela sera suffisant pour la phase de développement. Pour les générer, deux méthodes s’offrent à nous, utiliser OpenSSL ou un utilitaire de parcel-bundler.
OpenSSL
Voici la commande pour générer ces deux fichiers :
[bash]$ openssl req -x509 -nodes -newkey rsa:4096 -keyout private.pem -out primary.crt[/bash]
Détaillons les paramètres passés à l’outil :
req
: cette commande permet de gérer les Certificate Signing Request (CSR)-x509
: permet de générer un certificat auto-signé-nodes
: pas de chiffrement de la clé privée-newkey
: permet de créer une nouvelle demande de certificat et une nouvelle clé privée-keyout
: définit le nom du fichier de la clé privée-out
: définit le nom du fichier du certificat
Cette commande nous génère deux fichiers private.pem
et primary.crt
que nous pourrons passer à la méthode createServer(..)
[js]const fs = require(‘fs’)
const serverOpts = {
key: fs.readFileSync(‘/path/to/private.pem’),
cert: fs.readFileSync(‘/path/to/primary.crt’),
}[/js]
Utiliser parcel-bundler
Le but ici est d’utiliser la fonctionnalité de parcel-bundler
pour générer les certificats auto-signés.
[js]const generateCertificate = require(‘parcel-bundler/lib/utils/generateCertificate’)[/js]
Cette fonction prend en paramètre un objet :
[js]const options = {
cacheDir: ‘.cache/’,
cache: true,
}[/js]
La première option cacheDir
, permet de définir le chemin du répertoire de cache, dans notre cas nous allons utiliser le chemin de cache par défaut (.cache/).
La deuxième option cache
, prend un booléen et permet d’activer le cache, évitant ainsi de générer à chaque démarrage de l’application les certificats auto-signés ; parcel-bundler va voir que les fichiers sont déjà existants et les utilisera.
Il nous reste plus qu’à appeler cette fonction avec les options définies et le tour est joué.
[js]generateCertificate(options)[/js]
Lancement du serveur
Maintenant que nous avons nos certificats, il faut lancer le serveur de développement avec le module https. Pour cela, il est nécessaire de lire ces certificats avec le module fs
et de les passer en options à la méthode https.createServer
que nous avons vu précédemment.
[js]const fs = require(‘fs’)
const https = require(‘https’)
[…]
const serverOpts = {
key: fs.readFileSync(‘.cache/private.pem’),
cert: fs.readFileSync(‘.cache/primary.crt’),
}
https.createServer(serverOpts, app).listen(1234);[/js]
Nous avons maintenant notre serveur de développement front, qui tourne sur le port 1234 en https.
On assemble le tout
Voici le code du fichier setupProxy.js
en entier :
[js]// setupProxy.js
const proxy = require(‘http-proxy-middleware’)
const Bundler = require(‘parcel-bundler’)
const express = require(‘express’)
const fs = require(‘fs’)
const https = require(‘https’)
const generateCertificate = require(‘parcel-bundler/lib/utils/generateCertificate’)
const options = {
cacheDir: ‘.cache/’,
cache: true,
}
generateCertificate(options);
const serverOpts = {
key: fs.readFileSync(‘.cache/private.pem’),
cert: fs.readFileSync(‘.cache/primary.crt’),
};
const bundler = new Bundler(‘src/index.html’);
const app = express();
app.use(proxy(‘/api’, { target: ‘http://localhost:8080’, pathRewrite: { ‘^/api’: » } }));
app.use(bundler.middleware());
https.createServer(serverOpts, app).listen(Number(process.env.PORT || 1234))[/js]
Conclusion
Nous venons donc de voir comment avec parcel-bundler, express, http-proxy-middleware
et le module https
de Node, monter un serveur de développement en front avec un proxy pour une API, le tout en https. A l’heure où j’écris cet article, parcel-bundler
est toujours en version 1.12.x
, une version 2
semble être en préparation mais je n’ai pas trouvé d’information sur le fait qu’ils intègrent cette fonctionnalité nativement, comme le ferait Webpack
.
À suivre donc …
Commentaire