Logo JS express

Les serveurs d'API sont partout: chaque fois que vous vous connectez ou actualisez une application Web, votre navigateur envoie des demandes pour les dernières données. Nous allons voir comment cela est géré en coulisse et comment vous pouvez coder votre propre serveur API.

Qu'est-ce qu'un serveur API et comment fonctionne-t-il?

Voici un exemple. Vous avez une application Web qui doit se connecter à une base de données et récupérer des données, comme les publications faites par les utilisateurs sur un site de réseau social. Vous ne pouvez évidemment pas permettre aux utilisateurs de se connecter directement à votre serveur de base de données, car c'est une énorme faille de sécurité qui laisse les détails de connexion dans votre application.

La solution est de placer un serveur au milieu qui prend les requêtes de l'utilisateur, les interprète, puis interroge en toute sécurité la base de données pour les informations demandées. L'utilisateur n'a jamais à voir la base de données; en fait, il est souvent exécuté dans un sous-réseau privé pour le rendre inaccessible à partir de tout sauf de vos serveurs API.

Cela permet aux clients d'accéder à vos données en toute sécurité via HTTP / HTTPS. Étant donné que le serveur API vous appartient et que vous le contrôlez, cette connexion peut être sécurisée plus facilement. Cependant, vous aurez toujours besoin d'une forme d'authentification pour vérifier que les utilisateurs sont connectés comme ils prétendent être.

Une configuration de serveur API

Le serveur d'API n'est pas censé faire le gros du travail sur votre site Web. Pour la plupart des contenus statiques, vous souhaiterez utiliser un serveur Web traditionnel comme NGINX, qui sera beaucoup plus performant. Par exemple, vous diffuserez index.html et bundle.js en utilisant votre serveur NGINX, que le client décompressera et exécutera. L'application JavaScript côté client fera ensuite une demande au serveur API, qui la traitera à partir de là.

Vous pouvez créer des serveurs API avec n'importe quelle langue. Tout ce dont vous avez besoin est la capacité d'écouter et de répondre aux requêtes HTTP, ainsi que la possibilité de vous connecter à une base de données, les deux ayant de nombreuses bibliothèques pour n'importe quelle langue. Dans ce guide, nous utiliserons JavaScript avec Node.JS, Express pour HTTP et la gestion des itinéraires. Une autre option populaire utilisant C # est ASP.NET de Microsoft.

Si vous utilisez AWS, vous voudrez peut-être examiner API GateWay d'AWS. Plutôt que d'exécuter un serveur d'API complet, API GateWay fournit une solution gérée bon marché qui peut servir d'interface pour les fonctions Lambda et RDS.

Configuration d'un serveur API avec Express.JS

Express.JS est un framework d'application Web qui s'exécute sur Node (JavaScript côté serveur). Il est très simple à utiliser et se marie bien avec les applications JavaScript côté client.

Créez un nouveau dossier pour le serveur et exécutez npm init pour configurer votre package.json. Créer App.jset collez ce qui suit dans:

const express = require ('express')
const app = express ()
port const = 3000

