Utiliser des APIs Web avec fetch

Objectifs: Ce TP a pour un double objectif :

  • vous familiariser avec les requêtes réseau depuis une application WEB en utilisant l'API fetch de JavaScript

  • au travers de l'utilisation de fetch comprendre la mise en oeuvre de la programmation asynchrone en JavaScript à l'aide des Promesses

Documentations fetch et sur les promesses JavaScript

Dans ce TP vous allez travailler avec l'API OpenWeather. OpenWeather API est une interface de programmation d'application (API) fournie par OpenWeather, une entreprise qui fournit des informations météorologiques mondiales. L'API permet aux développeurs de créer des applications qui utilisent des données météorologiques en temps réel, telles que les prévisions météorologiques actuelles, les prévisions à court terme et à long terme, les données historiques, les alertes météorologiques, les données de qualité de l'air, et bien plus encore.

Le site web d'OpenWeather https://openweathermap.org/

En utilisant l'API OpenWeather, les développeurs peuvent accéder à des données météorologiques précises et fiables pour n'importe quelle région du monde, ainsi que pour des intervalles de temps spécifiques. Ces données sont fournies dans un format JSON ou XML, ce qui les rend facilement utilisables pour la création d'applications météorologiques pour les ordinateurs de bureau, les smartphones, les tablettes et les autres appareils.

L'API OpenWeather offre également une variété de fonctionnalités, telles que la possibilité de personnaliser les requêtes pour récupérer des données spécifiques, de fournir des données historiques pour une période spécifique, de recevoir des alertes météorologiques en temps réel, et bien plus encore.

1. Obtenir une clé d'API

Pour utiliser l'API OpenWeather, vous devez d'abord vous inscrire sur le site web d'OpenWeather pour obtenir une clé d'API (API key) qui vous permettra d'accéder aux données météorologiques. Une fois que vous aurez votre clé d'API, vous pourrez utiliser l'API en envoyant des requêtes HTTP à l'URL de l'API, qui est https://api.openweathermap.org/data/2.5/weather.

Pour vous inscire rendez-vous à l'URL https://home.openweathermap.org/users/sign_up Le processus d'inscription est très simple.

S'inscrire sur le site web d'OpenWeather

Une fois votre adresse mail confirmée et votre compte créé vous pouvez accéder à votre clé d'API qui vous sera nécessaire pour effectuer des requêtes auprès de OpenWeatherMap.

Récupérer votre clé d'API

Attention : La validation de la clé n'est pas immédiate. Il se peut qu'il vous faille attendre un délai de quelques minutes à quelques heures avant que votre clé ne soit pleinement activée.

1. Tester une API avec l'outil Postman

