Skip to content

API

Introduction

Dans ce chapitre, nous allons explorer le monde des APIs et apprendre à créer une API avec NitroJS. Nous commencerons par comprendre ce qu'est une API et son rôle dans le développement d'applications. Ensuite, nous découvrirons le framework backend Node.js appelé NitroJS, qui nous permettra de créer notre propre API. Nous aborderons également des concepts clés tels que le routage, le file-based routing et la gestion des problèmes de CORS. Enfin, nous apprendrons à héberger notre API sur Vercel et à adapter notre application front-end pour interagir avec notre API à l'aide de fetch.

Qu'est-ce qu'une API ?

Une API (Application Programming Interface) est un ensemble de règles et de protocoles qui permettent à différentes applications de communiquer entre elles. Elle définit les méthodes et les formats de données utilisés pour l'échange d'informations.

Les APIs jouent un rôle essentiel dans le développement d'applications modernes. Elles permettent aux développeurs de créer des fonctionnalités et des services réutilisables, d'intégrer des services tiers et de faciliter l'interopérabilité entre différentes plateformes.

Une API peut prendre différentes formes, telles qu'une API web qui expose des endpoints HTTP pour accéder à des ressources, une API RESTful qui suit les principes de l'architecture REST, ou une API SOAP qui utilise le protocole SOAP pour la communication.

Dans le contexte de notre chapitre, nous allons nous concentrer sur la création d'une API web avec NitroJS, un framework backend Node.js. NitroJS nous permettra de créer des routes et de définir les actions à effectuer pour chaque route.

Routage et File-based Routing avec NitroJS

Le routage est un aspect essentiel de la création d'une API. Il permet de définir les différentes routes de l'API et de spécifier les actions à effectuer pour chaque route.

Dans le cas de NitroJS, le framework backend Node.js que nous utilisons, le routage est géré de manière simple et intuitive grâce au file-based routing.

Le file-based routing consiste à associer chaque route à un fichier spécifique dans l'arborescence du projet. L'URL de la route correspond au chemin du fichier dans le projet.

Par exemple, si nous voulons créer une route /api/personnes, nous allons créer un fichier nommé personnes.ts dans le répertoire approprié de notre projet NitroJS. Dans ce fichier, nous allons définir la logique de notre route.

Voici un exemple de code pour illustrer le file-based routing avec NitroJS :

typescript
// personnes.ts

export default function defineEventHandler(event) {
  // Logique de la route /api/personnes
  // ...
}

NitroJS utilise le framework HTTP h3 pour gérer les requêtes entrantes et les associer aux fichiers de routage correspondants. Lorsqu'une requête est reçue pour une route spécifique, le fichier de routage correspondant est exécuté et la logique de la route est appliquée.

Le file-based routing offre une structure claire et modulaire pour organiser les routes de notre API. Chaque route est définie dans un fichier séparé, ce qui facilite la gestion et la maintenance de l'API.

Gestion des paramètres d'URL

Dans certains cas, nous aurons besoin de gérer des paramètres dans les URLs de nos routes. Par exemple, nous pourrions avoir une route /api/personnes/{id} qui renvoie les informations d'une personne spécifique en fonction de son ID.

Pour gérer les paramètres d'URL dans NitroJS, nous pouvons utiliser des fichiers avec des noms entre crochets pour représenter les paramètres. Par exemple, pour la route /api/personnes/{id}, nous créerions un fichier nommé [id].ts dans le répertoire approprié.

Voici un exemple de code pour illustrer la gestion des paramètres d'URL avec NitroJS :

typescript
// [id].ts

export default function defineEventHandler(event) {
  const id = event.req.params.id;
  // Logique de la route /api/personnes/{id}
  // Utilisation de l'ID pour récupérer les informations de la personne correspondante
  // ...
}

Dans cet exemple, la valeur de l'ID est extraite à partir de event.req.params.id et peut être utilisée dans la logique de la route pour effectuer des opérations spécifiques.

Le file-based routing avec NitroJS offre donc une grande flexibilité pour gérer les paramètres d'URL dans nos routes et créer des APIs puissantes et dynamiques.

Utilisation des Handlers pour renvoyer du contenu dans NitroJS

