LIFWEB TP4 - Programmation asynchrone en JavaScript, l’API GitHub

Introduction

On souhaite réaliser une application qui vérifie les projets GitHub d’une liste, pour savoir s’ils sont toujours actifs ou pas. On donne :

La page de départ contient un bouton, une barre de progression, un span pour un compteur et une zone d’affichage Output. On donne une capture ci-après, dans laquelle on a vérifié les projets du fichier TheBody983-starred.json.

Screenshot application finale

On voit que quatre projets sont toujours OK, mais qu’un est KO (le projet n’existe pas sur GitHub). La barre de progression se remplie au fur et à mesure que l’on détermine l’état des projets, on peut le voir sur la démonstration YouTube (avec une version légèrement différente de l’interface et quelques explications).

Fonctionnalités

Avec l’ensemble des exercices, les fonctionnalités suivantes seront réalisées :

  • Téléchargement de l’index des projets.
  • Affichage des informations détaillées des projets.
  • Mise à jour de la barre de progression.
  • Lancement des requêtes en parallèle.
  • Accès à l’API GitHub.
    • Authentification GitHub.
  • Bouton d’arrêt des requêtes.
  • Mise en forme CSS.

Exercice -1 (PRÉPARATION) : environnement de développement

À partir de ce TP et dans tous les suivants, on suit les recommandations du CM5.

  • Copier le fichier package.json à la racine de votre dossier de travail pour cette UE
    • Typiquement, créez au moins un dépôt GitHub/GitLab pour cette UE et y mettre package.json à la racine.
  • Installer ses dépendances avec npm install (ou pnpm install).
    • Ce sont essentiellement des outils de développement qui vous éviteront des erreurs et vous rendront plus productifs.

Configurer votre VSCode avec les plugins suivants :

Le fichier package.json fournit une configuration de départ pour ESlint et Prettier qu’il faudra suivre. Pour tester votre configuration, ouvrez un des TPs précédents, vous devriez voir du rouge et des changements lors du formatage automatique.

⚠️ On attend désormais dans ce TP et les suivants, un code formaté et, sauf exception, sans warnings des linters. ⚠️

Exercice 0 (PRÉPARATION) : barre de progression

Une barre de progression <progress> (MDN) accompagnée d’un <span> est présente dans la page. Cette barre permet d’indiquer l’état d’avancement de la vérification. Exécuter le script suivant ligne par ligne pour comprendre le fonctionnement :

$progressBar.max = 3;
$progressBar.value = 0;
$progressBar.value = 1;
$progressBar.value = 2;
$progressBar.value = 3;

Écrire les fonctions setProgress(total) pour initialiser l’affichage et updateProgress() pour le faire évoluer d’un cran. Avec setInterval écrire une fonction qui incrémente la barre de 1/n à chaque seconde pendant n secondes.

Exercice 1 : vérification de projets GitHub

Les fichiers json fournis sont de tailles croissantes et contiennent des projets invalides :

Quand on clique sur le bouton $goButton, dans la fonction downloadAndCheck(event) à compléter, il faut :

  1. Télécharger le fichier JSON choisi par le $fileSelector avec fetch() (MDN).
  2. Pour chacun des liens contenus, il faut faire une nouvelle requête de type HEAD avec la fonction checkLinkAlive(uri) à compléter.
  3. Au fur et à mesure que les projets répondent, il faut :
    1. Incrémenter la barre de progression de la page avec updateProgress().
    2. Remplir le contenu de $output avec la fonction avec displayLink(link).

Limites du nombre de requêtes

⚠️ Vous êtes limités sur le nombre de requêtes que vous pouvez-faire. Pour l’instant, limitez-vous au plus petit des fichiers TheBody983-starred.json. Cette limitation sera levée dans l’exercice 4. ⚠️

Requêtes CORS

