L’évolution de l’architecture web : la nostalgie de PHP et le cauchemar du CORS

« À l’époque, un seul fichier suffisait… »

Le PHP que j’avais utilisé à l’université était vraiment pratique. Dans un seul fichier index.php, on pouvait écrire les balises HTML, ouvrir <?php ?> au milieu et y ajouter directement le code de requête vers la base de données. Il n’y avait pas de séparation nette entre frontend et backend. Une fois une variable déclarée, on pouvait l’utiliser partout dans le HTML, et les erreurs liées à la communication de données étaient pratiquement inexistantes.

Mais quand, dans la pratique, je suis passé à une stack avec Vue.js pour le frontend et Spring Boot pour le backend, l’enfer a commencé.

« J’ai bien lancé le serveur Spring en local, l’interface Vue tourne aussi, alors pourquoi les données n’arrivent-elles pas ? »

La console des outils de développement de Chrome était recouverte de messages d’erreur rouge vif.

Access to XMLHttpRequest at ... has been blocked by CORS policy

Au fond, qu’est-ce que ce « CORS » qui bloque mes données ? Et pourquoi avons-nous abandonné cette méthode si confortable où un seul fichier suffisait, pour nous imposer volontairement la séparation du frontend et du backend ?

Autrefois, tout le monde vivait sous le même toit. Aujourd’hui, chacun habite dans sa propre maison et doit passer par un contrôle.

Qui doit cuisiner ? (SSR vs CSR)

Pour comprendre ce changement, il faut d’abord comprendre qui prépare le « plat » qu’est une page web, c’est-à-dire le HTML. C’est exactement là que se situe la différence entre SSR (Server Side Rendering) et CSR (Client Side Rendering).

1. SSR : une lunch box déjà prête (PHP, JSP)

  • Principe : le serveur (la cuisine) prépare le riz, les accompagnements et la soupe, les dispose joliment dans la lunch box (HTML), puis l’envoie.
  • Client (navigateur) : il lui suffit de soulever le couvercle de la lunch box et d’en montrer le contenu.
  • Avantages : le premier écran se charge vite. Les moteurs de recherche (SEO) lisent facilement le contenu.
  • Inconvénients : pour changer un seul accompagnement, il faut recevoir à nouveau toute la lunch box. (l’écran clignote)

2. CSR : un kit repas livré (React, Vue)

  • Principe : le serveur ne cuisine pas. Il se contente d’envoyer les ingrédients (données JSON) et la recette (JavaScript).
  • Client (navigateur) : il prend les ingrédients reçus et les fait revenir et sauter lui-même sur mon ordinateur (dans le navigateur) pour construire l’écran.
  • Avantages : on peut remplacer uniquement les accompagnements voulus, si bien que les transitions d’écran sont très fluides (comme dans une application). La charge du serveur diminue.
  • Inconvénients : le chargement initial est lent, car il faut d’abord télécharger la recette (les fichiers JS).

[Tip] CSR et SPA ne veulent pas exactement dire la même chose

On les emploie souvent comme s’ils étaient interchangeables, mais à strictement parler, ce n’est pas le cas.

  • CSR (Client Side Rendering) : c’est le « comment » (How). Le terme désigne la manière dont le navigateur dessine l’écran.
  • SPA (Single Page Application) : c’est la « forme » (What). Le terme désigne une application qui ne comporte qu’une seule page.

En pratique, on utilise généralement le CSR pour construire une SPA. Autrement dit, comme on veut éviter le clignotement des rechargements complets en utilisant une seule page (SPA), on choisit une méthode où le navigateur redessine lui-même les parties nécessaires (CSR).

Si nous utilisons Vue.js ou React, c’est avant tout pour l’expérience utilisateur. Pour qu’un site web se comporte avec la fluidité d’une application mobile, on a déplacé l’acte de « cuisiner » du serveur vers le navigateur.

CORS, le vigile qui bloque les invités indésirables

En séparant le frontend (Vue) et le backend (Spring), nous nous sommes retrouvés avec « deux maisons ».

  • Maison du frontend : localhost:8080 (serveur Vue)
  • Maison du backend : localhost:3000 (serveur Spring)

Et c’est là que le problème apparaît. Pour des raisons de sécurité, le navigateur web suit une règle de base : « il ne faut pas faire confiance trop facilement à des ressources venant d’une autre Origin ». C’est la SOP, la Same Origin Policy.