Dans NitroJS, les handlers sont des fonctions qui définissent la logique à exécuter lorsqu'une route spécifique est appelée. Ils permettent de renvoyer différents types de contenu en réponse à une requête API.

Exemple 1 : Renvoyer du HTML

ts
// /api/index.ts

export default defineEventHandler(async () => {
  return "<h1>Bienvenue dans l'API</h1>";
});

Dans cet exemple, le handler de la route /api renvoie une chaîne de caractères contenant du code HTML. Lorsque cette route est appelée, le contenu HTML sera renvoyé en réponse.

capture d’écran 2023-10-01 223645

Exemple 2 : Renvoyer du JavaScript

ts
// /api/hello.ts

export default defineEventHandler(async () => {
  return { message: 'hello' };
});

Dans cet exemple, le handler de la route /api/hello renvoie un objet JavaScript. Lorsque cette route est appelée, l'objet JavaScript sera renvoyé en réponse.

Les handlers dans NitroJS offrent une grande flexibilité pour générer des réponses personnalisées en fonction des routes appelées. Ils peuvent renvoyer du HTML, du JavaScript, des objets JSON, des tableaux, etc. Cela permet de créer des APIs dynamiques et flexibles.capture d’écran 2023-10-01 223654

Exemple 3 : Récupérer des données à partir d'un fichier JSON

Dans cet exemple, nous avons un fichier /api/personnes/index.ts qui illustre comment récupérer des données à partir d'un fichier JSON à l'aide de la fonction useStorage dans NitroJS.

Le code du fichier /api/personnes/index.ts est le suivant :

typescript
import { Personnes } from './types';
import { useStorage } from '#imports';

export default defineEventHandler(async () => {
  const personnes: Personnes = await useStorage('assets:server').getItem(
    `db/personnes.json`
  );

  return personnes;
});

Dans ce fichier, nous importons le type Personnes à partir du fichier types.ts. Ensuite, nous utilisons la fonction useStorage provenant de #imports pour accéder aux fichiers du dossier assets côté serveur.

La fonction useStorage('assets:server') permet de spécifier le point de montage assets:server pour accéder aux fichiers du dossier assets côté serveur.

Ensuite, nous utilisons la méthode getItem pour récupérer les données du fichier db/personnes.json. Ces données sont typées selon le type Personnes.

Finalement, nous renvoyons les données récupérées en réponse à la requête.

capture d’écran 2023-10-01 223709

Types

Le fichier types.d.ts dans le répertoire /api/personnes définit les types de données utilisés dans notre API pour représenter une personne et une liste de personnes.

ts
export interface Personne {
  id: number;
  prenom: string;
  nom: string;
  date_de_naissance: string;
  avatar: string;
  numero_de_telephone: string;
  adresse_email: string;
  description: string;
}

export type Personnes = Personne[];

Voici une explication des types définis dans ce fichier :

  • Personne : Il s'agit d'une interface qui représente les informations d'une personne. Chaque personne a les propriétés suivantes :

    • id : un identifiant numérique unique pour chaque personne.
    • prenom : le prénom de la personne.
    • nom : le nom de famille de la personne.
    • date_de_naissance : la date de naissance de la personne au format string.
    • avatar : une chaîne de caractères représentant le chemin vers l'avatar de la personne.
    • numero_de_telephone : le numéro de téléphone de la personne.
    • adresse_email : l'adresse e-mail de la personne.
    • description : une description ou une biographie de la personne.
  • Personnes : Il s'agit d'un type qui représente une liste de personnes. Il est défini comme un tableau ([]) de Personne.

En définissant ces types, nous pouvons spécifier la structure des données que nous utilisons dans notre API et nous assurer de leur cohérence lors de l'utilisation et de la manipulation de ces données.

Ces types peuvent être utilisés dans d'autres parties de notre API pour garantir la conformité des données et faciliter le développement en fournissant une documentation claire sur les propriétés et les structures des objets utilisés.

Exemple 4 : Récupérer une personne spécifique à partir de son ID

Dans cet exemple, nous avons le fichier /api/personnes/[id].ts qui illustre comment récupérer une personne spécifique à partir de son ID en utilisant les paramètres d'URL dans NitroJS.

Le code du fichier /api/personnes/[id].ts est le suivant :

