Publié par

Il y a 1 mois -

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 :

$ npm install

Pour démarrer l’application il suffit de lancer la commande :

$ npm start

Cette commande est configurée dans le package.json :

{
  ...
  "scripts": {
    "start": "parcel src/index.html",
    ...
  },
}

Pour lancer le server en https, il suffit juste d’ajouter l’option --https :

{
  ...
  "scripts": {
    "start": "parcel src/index.html --https",
    ...
  },
}

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

// 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);

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 :

// package.json
{
 ...
 "scripts": {
   ...,
   "start": "node setupProxy.js",
 }
}

Dans notre cas, tous les appels d’API que nous ferons dans notre application devront donc commencer par le préfixe /api :

import axios from 'axios';

async function getFoo() {
 try {
   const result = await axios.get('/api/foo-path');
   // Handle result
 } catch (error) {
   // Do error handling
 }
}

La requête de cet appel sera :

GET http://localhost:8080/foo-path

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 :

https.createServer([options][, requestListener])

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 :

$ openssl req -x509 -nodes -newkey rsa:4096 -keyout private.pem -out primary.crt

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(..)

const fs = require('fs')

const serverOpts = {
   key: fs.readFileSync('/path/to/private.pem'),
   cert: fs.readFileSync('/path/to/primary.crt'),
}

Utiliser parcel-bundler

Le but ici est d’utiliser la fonctionnalité de parcel-bundler pour générer les certificats auto-signés.

const generateCertificate = require('parcel-bundler/lib/utils/generateCertificate')

Cette fonction prend en paramètre un objet :

const options = {
 cacheDir: '.cache/',
 cache: true,
}

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é.

generateCertificate(options)

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.

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);

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 :

// 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))

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 …

Publié par

Commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.