Postman est un outil de développement web qui permet d'exécuter des appels HTTP directement depuis une interface graphique. Il est utilisé pour interagir avec une API et est un outil de référence dans le monde du développement Web. Avec Postman, vous pouvez facilement effectuer des requêtes HTTP via une interface graphique, choisir l'URL et la méthode HTTP (GET, POST, PUT, PATCH, DELETE ...), définir les en-têtes de requête (headers), fixer ls valeurs des éventuels paramètres de requête (query params) et dans certains cas fournir le corps (bodyde la requête ¹.

Postman est disponible en plusieurs versions, dont une version gratuite et une version payante. La version gratuite de Postman (Postman Free) est destinée aux développeurs individuels et aux petites équipes. Elle offre des fonctionnalités de base telles que la création de requêtes HTTP, la gestion des environnements, la documentation des API, etc. C'est avec cette version que nous allons expérimenter.

Pour utiliser Postman, il faut tout d'abord vous enregister sur le site de Postman. Ensuite vous pouvez l'utiliser soit depuis un application à installer sur votre ordinateur, soit depuis d'une application web dans votre navigateur. Il existe depuis peu un extension Postman pour VSCode (elle est actuellement en béta test) qui permet de développer et tester votre API directement depuis VSCode. C'est cette dernière que nous allons utiliser pour ce TP.

Installer l'extension Postman pour VSCode

  1. Avant tout créez un répertoire AWA et dans celui-ci un répertoire TP02 dans lequel vous rangerez le travaillé effectué au cours de ce TP,

  2. Placez vous dans ce répertoire et lancez VS Code

  3. Installez l'extension Postman comme indiqué sur la figure ci-dessous.

    installation de l'extension Postman pour VS Code
    Installation de l'extension Postman pour VS Code.
  4. Une fois l'extension installée, lancez-la et connectez vous avec Postman. Si vous n'avez pas encore de compte Postman, créez-en un.

    Lancement de l'extension et connexion à Postman
    Lancement de l'extension et connexion à Postman.

Créer et exécuter une requête

  1. Créez une nouvelle collection que vous nommerez OpenWeather API, elle vous peremttra de regrouper les requêtes liées à cette API.

    Créer une nouvelle collection
    Créer une nouvelle collection.
  2. Dans cette collection créez une nouvelle requête que vous nommerez Current Weather

    Créer une nouvelle requête
    Créer une nouvelle requête.
  3. l'url suivante https://api.openweathermap.org/data/2.5/weather?q=Paris&appid=<votre clé api> où vous remplacerez <votre clé api> par la clé d'API que vous avez obtenue lorsque vous vous êtes enregistré sur le site d'OpenWeather.

    Définir et envoyer une requête
    Définir et envoyer une requête.
  4. Consultez la documentation de cette API afin de comprendre le format des données produites. Pour cela rendez-vous à l'URL https://openweathermap.org/current.

    Documentation de l'API
    Documentation de l'API.
  5. Vous avez pu constater que la valeur pour la température est plutôt étrange. Cela vient du fait que par défaut les mesures de températures sont exprimés en ° Kelvin. Consultez la documentation de l'API pour trouver comment obtenir des températures en ° Celsius et modifiez votre requête en conséquence afin de régler ce problème.

    Correction

    il suffit d'ajouter le paramètre units avec la valeur metric à l'URL de la requête

    const apiUrl = `https://api.openweathermap.org/data/2.5/weather?q=Paris&appid=${apiKey}&units=metric`;
  6. Faites de même pour que la description des conditions météorologiques ne soit plus en anglais mais en français.

2. Appeler l'API Current Weather Data depuis JavaScript

Maitenant que vous avez compris le fonctionnement et le paramétrage de la requête pour obtenir la météo courrante, vous allez effectuer cette requête depuis du code JavaScript, dans un premier temps avec node.js

  1. Postman permet de générer du code afin d'effecuer la requête depuis différents outils et différents langages de programmation. Générez le code pour JavaScript.

    Documentation de l'API
    Documentation de l'API.
  2. Créez un fichier javascript testOpenWeather.js et copiez dans celui-ci le code (Code snippet) généré par Postman. Exécutez testOpenWeather.js depuis un terminal et vérifiez qu'il fonctionne correctement.

    Génération du code JavaScript
    Documentation de l'API.
  3. Le programme affiche la réponse au format texte. Modifiez le afin de lire la réponse au format JSON et d'afficher la description des conditions météo, la température courante et la date et l'heure où les données ont été calculées.

    Affichage des données météo
    Affichage des données météo.

3. Afficher dans une page web la météo d'un lieu

Dans un premier temps vous allez faire une page HTML très simple qui lorsqu'elle est chargée affiche la météo d'un lieu fixé en dur dans le code de la page.

  1. Créez un fichier HTML weather1.html et ajoutez le code suivant dans l'élément body :

  2. <body>
        <h1>Météo de Paris</h1>
        <ul>
            <li>
                <p>Date : <span id="date"></span></p>
            </li>
            <li>
                <p>Description : <span id="description"></span></p>
            </li>
            <li>
                <p>
                    Température : <span id="température"></span>
                </p>
            </li>
        </ul>
        <script src="weather1.js"></script>
    </body>
  3. Créez un fichier JavaScript nommé weather1.js dans lequel vous recopierez le code de testOpenWeather.js réalisé à l'exercice 2.

  4. Modifiez le code JavaScript afin de ne plus afficher les données sur la console mais dans les éléments prévus à cet effet dans la page HTML.

  5. Enregistrez les deux fichiers et ouvrez le fichier HTML dans votre navigateur. Vérifiez que les données météorologiques pour Paris s'affichent correctement sur la page.

    La page weather1.html
  6. Dans le code JavaScript on utilise le nom de la ville pour spécifier le lieu à considérer dans la requête. Vous avez peut être remarqué que cet usage du nom du lieu est déprécié (deprecated) et qu'il est conseillé d'utiliser plutôt des coordonnées géographiques (latitude et longitude). Modifiez votre requête pour remplacer le paramètre q=Paris par les données de latitude et longitude de cette ville (latitude : 48° 51′ 24″ nord, longitude 2° 21′ 07″ est).

  7. Correction

    il suffit de remplacer le paramètre q par les deux paramètres lat et lon. Par contre il faut transformer les coordonnées géographiques de DMS (Degrés Minutes Secondes) en DD (Degrés Décimaux).

    const apiUrl = `https://api.openweathermap.org/data/2.5/weather?lat=48.85667&lon=2.35194&appid=${apiKey}&units=metric`;

    Pour faire la conversion DMS vers DD il existe beaucoup de convertisseurs en ligne, comme par exemple celui de EDDMaps

    convertisseur DMS vers DD
    EDDMaps : convertisseur coordonnées DMS vers DD

    Par contre il se peut que le résultat soit légèrement différent de celui obtenu en donnant le nom du lieu

    Comparaison des résultats
    Comparaison des résultats

4. Détecter automatiquement votre position

4.1 utiliser Geolocation.getCurrentPosition

HTML5 propose une API JavaScript de géolocalisation pour obtenir la position géographique d'un ordinateur, d'un téléphone ou d'une tablette, ce qui permet aux contenus Web d'accéder à leur localisation. Un site internet ou une application mobile peut alors offrir divers services liés à la localisation de l'utilisateur.

La méthode Geolocation.getCurrentPosition() fournit la position actuelle de l'appareil. Consultez sa documentation puis modifiez votre code pour ne plus afficher la météo de Paris lorsque la page est chargée, mais celle correspondant à la position de votre ordinateur. Le résultat attendu est le suivant

Météo locale
Obtention des conditions météo associées à votre géolocalisation

Pour ne pas casser votre travail fait dans l'exercice précédent, faites une copie des fichiers weather1.html et weather.js vers de nouveaux fichiers weather2.html et weather2.js que vous modifierez pour faire cet exercice.

Correction

La méthode Geolocation.getCurrentPosition() qui fournit la position actuelle de l'appareil est une méthode aynchrone, il faut donc intégrer le traitement effectuant la requête à OpenWeather API dans la fonction callback passée en paramètre de l'appel à getCurrentPosition().

Le code de weather2.js

const apiKey = "a08807a5e6c7223bf1c221f8f87580a4";
const apiUrl = `https://api.openweathermap.org/data/2.5/weather?appid=${apiKey}&units=metric`;

const options = {
	// les options pour Geolocation.getCurrentPosition
	enableHighAccuracy: true,
	timeout: 5000,
	maximumAge: 0,
};

navigator.geolocation.getCurrentPosition(success, error, options);

//---------------------------------------------------------------------
// fonctions utilisées par le programme ci-dessus
//---------------------------------------------------------------------

/**
 * Fait une requête sur WeatherMap API pour obtenir les conditions météorologiques
 * actuelles en un lieu donné et affiche le résultat dans la page HTML
 * @param {number} latitude  latitude du lieu
 * @param {string} longitude longitude du lieu
 * @param {string} elementId l'id de l'élement HTML où doit être affiché le résultat
 */
function afficherMeteo(latitude, longitude, elementId) {
	// Effectuer une requête à l'API OpenWeatherMap
	fetch(apiUrl + `&lat=${latitude}&lon=${longitude}`)
		.then(response => response.json())
		.then(data => {
			// Récupérer les données de température et de description du temps
			const temperature = data.main.temp;
			const description = data.weather[0].description;

			// Afficher les données dans la page HTML
			const weatherElement = document.getElementById(elementId);
			weatherElement.innerHTML = `Vous êtes à (lat=${latitude}, lon=${longitude}).
                   Il fait actuellement ${temperature} degrés Celsius avec ${description}.`;
		})
		.catch(error => console.error(error));
}

/**
 * Callback pour getCurrentPosition en cas de succès
 * @param {Position} pos la position retrouvée
 */
function success(pos) {
	let crd = pos.coords;
	// trace sur la console
	console.log("Votre position actuelle est :");
	console.log(`Latitude : ${crd.latitude}`);
	console.log(`Longitude : ${crd.longitude}`);
	console.log(`La précision est de ${crd.accuracy} mètres.`);
	// utiliser les coordonnées obtenues pour récuperer la méto et afficher
	// les résultats dans la page Web
	afficherMeteo(crd.latitude, crd.longitude, "weather");
}

/**
 * Callback pour getCurrentPosition en cas d'échec
 * @param {Error} err l'erreur détectée
 */
function error(err) {
	// trace sur la console
	console.warn(`ERREUR (${err.code}): ${err.message}`);
	// affiche un message sur la page HTML
	const weatherElement = document.getElementById(elementId);
	weatherElement.innerHTML = `Erreur lors de la géolocalisation de votre appareil ${err.message} (code : ${err.code})`;
}

La fonction Geolocation.getCurrentPosition() étant asynchrone, il faut lui transmettre le traitement à effectuer lorsque la géolocalisation est acquise au travers d'une fonction callback. On peut reprocher à cette manière un éventuel manque de clarté, le traitement étant enfoui dans la fonction callback. Une alternative est de transformer cette fonction en une promesse (Promisification en anglais) ce qui donnerait le code suivant.

const apiKey = "a08807a5e6c7223bf1c221f8f87580a4";
const apiUrl = `https://api.openweathermap.org/data/2.5/weather?appid=${apiKey}&units=metric`;

const options = {
	// les options pour Geolocation.getCurrentPosition
	enableHighAccuracy: true,
	timeout: 5000,
	maximumAge: 0,
};

geolocalisation()
	.then((coord) => afficherMeteo(coord.latitude, coord.longitude, "weather"))
	.catch((err) => {
		const weatherElement = document.getElementById('weather');
		weatherElement.innerHTML = `Erreur lors de la géolocalisation de votre appareil
		    ${err.message} (code : ${err.code})`;
	}
	);

//---------------------------------------------------------------------
// fonctions utilisées par le programme ci-dessus
//---------------------------------------------------------------------

/**
 * Fait une requête sur WeatherMap API pour obtenir les conditions météorologiques
 * actuelles en un lieu donné et affiche le résultat dans la page HTML
 * @param {number} latitude  latitude du lieu
 * @param {string} longitude longitude du lieu
 * @param {string} elementId l'id de l'élement HTML où doit être affiché le résultat
 */
function afficherMeteo(latitude, longitude, elementId) {
	// Effectuer une requête à l'API OpenWeatherMap
	fetch(apiUrl + `&lat=${latitude}&lon=${longitude}`)
		.then(response => response.json()})
		.then(data => {
			// Récupérer les données de température et de description du temps
			const temperature = data.main.temp;
			const description = data.weather[0].description;

			// Afficher les données dans la page HTML
			const weatherElement = document.getElementById(elementId);
			weatherElement.innerHTML = `Vous êtes à (lat=${latitude}, lon=${longitude}).
                   Il fait actuellement ${temperature} degrés Celsius avec ${description}.`;
		})
		.catch((error) => {
			console.error(error);
		});
}