Imaginez : je suis connecté à Naver, et depuis un site créé par un hacker, une requête secrète part vers le serveur de Naver pour dire « donne-moi les informations personnelles de cet utilisateur ». Si le navigateur ne bloquait pas cela, toutes mes données seraient exposées.

C’est pourquoi le navigateur bloque par défaut les requêtes dès que l’origine, c’est-à-dire le domaine ou le port, diffère. Or, pour le développement, nous avons justement séparé les ports de façon intentionnelle. Nous voulons seulement utiliser nos propres données, mais le navigateur, tel un vigile, nous répond : « votre port ne correspond pas, accès refusé ». Voilà ce qu’est réellement une erreur CORS (Cross-Origin Resource Sharing).

[Code Verification] Délivrer un laissez-passer

La solution est en fait assez simple. Le serveur, donc le backend, doit simplement écrire un laissez-passer au navigateur, le vigile, pour lui dire : « cet utilisateur est un invité que j’ai moi-même convié, laisse-le entrer ».

Dans Spring Boot, ce laissez-passer peut être délivré avec un simple fichier de configuration.

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 1. Pour tous les chemins API
                .allowedOrigins("http://localhost:8080") // 2. Autoriser les requetes depuis cette origine
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 3. Autoriser ce type de requetes
                .allowCredentials(true); // 4. Les cookies et identifiants peuvent etre inclus
    }
}

Analyse :

  1. allowedOrigins : c’est le plus important. Si vous y indiquez l’adresse du serveur frontend (localhost:8080), le serveur Spring appose sur l’en-tête de la réponse un tampon Access-Control-Allow-Origin: http://localhost:8080 avant de l’envoyer.
  2. Le navigateur vérifie ce tampon, se dit « Ah, le propriétaire du serveur a donné son accord », puis transmet les données au frontend.

Il faut toutefois faire attention à ne pas, par paresse, tout ouvrir avec allowedOrigins("*"). Ce serait comme laisser la porte d’entrée grande ouverte avec un panneau « Bienvenue aux voleurs ».

Conseil pratique : quand utiliser quoi ?

Est-ce que cela signifie que le CSR, donc Vue ou React, est toujours la bonne réponse ? Non. En pratique, il faut choisir en fonction de l’objectif.

  1. Pages d’administration (Admin), tableaux de bord :
    • Recommandation : CSR (Vue, React)
    • Pourquoi : les interactions avec les données sont nombreuses et il n’est pas nécessaire d’apparaître dans les moteurs de recherche. Ce qui compte, c’est une réactivité vive, comme celle d’une application.
  2. Sites d’actualités, blogs, page d’accueil d’une boutique en ligne :
    • Recommandation : SSR (Next.js, Nuxt.js)
    • Pourquoi : il faut être bien référencé sur Google (SEO), et quand un client arrive, le contenu doit s’afficher immédiatement plutôt qu’un écran blanc.
  3. Petits projets personnels :
    • Recommandation : Thymeleaf (SSR intégré à Spring Boot)
    • Pourquoi : quand on développe seul, inutile de s’épuiser à séparer frontend et backend puis à configurer CORS. Tout regrouper au même endroit, comme à l’époque de PHP, reste ce qu’il y a de plus productif.

Pour conclure : franchir la frontière

La « grande famille sous un même toit » de l’époque PHP était confortable, mais plus tout se complexifiait, plus cela devenait difficile à gérer. Aujourd’hui, avec « deux familles séparées » que sont le frontend et le backend, la communication via des sujets comme CORS est plus pénible, mais chacun peut se concentrer sur son propre rôle.

La prochaine fois que vous rencontrerez une erreur CORS, essayez donc de ne pas réagir uniquement avec agacement. Le navigateur n’est pas en train de vous harceler : il effectue simplement un contrôle strict pour protéger votre maison, c’est-à-dire votre serveur.

Maintenant, le passage entre frontend et backend est ouvert. Les données peuvent circuler. Mais où ces données sont-elles réellement stockées côté serveur ? Autrefois, il suffisait d’envoyer une requête SQL et de récupérer ce qu’il fallait. En Spring, avec des notions comme JPA et Entity, on a parfois l’impression qu’on nous empêche d’écrire du SQL directement.

La prochaine fois, nous verrons comment la « méthode canonique » de conception de bases de données, la normalisation, peut devenir un frein en pratique, et pourquoi JPA cherche autant à vous cacher le SQL.

Laisser un commentaire