ts
import { useStorage } from '#imports';
import { Personnes } from './types';

export default defineEventHandler(async (event) => {
  const id = event.context.params.id;
  const personnes: Personnes = await useStorage('assets:server').getItem(
    `db/personnes.json`
  );

  const personne = personnes.find((p) => p.id === Number.parseInt(id));

  if (!personne) {
    return new Error('person not found');
  }

  return personne;
});

Dans ce fichier, nous utilisons les paramètres d'URL pour récupérer l'ID de la personne à partir de event.context.params.id. Ensuite, nous utilisons la fonction useStorage pour récupérer les données du fichier db/personnes.json.

Nous cherchons ensuite la personne correspondante dans le tableau personnes en utilisant la méthode find et en comparant l'ID avec celui fourni dans l'URL. (Exemple : /api/personnes/1)

Si aucune personne correspondante n'est trouvée, nous renvoyons une instance de l'objet Error avec le message "person not found".

Sinon, nous renvoyons l'objet personne correspondant en réponse à la requête.capture d’écran 2023-10-01 223718

Exemple 5 : Recherche de personnes avec Fuse.js

Dans cet exemple, nous avons le fichier /api/personnes/search.ts qui illustre comment effectuer une recherche de personnes en utilisant la bibliothèque Fuse.js dans NitroJS.

Le code du fichier /api/personnes/search.ts est le suivant :

ts
import { useStorage } from '#imports';
import Fuse from 'fuse.js';

import { Personnes } from './types';

export default defineEventHandler(async (event) => {
  const query = await getQuery(event);
  const q = query.q;

  if (!q) {
    return new Error('q get param is required');
  }

  const personnes: Personnes = await useStorage('assets:server').getItem(
    `db/personnes.json`
  );

  const options = {
    includeScore: true,
    keys: ['prenom', 'nom', 'description'],
  };

  const fuse = new Fuse(personnes, options);

  const results = fuse.search(q);

  if (!results) {
    return new Error('Error while searching for results');
  }

  return results.map((result) => result.item);
});

Dans ce fichier, nous utilisons la bibliothèque Fuse.js pour effectuer une recherche de personnes basée sur une requête spécifique (q). (Exemple : /api/personnes/search?q=ali)

Nous utilisons également la fonction useStorage pour accéder aux données du fichier db/personnes.json.

Nous configurons les options de recherche de Fuse.js en spécifiant les clés (keys) sur lesquelles effectuer la recherche, à savoir 'prenom', 'nom' et 'description'.

Ensuite, nous créons une instance de la classe Fuse en passant les personnes et les options de recherche. Nous utilisons ensuite la méthode search pour effectuer la recherche avec la requête spécifiée.

Les résultats de la recherche sont renvoyés sous forme d'un tableau d'objets, chacun contenant une propriété item qui correspond à une personne trouvée.

Si aucun résultat n'est trouvé, nous renvoyons une instance de l'objet Error avec le message "Error while searching for results".capture d’écran 2023-10-01 223731

Hébergement des fichiers statiques

NitroJS gère les fichiers statiques via le répertoire public/. Tous les fichiers présents dans le répertoire public/ sont automatiquement servis par NitroJS.

Par exemple, si vous avez un fichier image.png dans le répertoire public/, il sera accessible à l'URL /image.png. De même, un fichier video.mp4 dans le répertoire public/ sera accessible à l'URL /video.mp4.

Lorsque vous construisez votre application avec NitroJS, le répertoire public/ est copié dans le répertoire .output/public/ et un manifeste avec les métadonnées est créé. Ce manifeste permet à NitroJS de connaître les fichiers publics sans avoir à analyser le répertoire, ce qui permet d'obtenir de bonnes performances avec les en-têtes de mise en cache.

Par exemple, le manifeste pourrait ressembler à ceci :

json
{
  "/image.png": {
    "type": "image/png",
    "etag": "\"4a0c-6utWq0Kbk5OqDmksYCa9XV8irnM\"",
    "mtime": "2023-03-04T21:39:45.086Z",
    "size": 18956
  },
  "/video.mp4": {
    "type": "video/mp4",
    "etag": "\"9b943-4UwfQXKUjPCesGPr6J5j7GzNYGU\"",
    "mtime": "2023-03-04T21:39:45.085Z",
    "size": 637251
  }
}