/**
 * Permet d'obtenir de manière asynchrone la géolocalisation de l'appareil
 * @returns une Promesse qui lorsqu'elle sera résolue (c'est à dire la géolocalisation obtenue) 
 *      aura pour 
 */
function geolocalisation() {
	return new Promise(function (resolve, reject) {
		/**
		 * Callback pour getCurrentPosition en cas de succès
		 * @param {GeolocationCoordinates} pos un objet de type GeolocationCoordinates (voir la doc de MDN
		 *   https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates)
		 */
		function success(pos) {
			let crd = pos.coords;
			// trace sur la console
			console.log("Votre position actuelle est :");
			console.log(`Latitude : ${crd.latitude}`);
			console.log(`Longitude : ${crd.longitude}`);
			console.log(`La précision est de ${crd.accuracy} mètres.`);
			// la promesse est tenue on renvoie les coordonnées géographiques
			resolve(crd);
		}

		/**
		 * Callback pour getCurrentPosition en cas d'échec
		 * @param {Error} err l'erreur détectée
		 */
		function error(err) {
			// trace sur la console
			console.warn(`ERREUR (${err.code}): ${err.message}`);
			// affiche un message sur la page HTML
			const weatherElement = document.getElementById(elementId);
			// la promesse est rompue on renvoie l'erreur
			reject(err);
		}

		navigator.geolocation.getCurrentPosition(success, error, options);
	});
}