app.get ('/', (req, res) => res.send ('Message du gestionnaire d'itinéraire Express: Hello World!'))

app.listen (port, () => console.log (`Exemple d'application écoutant sur le port $ {port}!`))

Ceci est le passe-partout de base pour un simple serveur Express. Le serveur lui-même est créé avec Express(). Après cela, les routes et leurs fonctions de gestionnaire associées sont enregistrées. Dans ce cas, app.get ('/', gestionnaire) enregistre une fonction de gestionnaire pour les requêtes GET sur le / route. Il y a autres fonctions de gestion pour les autres verbes HTTP, comme POST et PUT.

Dans le gestionnaire, le demande objet représente le Requête HTTP, avec res représentant la réponse. ensuite res.send renverra des données de base, comme une chaîne ou un objet JSON. Vous pouvez également utiliser Express comme serveur Web traditionnel avec res.sendFile, mais nous vous recommandons d'utiliser un natif pour les performances avec un objet statique.

Pour commencer, vous pouvez exécuter nœud App.js, mais nodemon est mieux car il surveillera le fichier de base pour les modifications et redémarrera automatiquement.

npm i -g nodemon

nodemon app.js

Si vous visitez localhost: 3000 dans votre navigateur, vous devriez voir une réponse express aux demandes.

En plus des multiples fonctions de gestionnaire, vous pouvez également correspond à de nombreux itinéraires différents. Le routage explicite est simple:app.get ('/ utilisateurs') traitera les demandes adressées à /utilisateurs. Vous pouvez également faire correspondre les itinéraires en utilisant caractères génériques et expressions régulières. Vous pouvez même gestionnaires de routeurs nest; par exemple, créer un nouveau gestionnaire spécifiquement pour un sous-répertoire comme '/utilisateurs', qui est distincte de l'application principale et généralement stockée et exportée à partir de son propre fichier.

Cependant, tout cela est toujours servi via HTTP, donc la première mise à niveau consistera à configurer HTTPS. C'est facile à gérer; tout ce dont vous aurez besoin est votre clé privée SSL et votre certificat. Si vous ne faites que tester, vous pouvez générer un certificat auto-signé à l'aide de openssl:

openssl req -nodes -new -x509 -keyout server.key -out server.cert

Vous devrez faire confiance manuellement à ce certificat lorsque Chrome paniquera, mais cela fonctionnera. Plutôt que d'appeler écoute app, nous allons configurer le serveur HTTPS, lui transmettre l'application, puis écouter cela.

const express = require ('express')
var https = require ('https')
var fs = exiger ('fs')

const app = express ()
port const = 3000

app.get ('/', (req, res) => res.send ('Message du gestionnaire d'itinéraire Express: Hello World!'))

https.createServer ({
    clé: fs.readFileSync ('server.key'),
    cert: fs.readFileSync ('server.cert')
  }, application)
  .listen (port, () => console.log (`Exemple d'application écoutant sur le port $ {port}!`))

Connexion d'une base de données

Cette étape dépend de votre base de données spécifique, mais en réalité, elle n’a rien de spécial. Tout ce que vous avez à faire est d’installer le pilote Node.JS pour votre base de données, de fournir les détails de connexion à Express et de vous y connecter comme vous le feriez à partir de JavaScript normal (ou de tout autre langage que vous utilisez pour créer votre serveur API).

Pour ce guide, nous utiliserons MongoDB, une base de données de documents JSON souvent associée à Express. Si vous avez Docker, vous pouvez l'exécuter dans un conteneur pour le tester:

docker run -d -p 27017-27019: 27017-27019 --nom mongodb mongo: 4.0.4

Vous pouvez utiliser Boussole MongoDB pour s'y connecter et effectuer des tâches administratives.

Du côté express, vous devrez installer le package MongoDB NPM pour vous y connecter.

npm installer mongodb

Parce que nous ne voulons pas qu'Express démarre tant que la base de données n'est pas connectée, nous allons déplacer app.listen () à l'intérieur de MongoClient.connect ().

const express = require ('express')
var https = require ('https')
var fs = exiger ('fs')
const MongoClient = require ('mongodb'). MongoClient

const app = express ()
port const = 3000

app.get ('/', (req, res) => res.send ('Message du gestionnaire d'itinéraire Express: Hello World!'))

var db;
MongoClient.connect ('mongodb: // localhost: 27017 /', (err, client) => {
  if (err) retourne console.log (err)
    db = client.db ('test') // quel que soit le nom de votre base de données

  https.createServer ({
    clé: fs.readFileSync ('server.key'),
    cert: fs.readFileSync ('server.cert')
  }, application)
  .listen (port, () => console.log (`Exemple d'application écoutant sur le port $ {port}!`))
})

Vous pouvez maintenant vous connecter à Mongo en utilisant le db variable et toute méthode standard. Vous voudrez vous assurer d'utiliser asynchroniser / attendre cependant, ou vous retournerez des promesses non gérées.

app.get ('/', async (req, res) => {
  réponse const = attendre db.collection ('test'). find (). toArray ();
  res.send (réponse)
})

Cela se connecte à la base de données, renvoie le contenu du tester collection et le recrache en tant que tableau JSON.

Étant donné qu'Express n'est que l'interface pour ces fonctions, vous n'avez pas à définir toute votre logique dans ce seul fichier. Vous pouvez le diviser en modules et importer ce que vous devez appeler à partir des gestionnaires d'itinéraire Express.

Mise en cache des demandes d'API pour les performances

Express n’est pas la solution la plus rapide. Si vous prévoyez de l'utiliser en production, vous souhaiterez probablement mettre en œuvre une forme de mise en cache afin qu'il n'ait pas à effectuer de recherches coûteuses sur des demandes répétables.

Une chose à noter est que vous ne devez jamais mettre en cache tout ce qui nécessite une authentification pour afficher, comme les informations personnelles d'un utilisateur. La règle générale est que si la page est la même pour tout le monde, vous pouvez la mettre en cache pour tout le monde. Les méthodes PUT, DELETE et POST ne doivent jamais être mises en cache.

Vous pouvez utiliser un stockage en mémoire comme Redis pour cela, mais un simple cache mémoire fonctionne assez bien. Installer cache-mémoire de npm:

npm i mémoire cache

Puis dans App.js, créez un nouveau middleware de mise en cache avant vos routes:

const cache = require ('cache-mémoire');

let memCache = nouveau cache.Cache ();
laissez cacheMiddleware = (durée) => {
  return (req, res, suivant) => {
    let key = '__express__' + req.originalUrl || req.url;
    laissez cacheContent = memCache.get (clé);
    if (cacheContent) {
      res.send (cacheContent);
      revenir;
    } autre {
      res.sendResponse = res.send;
      res.send = (corps) => {
        memCache.put (clé, corps, durée * 1000);
        res.sendResponse (corps);
      }
      suivant()
    }
  }
}

Ensuite, sur les routes que vous pouvez mettre en cache, vous pouvez utiliser ce middleware avant le gestionnaire principal, pour mettre en cache les résultats pour X secondes:

app.get ('/ produits', cacheMiddleware (30), function (req, res) {
  ...
});
//]]>