Dans cet exemple, nous avons un fichier image.png de type "image/png" avec un etag, une date de modification (mtime) et une taille. De même, nous avons un fichier video.mp4 de type "video/mp4" avec ses métadonnées correspondantes.

Vous pouvez placer vos fichiers statiques, tels que des images, des vidéos, des fichiers robots.txt, etc., dans le répertoire public/ de votre projet NitroJS.

Par exemple, vous pouvez placer des images dans le répertoire public/img/. Ces images seront accessibles à l'URL /img/1.png, où 1.png est le nom de l'image.capture d’écran 2023-10-01 223751

De plus, vous pouvez placer le fichier index.html fourni dans votre question dans le répertoire public/. Ce fichier HTML sera accessible à l'URL racine de votre application.capture d’écran 2023-10-01 223636

Hébergement sur Vercel

Pour héberger votre projet NitroJS sur Vercel, vous devez effectuer les étapes suivantes :

  1. Modifier le fichier de configuration de NitroJS : Dans le fichier nitro.config.ts, vous devez ajouter la configuration appropriée pour Vercel. Voici un exemple de configuration :

    typescript
    export default defineNitroConfig({
      preset: 'vercel_edge',
      publicAssets: [
        {
          baseURL: 'img',
          dir: 'public/img',
          maxAge: 60 * 60 * 24 * 7,
        },
      ],
    });

    Dans cet exemple, nous utilisons le preset vercel_edge pour la configuration de NitroJS. De plus, nous spécifions la configuration des assets publics en définissant la base URL (baseURL), le répertoire (dir) et la durée de mise en cache maximale (maxAge) pour les fichiers du répertoire public/img.

  2. Sauvegarder le projet sur GitHub : Assurez-vous d'avoir sauvegardé votre projet NitroJS sur GitHub. Cela permettra à Vercel de récupérer le code source de votre projet lors du processus de déploiement.

  3. Importer le projet sur Vercel : Accédez à votre compte Vercel et importez votre projet depuis GitHub. Vercel détectera automatiquement votre projet NitroJS et vous guidera tout au long du processus d'importation.

  4. Utiliser la configuration de base pour déployer le projet : Lors de l'importation de votre projet sur Vercel, vous pouvez utiliser la configuration de base recommandée par Vercel pour déployer votre projet. Cette configuration par défaut est généralement suffisante pour la plupart des projets NitroJS.

Une fois que vous avez suivi ces étapes, Vercel prendra en charge le processus de déploiement de votre projet NitroJS. Vous pourrez accéder à votre API hébergée sur Vercel à l'URL fournie par Vercel.

Gestion des CORS (Cross-Origin Resource Sharing)

Les CORS (Cross-Origin Resource Sharing) sont une politique de sécurité du navigateur qui permet de contrôler les requêtes d'accès aux ressources d'un domaine depuis un autre domaine. Cette politique vise à protéger les utilisateurs en empêchant les attaques de type CSRF (Cross-Site Request Forgery) et en limitant l'accès aux ressources sensibles.

Lorsqu'une requête est effectuée depuis un domaine différent (origine différente), le navigateur bloque par défaut l'accès aux ressources de ce domaine en raison de la politique des CORS. Pour permettre l'accès aux ressources depuis un autre domaine, le serveur doit inclure le header Access-Control-Allow-Origin dans sa réponse HTTP.

Le header Access-Control-Allow-Origin indique au navigateur quels domaines sont autorisés à accéder aux ressources. La valeur de ce header peut être un domaine spécifique, * pour autoriser tous les domaines, ou une liste de domaines autorisés séparés par des virgules.

Dans les exemples que vous avez donnés, nous utilisons Vercel pour gérer les CORS en ajoutant le header Access-Control-Allow-Origin dans la réponse HTTP. Voici une explication des différentes options que vous pouvez utiliser :

  1. "Access-Control-Allow-Origin": "*" : Cette configuration permet à toutes les origines (tous les domaines) d'accéder aux ressources. Cela peut être utile pour les APIs publiques ou les ressources non sensibles.

  2. "Access-Control-Allow-Origin": "https://example.com" : Cette configuration limite l'accès aux ressources uniquement depuis le domaine https://example.com. Vous pouvez spécifier un domaine spécifique pour limiter l'accès aux ressources à ce domaine uniquement.

  3. "Access-Control-Allow-Origin": "https://example.com, https://subdomain.example.com" : Cette configuration permet l'accès aux ressources depuis les domaines https://example.com et https://subdomain.example.com. Vous pouvez spécifier plusieurs domaines autorisés en les séparant par des virgules.