Vous remarquerez que pour pouvoir accéder aux fonctions callback resolve et reject de la promesse créée les fonctions success et error passées en paramètre de la méthode getCurrentPosition() sont déclarées dans l'executor (la fonction anonyme) passé en paramètre du constructeur de la promesse.

4.2 déterminer le nom du lieu avec l'API de géocodage d'OpenWeather

Plutôt que d'afficher les coordonnées géographiques de l'endroit où votre appareil a été géolocalisé, on souhaiterait afficher le nom du lieu.

Météo locale
Obtention des conditions météo associées à votre géolocalisation avec affichage du nom du lieu

Modifiez votre code précédent pour aboutir à ce résultat. Pour obtenir le nom du lieu OpenWeatherMap propose une API de geocodage inversée.

Correction

Pour obtenir le résultat attendu, nous allons refactoriser la méthode afficherMeteo() afin de pouvoir lui faire réaliser deux appels à l'API d'OpenWeather (un pour obtenir les conditions météorologiques, l'autre pour obtenir le nom du lieu associé à votre géolocalisation) et ensuite procéder à l'affichage.

/**
 * Fait une requête sur WeatherMap API pour obtenir les conditions météorologiques
 * actuelles en un lieu donné et affiche le résultat dans la page HTML
 * @param {number} latitude  latitude du lieu
 * @param {string} longitude longitude du lieu
 * @param {string} elementId l'id de l'élement HTML où doit être affiché le résultat
 */
function afficherMeteo(latitude, longitude, elementId) {

	Promise.all(
		[
			recupererConditionsMeteo(latitude, longitude),
			recupererNomDuLieu(latitude, longitude)
		]
	).then(function (res) {
		// Afficher les données dans la page HTML
		const weatherElement = document.getElementById(elementId);
		weatherElement.innerHTML = `Vous êtes à ${res[1]}.
                   Il fait actuellement ${res[0].temperature} degrés Celsius avec ${res[0].description}.`;
	});
}

On utilise la méthode statique Promise.all() afin de pouvoir effectuer en parallèle les deux requêtes via OpenWeather API. Les promesses passées en paramètre de cette méthode sont retournées par les fonctions recupererConditionsMeteo et recupererNomDuLieu.

/**
 * @param {number} latitude  latitude du lieu
 * @param {string} longitude longitude du lieu
 * @returns {Promise} une promesse qui si elle est résolue (fulfilled) a pour
 *       valeur un objet avec deux attributs
 *       - temperature : la température en degrés Celsius
 *       - description : une description (en anglais) des conditions météo
 */
function recupererConditionsMeteo(latitude, longitude) {
	return fetch(currentWeatherAPIUrl + `&lat=${latitude}&lon=${longitude}`)
		.then( response =>  response.json())
		.then( data => {
			// Récupérer les données de température et de description du temps
			const temperature = data.main.temp;
			const description = data.weather[0].description;
			return { temperature, description }
		});
}

/**
 * @param {number} latitude  latitude du lieu
 * @param {string} longitude longitude du lieu
 * @returns {Promise} une promesse qui si elle est résolue (fulfilled) a pour
 *       valeur le nom du lieu
 */
function recupererNomDuLieu(latitude, longitude) {
	return fetch(reverseGeocodingAPIUrl + `&lat=${latitude}&lon=${longitude}`)
		.then(response =>  response.json())
		.then(data => data[0].name); // Renvoyer le nom du lieu
}

5. Utiliser l'API de géocodage d'OpenWeather

5.1 Météo en n'importe quel lieu

On veut maintenant permettre à l'utilisateur de consulter la météo pour n'importe quel lieu.

météo en n'importe quel lieu
Recherche de la météo en n'importe quel lieu

Créez une page HTML weather3.html et le script associé weather3.js afin d'avoir l'affichage et le comportement définis sur la figure ci-dessus.

Correction

Le code HTML weather3.html

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AWA TP2</title>
    <link rel="icon" type="image/png" href="../ukraine-icon.png">
</head>
<body>
    <h1>Météo</h1>
    <p>
        Consultez la météo de la localité de votre choix
    </p>
    <div>
        <label for="">Localité : </label>
        <input type="text" id="nom-localite" placeholder="nom de la localité">
        <button id="searchBtn">Chercher</button>
    </div>
    <p id="weather"></p>
    <script src="weather3.js"></script>
</body>
</html>

Le code javavascript weather3.js

const apiKey = "a08807a5e6c7223bf1c221f8f87580a4";
const currentWeatherAPIUrl = `https://api.openweathermap.org/data/2.5/weather?appid=${apiKey}&units=metric`;
const geocodingAPIUrl = `https://api.openweathermap.org/geo/1.0/direct?appid=${apiKey}`;

document.getElementById("searchBtn").addEventListener("click", function() {
	afficherMeteo(document.getElementById("nom-localite").value, "weather");
} );

//---------------------------------------------------------------------
// fonctions utilisées par le programme ci-dessus
//---------------------------------------------------------------------
/**
 * Fait une requête sur WeatherMap API pour obtenir les conditions météorologiques
 * actuelles en un lieu donné et affiche le résultat dans la page HTML
 * @param {number} latitude  latitude du lieu
 * @param {string} longitude longitude du lieu
 * @param {string} elementId l'id de l'élement HTML où doit être affiché le résultat
 */
function afficherMeteo(name, elementId) {
	
	console.log("name " + name + " elementId" + elementId);
	fetch(geocodingAPIUrl + `&q=${name}`)
		.then( response => response.json()) // Renvoie les données du résultat de la requête au format JSON
		.then(data => { 
			const latitude = data[0].lat;
			const longitude = data[0].lon; 
			return fetch(currentWeatherAPIUrl + `&lat=${latitude}&lon=${longitude}`)
		})
		.then(response => response.json())
		.then(data => {
			// Récupérer les données de température et de description du temps
			const temperature = data.main.temp;
			const description = data.weather[0].description;
			// Afficher les données dans la page HTML
			const weatherElement = document.getElementById(elementId);
			weatherElement.innerHTML = `A  ${name} il fait actuellement ${temperature}
                             degrés Celsius avec ${description}.`;
		})
		.catch( err => {
			const weatherElement = document.getElementById(elementId);
			weatherElement.innerHTML = `Erreur ${err.message}`;
		});
}

5.2 Améliorer les messages d'erreur

Que se passe-t-il si le nom de la localité est inconnu ? On voudrait que le programme produise l'affichage suivant

erreur : localté inconnue
Affichage d'un message d'erreur quand la localité est inconnue

Si nécessaire modifiez votre programme pour obtenir l'affichage ci dessus en cas d'erreur sur le nom de la localité.

Correction

Si l'on prend le programme donné en solution de l'exercice précédent, la vidéo ci-dessous vous montre et vous explique ce qu'il se passe si le nom de la localité n'est pas reconnu

Erreur sur le nom de la localité

Comme indiqué dans la vidéo explicative précédente il suffit donc de détecter si tableau résultat de la requête à l'API de géocodage inversé est vide ou non. Si il est vide on lance une erreur avec un message explicite pour l'utilisateur.

function afficherMeteo(name, elementId) {
	fetch(geocodingAPIUrl + `&q=${name}`)
		.then( response => response.json()) // résultat de la requête au format JSON
		.then(data => { 
if (data.length === 0) { // le tableau est vide // aucune localité a été trouvée à ce nom throw new Error(`Aucune localité connue au nom de ${name}`) }
const latitude = data[0].lat; const longitude = data[0].lon; return fetch(currentWeatherAPIUrl + `&lat=${latitude}&lon=${longitude}`) }) .then(response => response.json()) // résultat de la requête au format JSON .then(data => { // Récupérer les données de température et de description du temps const temperature = data.main.temp; const description = data.weather[0].description; // Afficher les données dans la page HTML const weatherElement = document.getElementById(elementId); weatherElement.innerHTML = `A ${name} il fait actuellement ${temperature} degrés Celsius avec ${description}.`; }) .catch( err => { const weatherElement = document.getElementById(elementId); weatherElement.innerHTML = `Erreur: ${err.message}`; }); }

6. Combiner Github API et OpenWeather API

Exercice Facultatif, pour ceux qui veulent aller plus loin

Trop fatigué ! On verra demain ;-)