Le client Vue face au serveur
Cours · Spring Boot : écrire le serveur (école d'ingénieur), chapitre 9 · école d'ingénieur, informatique · le début du chapitre, la suite sur Adloun
L'API de la Librairie est complète : un catalogue public, des commandes vérifiées et enregistrées, un espace réservé au personnel. Mais personne ne l'utilise encore, sinon curl et nos tests. Son vrai client, c'est l'application Vue du livre précédent, qui parlait jusqu'ici au serveur d'essai serveur.mjs. Brancher l'une sur l'autre pose trois questions que ce chapitre traite dans l'ordre.
D'abord, le navigateur refuse qu'une page venue d'un site lise les réponses d'un autre site, sauf si cet autre site l'y autorise : c'est la politique de même origine, et l'autorisation s'appelle CORS. Ensuite, un client a besoin d'un mode d'emploi de l'API : nous le ferons écrire par le serveur lui-même, au format OpenAPI. Enfin, en production, il est plus simple que le serveur Java serve aussi les fichiers de l'application Vue : une seule adresse, une seule origine, et le problème du début disparaît.
Objectifs du chapitre
- Savoir ce qu'est une origine, ce que bloque le navigateur et ce qu'il laisse passer.
- Autoriser des origines précises avec Spring Security et lire une requête préalable (preflight).
- Comprendre ce que fait le relais de Vite, et pourquoi il ne dispense pas toujours de CORS.
- Publier une documentation OpenAPI et Swagger UI avec springdoc.
- Servir l'application Vue construite depuis Spring Boot, y compris ses adresses du routeur.
Le projet code/ch9/librairie part de celui du chapitre 8. Les journaux, réponses et messages de la console du navigateur montrés ici ont été produits par ce projet, avec l'application Vue du livre précédent construite par Vite 8 et pilotée dans Chromium. Dans les réponses de curl, on n'a gardé que la ligne de statut et les en-têtes utiles au propos.
9.1 Deux programmes, deux origines
L'origine d'une page est le triplet (protocole, nom d'hôte, port) de son adresse. Deux pages de localhost servies l'une sur le port 5173, l'autre sur le port 8000, ont deux origines différentes (le port diffère) ; localhost:4173 et 127.0.0.1:4173 aussi (le nom diffère, même si les deux désignent la même machine).
Un script peut envoyer une requête vers n'importe quelle origine, mais le navigateur ne lui laisse lire la réponse que si elle vient de sa propre origine, ou si le serveur l'y autorise explicitement par des en-têtes Access-Control-Allow-*. C'est le mécanisme CORS (Cross-Origin Resource Sharing).
Cette règle protège l'utilisateur, pas le serveur : sans elle, une page quelconque ouverte dans un onglet pourrait lire, avec les cookies de l'utilisateur, les réponses de sa banque ouverte dans un autre. Un client qui n'est pas un navigateur (curl, un programme Java, l'application mobile) n'applique pas cette règle : CORS n'est donc pas une protection de l'API, et ne remplace en rien l'authentification du chapitre 8.
Pendant le développement, la situation est la suivante :
La page vient du serveur de développement de Vite ; l'API est ailleurs. Deux cas se présentent alors pour une requête d'une autre origine.
Une requête GET ou POST « simple » (sans en-tête particulier, corps de type formulaire ou texte) part directement, avec un en-tête Origin ; le navigateur regarde ensuite la réponse. Toute autre requête (un POST de JSON, un PUT, un en-tête Authorization…) est précédée d'une requête préalable (preflight) : OPTIONS sur la même adresse, avec deux en-têtes qui annoncent la méthode et, s'il le faut, les en-têtes de la vraie requête :
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
La vraie requête ne part que si la réponse l'autorise.
9.2 Autoriser des origines avec Spring Security
Les origines autorisées sont une affaire de configuration : elles changent entre le poste du développeur et la production. On les range donc dans application.yml, lues par un record, comme au chapitre 2 :
librairie:
nom: La Librairie du Campus
frais-campus: "2.00"
cors:
origines: # chapitre 9 : le serveur de développement de Vite
- http://localhost:5173
/** Chapitre 9 : « librairie.cors.origines », les sites autorisés à appeler l'API. */
@ConfigurationProperties("librairie.cors")
public record CorsProperties(List<String> origines) {
}
La suite du cours est sur Adloun
Le chapitre en entier, formules et figures comprises, avec le tuteur, les fiches, les QCM et les exercices.
Lire la suite du coursEn accès libre, sans inscription.