Il est important de noter que l'utilisation de "Access-Control-Allow-Origin": "*" peut présenter des risques de sécurité, car cela autorise tous les domaines à accéder aux ressources. Il est recommandé de limiter l'accès aux ressources en spécifiant des domaines spécifiques lorsque cela est possible.

Dans le cas de NitroJS, vous pouvez gérer les CORS en utilisant soit le fichier vercel.json, soit en modifiant le fichier nitro.config.ts. Les deux approches permettent de configurer le header Access-Control-Allow-Origin pour autoriser l'accès aux ressources depuis des domaines spécifiques ou de manière plus permissive.

Voici comment vous pouvez configurer les CORS dans NitroJS :

Option 1 : Utilisation du fichier vercel.json

json
{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Access-Control-Allow-Origin",
          "value": "*"
        }
      ]
    }
  ]
}

Avec cette configuration, le header Access-Control-Allow-Origin est défini à "*" pour toutes les sources, ce qui permet à tous les domaines d'accéder aux ressources.

Option 2 : Modification du fichier nitro.config.ts

typescript
export default defineNitroConfig({
  routeRules: {
    "/api/**": {
      cors: true,
      headers: {
        "Access-Control-Allow-Origin": "*"
      }
    }
  }
});

Avec cette configuration, le header Access-Control-Allow-Origin est défini à "*" pour toutes les routes commençant par /api/. Cela permet à tous les domaines d'accéder aux ressources de ces routes spécifiques.

Il est important de noter que la configuration "Access-Control-Allow-Origin": "*" permet à tous les domaines d'accéder aux ressources, ce qui peut présenter des risques de sécurité. Il est recommandé de limiter l'accès aux ressources en spécifiant des domaines spécifiques lorsque cela est possible.

N'oubliez pas de choisir la configuration qui correspond le mieux à vos besoins en matière de sécurité et d'accès aux ressources.

Liens vers le projet d’API

https://stackblitz.com/edit/unjs-nitro-q9sz32?file=README.md

https://api-annuaire.vercel.app/

Adaptation du Frontend pour utiliser l'API

Pour adapter le frontend de l'application d'annuaire afin d'utiliser notre API, nous devrons apporter des modifications à plusieurs fichiers. Commençons par créer une copie de la dernière version de l'application d'annuaire.

Variables d'environnement

Une fois que nous avons notre copie, nous pouvons procéder aux modifications nécessaires. La première étape consiste à ajouter un fichier .env à la racine du projet. Le fichier .env est utilisé pour définir les variables d'environnement qui peuvent être utilisées par l'application.

Dans le cas de Vite (l'outil de construction utilisé par l'application d'annuaire), nous devons préfixer les variables d'environnement par VITE_. Dans notre fichier .env, nous ajouterons la variable suivante :

plaintext
VITE_API_URL="https://api-annuaire.vercel.app"

Notez que vous devez modifier la valeur de VITE_API_URL pour correspondre à l'URL de votre API spécifique. Cette variable d'environnement sera utilisée pour stocker l'URL de base de l'API.

En définissant la variable VITE_API_URL dans le fichier .env, nous pouvons y accéder dans notre code d'application en utilisant import.meta.env.VITE_API_URL. Cela nous permet de changer facilement l'URL de l'API sans modifier directement le code lui-même.

Configuration

Voici la modification apportée au fichier vite.config.js :

javascript
import { resolve } from 'path';
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    target: 'esnext',
    rollupOptions: {
      input: {
        main: resolve(__dirname, 'index.html'),
        personne: resolve(__dirname, 'personne/index.html'),
      },
    },
  },
});

Dans cette configuration, nous avons ajouté l'option target: 'esnext' dans la configuration de construction (build). Cette option indique à Vite de cibler la version ESNext d'ECMAScript lors de la génération du code.

