Une API REST serverless avec AWS Lambda et Express

Une API REST serverless avec AWS Lambda et Express

16/04/2018

Dans​‌‍​‌​‌‍​‍ un article précédent je réalisais un état des lieux sur le serverless, sa définition, son mode de fonctionnement, ses implémentations et avantages. Nous allons voir dans cet article comment exposer un service serverless en HTTP en utilisant le service Lambda d’AWS.

AWS (Amazon Web Service) est la branche cloud d’Amazon. Elle offre une galaxie de service vaste permettant d’héberger des machines, des données, des applications, de traiter des données… Un de ces services s’appelle Lambda, il permet de déployer et exécuter des fonctions.

Conception

Pour concevoir notre application, nous allons utiliser Node.js 8.0 et Express.js et je pars du principe que vous avez déjà connaissance de ces Frameworks.

Niveau implémentation, une fonction de type Lambda à besoin d’un point d’entrée dans le code, ce dernier est une fonction recevant les paramètres suivants :

  • event : Les paramètres de l’évènement,
  • context : Le contexte d’exécution,
  • callback : La fonction de rappel pour gérer le succès ou l’échec.

Nous allons donc nous arranger pour que le paramètre event contienne une requête HTTP dé-sérialisée (JSON) pour construire un objet Request que l’on passera à notre application Express. Le résultat généré par L’application est un objet Response qui sera sérialisé en JSON.

Et pour tout besoin, il y a un paquet npm pour ça, je vous présente aws-serverless-express. Cette petite librairie assure le maintien en fonction de l’application Express, la transformation et le passage de la requête ainsi que la récupération et transmission du résultat.

Pour parler du même code et de la même API je vous passe le lien suivant : https://github.com/neoPix/lambda-demo-app. Il s’agit d’un service http très simple qui expose deux routes.

  • hello qui retourne un code 200 avec un message positif
  • excuse qui retourne un message d’erreur

Lambda

L’application ainsi définis est composée de trois fichiers :

  • app.js dans laquelle est créé l’application Express et où sont définis les routes,
  • index.js qui démarre l’application sur un serveur ou en local,
  • aws.js où on retrouve le point de montage de la lambda.

Pour déployer la Lambda, commencez par construire le code en entrant npm run build dans votre terminal. Vous obtiendrez un fichier dist.zip qui sera utile par la suite.

Le processus de création de la Lambda est détaillée ci-dessous.

Chez AWS, chaque élément a un arn. Les biologiestes comprendrons pourquoi ce nom et pour les autres, il s’agit simplement d’une clé unique permettant d’identifier une ressource. Vous en aurez besoin pour la suite et pouvez le trouver dans l’IHM :

ARN de ma Lambda

Gateway HTTP

Une fonction AWS Lambda ne peux pas être appelée directement en HTTP, il est donc nécessaire de mettre entre les deux une interface qui assure la tranformation, mais aussi l’appel de la fonction. AWS dispose d’un service nommé API Gateway qui a précisément ce rôle. Bien que ce dernier puisse se configurer manuellement, nous allons utiliser la documentation swagger pour le faire.

Cette documentation est stockée dans le fichier swagger.api.yaml. Il s’agit d’une description d’API classique à l’exception de la propriété x-amazon-apigateway-integration qui correspond aux options spécifiques à AWS. Vous y retrouvez les options qui permettent de piloter l’exécution.

1
2
3
4
5
uri: "arn:aws:apigateway:eu-west-3:lambda:path/2015-03-31/functions/${functionARN}"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
contentHandling: "CONVERT_TO_TEXT"
type: "aws_proxy"
  • uri la ressource à appeler,
  • passthroughBehavior si le contenue du corps de la requète dois ètre convertis en cas de non connaissance du content-type,
  • httpMethod la méthode d’appel de l’URI,
  • contentHandling la conversion appliquée sur la réponse,
  • type le mode de traitement de la donnée en entrée comme en sortie, ici des objets Request et Response sérialisés en JSON.

Vous noterez une variable dans l’url, vous devez la remplacer par l’ARN de votre Lambda avant la suite. Soit à la main, soit via le script suivant (en pensant bien à remplacer arn:aws:lambda:eu-west-3:070912926965:function:myNewApi par votre ARN) :

1
functionARN='arn:aws:lambda:eu-west-3:070912926965:function:myNewApi' envsubst < swagger.api.yaml > swagger.api.configured.yaml

Le fichier swagger.api.configured.yaml généré sera ensuite utilisé pour la définition de l’API.

La vidéo suivante récapitule le processus d’import.

Vous remarquerez que je réalise une partie des autorisations à la main trollface. Ce n’est pas nécessairement le plus simple je vous l’accorde, mais cette phase est nécessaire pour bien comprendre l’intégration entre les deux parties.

Conclusions

Nous avons donc réussi à déployer une application sur un service 100% dématérialisé qui n’est facturé qu’à l’appel, permettant ainsi de limiter vos coûts d’exploitation 💸 tout en proposant un service fiable et de qualité 👏.

Nous avons repris une application Express qui aurait pu être une application déjà existante et l’avons fait fonctionner sur comme une fonction dans un environnement hautement réplicable 👍.

Nous avons aussi posé les briques élémentaires permettant de déployer le code. Nous verrons plus tard comment automatiser ce déploiement à l’aide de scripts.