☣️ Le navigateur limite les requêtes autorisées via le mécanisme CORS où le serveur déclare quels sont les domaines autorisés à exécuter du JavaScript. ☣️ Ainsi :

  • Un fetch sur https://github.com/orodio/harness :
    • ✅ est autorisé depuis le navigateur si vous êtes sur https://github.com (ou un nom d’hôte autorisé par GitHub).
    • ❎ est interdit depuis le navigateur si vous êtes sur votre propre serveur de développement http://localhost (ou un nom d’hôte que GitHub n’a pas explicitement autorisé).
    • ✅ est autorisé depuis Node.js, car c’est le navigateur qui limite l’accès pour raison de sécurité, cette restriction n’existe pas en Node.js.
  • Un fetch sur https://api.github.com/repos/orodio/harness
    • ✅ est toujours autorisé depuis le navigateur comme depuis Node.js, car GitHub ne limite pas les accès à ce nom d’hôte.

Ainsi, il est nécessaire de réécrire les URLs pour transformer celles de la forme https://github.com/${USER}/${PROJECT} (qui limite les requêtes via CORS) en celles de la forme https://api.github.com/repos/${USER}/${PROJECT} (qui ne les limite pas). C’est ce que fait le début de la fonction checkLinkAlive(link) fournie. Dans la console, sur l’onglet XHR on pourra voir la liste des fetch semblable à l’image suivante quand les requêtes passent :

Listes des XHR en console

Exercice 2 : Requêtes parallèles

Utiliser Promise.allSettled (MDN) ou Promise.all (MDN) pour lancer les requêtes de vérification en parallèle.

Vous aurez un tableau de promesses qui permettra d’afficher les informations des projets dans l’ordre du fichier json et pas dans l’ordre d’arrivée des réponses.

Ajouter un bouton à l’interface pour choisir si on lance la vérification en parallèle 🚀 ou en série 🐢.

Exercice 3 : Détails des projets

On peut accéder aux informations de ces projets en interrogeant l’API publique https://api.github.com/repos/{owner}/{repo} (documentation), pour obtenir par exemple le nombre d’étoiles actuels de chaque projet et sa date de création.

Améliorer l’affichage des liens de displayLink(link) pour utiliser les informations détaillées fourni par l’API, par exemple pour y faire figurer l’évolution en nombre d’étoiles entre le fichier json et le présent. Le nombre d’étoiles est accessible dans body.stargazers_count et la date de création dans body.created_at.

Exercice 4 (BONUS) : Authentification GitHub

Par défaut, sans authentification, l’API GitHub n’autorise que 60 requêtes par heure et vous recevrez des réponses HTTP 403 si la limite est atteinte :

Si vous êtes authentifié, la limite est beaucoup plus confortable. Pour utiliser l’authentification, il faut :

  • Avoir un compte https://github.com/ 🤔.
  • Créer un token secret sur votre compte GitHub dans les Developer Settings comme indiqué dans la doc. Lors de la création, ne donnez aucun droit, il suffit d’être authentifié, il ne s’agit pas de modifier votre projet ou votre compte. .
  • Passer ce token via l’en-tête HTTP de la forme "Authorization: token ghp_UNE_CHAINE_ALEATOIRE" (MDN) via les options de fetch comme indiqué ici.

Vous aurez alors 5.000 requêtes par heure et vous pourrez accéder aux status de vos projets privés.

Modifier votre projet et vérifier sur le fichier romulusFR-starred.json que vous arrivez bien à lister tous les projets.

Exercice 5 (BONUS) : Interruption des requêtes

Une fois les requêtes fetch lancées, on aimerait pouvoir les interrompre, en particulier s’il y en a plusieurs centaines. Pour cela, l’API propose une fonctionnalité de signal avec la classe AbortController (MDN) et sa propriété AbortController.signal (MDN). Il faut passer le signal en paramètre des options de fetch pour qu’il puisse interrompre la requête (MDN).

Ajouter un bouton 🛑 à l’interface pour interrompre la vérification. Tous les liens qui ont été interrompus apparaitront KO.

Exercice 6 (BONUS) : Styles CSS

Utiliser la librairie CSS https://bulma.io/ pour un rendu moderne en affectant des classes CSS aux éléments de la page HTML et obtenir un rendu comme dans les exemples précédents.

Exercice 7 (AU LONG COURS) : Serveur CTF

Passer le troisième et le quatrième niveaux du CTF sur https://lifweb.univ-lyon1.fr/.