Cela permet d'utiliser les fonctionnalités les plus récentes d'ECMAScript dans notre application, ce qui peut améliorer les performances et la compatibilité avec les navigateurs modernes.

De plus, nous avons spécifié les fichiers d'entrée (input) pour la génération du bundle. Dans cet exemple, nous avons défini deux fichiers d'entrée : index.html pour la page principale et personne/index.html pour la page des personnes.

Ces modifications dans le fichier vite.config.js permettent de configurer Vite pour prendre en compte la version ESNext d'ECMAScript et de spécifier les fichiers d'entrée pour la génération du bundle.

main.js

Voici la nouvelle version du fichier main.js :

javascript
import * as bootstrap from 'bootstrap';
import './style.scss';
import { nav } from './nav';

const getPersonnes = async () => {
  const url = new URL(import.meta.env.VITE_API_URL);
  url.pathname = '/api/personnes';
  const reponse = await fetch(url);
  const personnes = await reponse.json();

  return personnes;
};

const listePersonnes = () => {
  // récupération des données

  let html = '';
  for (let i = 0; i < personnes.length; i++) {
    const personne = personnes[i];

    // url de l'image
    const imgUrl = new URL(import.meta.env.VITE_API_URL);
    imgUrl.pathname = personne.avatar;

    let personneCard = `
      <a class="card col-5 col-md-3" href="/personne/?id=${personne.id}">
        <img src="${imgUrl}" crossorigin class="card-img-top" alt="avatar de ${personne.prenom} ${personne.nom}">
        <div class="card-body">
          <h5 class="card-title">${personne.prenom} ${personne.nom}</h5>
        </div>
      </a>
    `;
    html += personneCard;
  }
  return html;
};

let personnes = await getPersonnes();

document.querySelector('#app').innerHTML = `
  <main>
    ${nav}

    <div class="container-fluid my-4">
      <input type="text" class="form-control" id="search-input" placeholder="Recherchez dans l'annuaire" />
    </div>

    <div class="container-fluid my-4">
      <div id="liste-personnes" class="d-flex gap-3 flex-wrap justify-content-center">
        ${listePersonnes()}
      </div>
    </div>
  </main>
`;

// recherche
document.querySelector('#search-input').addEventListener('input', async (e) => {
  const url = new URL(import.meta.env.VITE_API_URL);
  url.pathname = '/api/personnes/search';
  url.searchParams.set('q', e.target.value ?? '');
  const reponse = await fetch(url);
  const results = await reponse.json();
  console.log(results);

  if (!results || results.length === 0 || results.statusCode === 500) {
    personnes = await getPersonnes();
  } else {
    personnes = results;
  }
  const liste = document.querySelector('#liste-personnes');
  liste.innerHTML = listePersonnes();
});

Dans cette nouvelle version, nous avons ajouté la fonction getPersonnes qui récupère les données depuis notre API en utilisant l'URL spécifiée dans la variable d'environnement VITE_API_URL.

La recherche utilise également l'API en envoyant une requête à l'URL /api/personnes/search avec le paramètre q correspondant à la valeur de recherche. Les résultats de la recherche sont ensuite affichés dans la liste des personnes.

Nous n'avons plus besoin de la bibliothèque Fuse.js dans l'application frontend, car la recherche est désormais gérée par l'API. Vous pouvez donc désinstaller la bibliothèque Fuse.js si elle n'est plus utilisée ailleurs dans votre code.

personne.js

Voici le code mis à jour pour le fichier personne.js :

javascript
import * as bootstrap from 'bootstrap';
import '../style.scss';
import { nav } from '../nav';

const getPersonne = async () => {
  // récupération des paramètres GET de l'url
  const queryString = window.location.search;
  const urlParams = new URLSearchParams(queryString);
  const personneId = urlParams.get('id') ?? 1;
  console.log(personneId);

  // récupération des données
  const url = new URL(import.meta.env.VITE_API_URL);
  url.pathname = '/api/personnes/' + personneId;
  const reponse = await fetch(url);
  const personne = await reponse.json();

  return personne;
};

const detailsPersonne = () => {
  // url de l'image
  const imgUrl = new URL(import.meta.env.VITE_API_URL);
  imgUrl.pathname = personne.avatar;

  return `
      <div class="card col col-sm-10 col-md-8 col-xl-6 mx-auto">
        <img src="${imgUrl}" crossorigin class="card-img-top" alt="avatar de ${personne.prenom} ${personne.nom}">
        <div class="card-body">
          <h5 class="card-title">${personne.prenom} ${personne.nom}</h5>
          <h6 class="card-title">${personne.date_de_naissance}</h6>
          <h6 class="card-title">${personne.numero_de_telephone}</h6>
          <h6 class="card-title">${personne.adresse_email}</h6>
          <p class="card-text">
            ${personne.description}
          </p>
        </div>
      </div>
    `;
};

const personne = await getPersonne();

document.querySelector('#app').innerHTML = `
  <main>
    ${nav}

    <div class="container-fluid my-4">
      ${detailsPersonne()}
    </div>
  </main>
`;

Dans cette version mise à jour du fichier personne.js, nous avons ajouté la fonction getPersonne qui récupère les données de la personne en utilisant l'URL spécifiée dans la variable d'environnement VITE_API_URL.

Ensuite, nous avons utilisé les données récupérées pour afficher les détails de la personne dans la fonction detailsPersonne. L'URL de l'image est construite en utilisant l'URL de l'API et le chemin vers l'avatar de la personne.

Enfin, nous avons utilisé la fonction getPersonne pour récupérer les données de la personne et afficher les détails dans l'élément avec l'ID app de la page.

Ces modifications permettent à la page personne.html d'afficher les détails d'une personne en utilisant les données provenant de l'API.

Nettoyage des fichiers

Maintenant que nous avons migré les données vers notre API et que nous n'en avons plus besoin dans un fichier data.json, nous pouvons procéder au nettoyage des fichiers inutiles.

  1. Suppression du fichier data.json : Comme nous utilisons maintenant notre API pour récupérer les données, le fichier data.json n'est plus nécessaire. Vous pouvez le supprimer en toute sécurité.

  2. Suppression du dossier /public/img : Comme nous utilisons maintenant l'URL de l'API pour récupérer les images, le dossier /public/img qui contenait les images statiques n'est plus nécessaire. Vous pouvez supprimer ce dossier pour éviter d'avoir des fichiers inutiles dans votre projet.

Assurez-vous de sauvegarder une copie de sauvegarde de ces fichiers au cas où vous auriez besoin de les récupérer ultérieurement.

Avec ces fichiers supprimés, votre projet sera plus propre et ne contiendra que les fichiers nécessaires pour fonctionner avec l'API.

Dans les sections suivantes, nous continuerons à explorer les modifications nécessaires pour adapter le frontend de l'application d'annuaire à notre API.

Liens vers le projet front

https://stackblitz.com/edit/vitejs-vite-t9g6aw?file=README.md

https://annuaire-front-fetch-api.vercel.app/

Exercice

Étape 1 : Création de l'API

  1. Forkez le projet d’api de l’annuaire.
  2. Modifiez le projet pour qu’il héberge les données de votre blog.

Étape 2 : Modification du frontend du blog

  1. Forkez votre projet de blog.
  2. Modifiez les fichiers frontend pour utiliser la fonction fetch afin de récupérer les données des articles depuis l'API du blog.
  3. Mettez à jour les URL utilisées dans les requêtes fetch pour correspondre aux routes de l'API que vous avez définies précédemment.
  4. Utilisez les données récupérées pour afficher les articles dans le frontend du blog, en utilisant les mêmes techniques que celles utilisées dans les exemples précédents.

Étape 3 : Hébergement

  1. Hébergez l'api de votre blog sur Vercel.
  2. Hébergez le frontend de votre blog sur Vercel.

Assurez-vous de tester l'API et le frontend du blog pour vous assurer que les données sont correctement récupérées et affichées.

N'hésitez pas à personnaliser davantage l'API et le frontend du blog en ajoutant des fonctionnalités supplémentaires ou en personnalisant le design.

Cet exercice vous permettra de mettre en pratique les concepts abordés dans ce chapitre et de mieux comprendre le processus de création d'une API et de communication avec celle-ci depuis un frontend.

Bon travail !