Aller au contenu
Bastide Connexion Créer un compte
Appuyez sur / pour chercher

Routage : redirections, réécritures et en-têtes

EnglishMarkdownv0.3.0

L'edge de Bastide peut rediriger une requête, la réécrire vers un autre chemin ou une autre origine, et poser des en-têtes de réponse, avant même que votre application ne la reçoive. Cette page présente les deux endroits où ces règles se déclarent, le simulateur qui les vérifie avant publication, et le retour à une version précédente.

Deux endroits, deux usages

Règles de routage du projetRoutes du déploiement
Où elles viventEn base, par projetDans le fichier glowsoft.json du dépôt
Comment elles changentPar l'API ou la ligne de commande, sans redéploiementÀ chaque déploiement, avec le code
Ce qu'elles fontRedirections, réécritures internes et vers une origine externeRedirections, en-têtes de réponse, réécritures internes
SyntaxeMotifs simples * et :nomCelle de vercel.json
VolumeJusqu'à 50 000 règles2 048 règles par bloc
Historique90 jours de versions, retour en un gesteCelui des déploiements : voir Restaurer

Choisissez les règles du projet pour les redirections en masse et celles qui changent sans livraison de code (une campagne, une migration d'adresses). Choisissez glowsoft.json pour ce qui suit le code : les en-têtes, les réécritures d'une application monopage, les redirections qu'une version introduit.

L'ordre d'évaluation

Pour chaque requête, l'edge applique dans cet ordre : la limite de débit du projet, la protection des prévisualisations, les règles de routage du projet, puis les routes du déploiement, puis le cache, et enfin l'application. Les règles du projet l'emportent donc sur celles du dépôt, et une réécriture de projet est relue par les routes du déploiement. Une requête redirigée ne lit rien au cache et ne réveille pas une application en veille.

Les règles de routage du projet

Les règles du projet se publient et se lisent par l'API et la ligne de commande. Il n'y a pas encore d'écran de console pour elles, et elles ne sont pas ouvertes aux agents : le catalogue MCP n'a pas d'outil pour elles. Un compte de service ne les mène pas non plus.

Une règle

ChampSens
sourceLe motif de chemin, qui commence par /. * couvre toute suite de caractères, / compris ; :nom couvre un segment. Pas d'expression régulière.
destinationUn chemin du site, ou une URL https:// vers un hôte de la liste d'autorisation (réécriture seulement). :nom et * y reprennent les captures, dans l'ordre.
typeredirect ou rewrite.
statusRedirection seulement : 301, 302, 307 ou 308. Par défaut 308.
conditionsJusqu'à 8 conditions sur un en-tête de requête : equals, prefix, exists ou absent.
timeoutMsRéécriture externe : délai de réponse, 5 000 ms par défaut, 10 000 ms au plus.
maxBytesRéécriture externe : taille de réponse, 5 Mo par défaut, 10 Mo au plus.

L'ordre de la liste est la précédence : la première règle dont le motif et les conditions concernent la requête répond. Écrivez la règle précise avant la règle générale qui la recouvre ; dans l'autre sens, la règle précise ne servirait jamais, et le simulateur la refuse.

Les origines externes

Une réécriture vers https://hôte/… n'est admise que si l'hôte figure dans allowedHosts, la liste d'autorisation du projet. Elle ne reçoit que des noms de domaine publics, en minuscules, sans port ni chemin : ni adresse IP, ni localhost, ni suffixe interne comme .local ou .internal. L'edge vérifie de nouveau à l'exécution l'hôte, le délai et la taille.

Publier

routingrules.write remplace la liste entière du projet : envoyez toujours la liste complète, dans l'ordre. Elle devient une version numérotée, prise en compte par chaque nœud à sa passe suivante, sans redéploiement. Une liste identique à la version active n'écrit rien.

{
  "projectId": "prj_01JQ8ZK4M7NP2RSTVWXYZ34567",
  "rules": [
    { "source": "/ancien/:page", "destination": "/nouveau/:page", "type": "redirect", "status": 301 },
    { "source": "/api/*", "destination": "https://api.exemple.fr/v1/*", "type": "rewrite", "timeoutMs": 3000 }
  ],
  "allowedHosts": ["api.exemple.fr"],
  "urls": [{ "path": "/ancien/tarifs" }, { "path": "/api/produits" }],
  "ifVersion": 3,
  "idempotencyKey": "routage-2026-10-26"
}

ifVersion porte la version active que vous avez lue (0 si le projet n'en a aucune). Si quelqu'un a publié entre-temps, l'appel est refusé en 409 plutôt que d'écraser sa version.

Le simulateur

Avant d'écrire quoi que ce soit, la publication rejoue la liste. Une liste refusée n'écrit rien : la réponse est un 422 qui détaille chaque conflit. Avec dryRun: true, rien n'est jamais écrit et le rapport est rendu, même s'il refuse.

Les conflits (conflicts) portent une nature :

NatureSens
loopUne chaîne de règles revient sur elle-même, ou dépasse 8 sauts.
shadowedUne règle n'est jamais atteinte : une règle plus générale la précède.
collisionDeux motifs à jokers se recoupent sans que l'ordre les départage.
duplicateDeux règles identiques.
invalidUne forme refusée, ou une réécriture vers un hôte hors de la liste.
incompleteLa simulation a atteint son budget de comparaisons sans conclure.

Pour chaque URL du jeu fourni dans urls (1 000 au plus, avec ses en-têtes éventuels), results donne l'issue : redirect, rewrite, external, none (aucune règle) ou loop, avec la destination, le statut et les règles traversées. Constituez ce jeu avec les adresses qui comptent pour vous : il sert de test de non-régression à chaque publication.

Versions et retour en arrière

Chaque publication crée une version immuable : son numéro, sa date, son auteur, son nombre de règles et son empreinte. L'historique garde 90 jours de versions.

routingrules.read rend les règles de la version active, ou d'une version donnée, page par page (200 par défaut, 1 000 au plus), avec la liste d'autorisation et l'historique.

routingrules.rollback rétablit une version de l'historique. Il la recopie en une version neuve, après avoir rejoué le simulateur : l'historique reste linéaire, et le retour en arrière se défait à son tour en rétablissant la version d'avant.

bastide routingrules read --project-id prj_01JQ8ZK4M7NP2RSTVWXYZ34567
bastide routingrules write --project-id prj_01JQ8ZK4M7NP2RSTVWXYZ34567 --rules "$(cat regles.json)" --allowed-hosts '["api.exemple.fr"]' --dry-run
bastide routingrules rollback --project-id prj_01JQ8ZK4M7NP2RSTVWXYZ34567 --version 3

Par l'API : GET et PUT /v1/projects/{projectId}/routing-rules, et POST /v1/projects/{projectId}/routing-rules/rollback, sur https://api.bastide.app. Lire demande le rang Lecteur ; publier et revenir en arrière, le rang Mainteneur.

Les routes du déploiement

Le fichier glowsoft.json, à la racine du dépôt, accepte trois blocs dont la forme et le sens sont ceux de vercel.json : redirects, headers et rewrites. Ils sont compilés à la construction et gelés avec le déploiement : les changer demande un nouveau déploiement, et restaurer une version précédente rétablit aussi ses routes. Une règle que l'edge ne saurait pas appliquer fait échouer la construction, avec un message qui situe la règle.

{
  "redirects": [
    { "source": "/blog/:slug", "destination": "/articles/:slug", "permanent": true }
  ],
  "headers": [
    {
      "source": "/:path*",
      "headers": [{ "key": "Strict-Transport-Security", "value": "max-age=31536000" }]
    }
  ],
  "rewrites": [
    { "source": "/:path*", "destination": "/index.html" }
  ]
}
  • Redirections : la première qui concerne la requête répond. Sans permanent ni statusCode, le statut est 308 ; "permanent": false donne 307. Les conditions has et missing portent sur un en-tête, un témoin, un paramètre de requête ou l'hôte. La clé env est refusée : l'edge ne détient pas les variables du projet.
  • En-têtes : toutes les règles qui concernent la requête s'appliquent, dans l'ordre. Un en-tête que l'application pose elle-même l'emporte.
  • Réécritures : le chemin demandé est servi d'abord ; une réécriture n'est essayée que si l'application y répond 404, trois au plus par requête. Une destination vers une autre origine est refusée : utilisez pour cela une règle de projet.

Comme dans vercel.json, un motif est sensible à la casse, et /:path* ne couvre pas la racine /.

Les en-têtes de sécurité par défaut

L'edge pose quatre en-têtes de sécurité, gelés avec chaque déploiement :

En-têteValeur
X-Content-Type-Optionsnosniff
Referrer-Policystrict-origin-when-cross-origin
X-Frame-OptionsSAMEORIGIN
Permissions-Policybrowsing-topics=()

Un bloc headers les surcharge, et une valeur vide en retire un. Strict-Transport-Security et une politique de sécurité de contenu ne sont pas posés d'office : déclarez-les si vous les voulez.

Limites

LimiteRègles du projetRoutes du déploiement
Nombre de règles50 0002 048 par bloc
Poids4 Mo de JSON par projet ; corps de requête de 16 Mo256 Ko de règles compilées
Jokers par motif4—
Longueur d'un motif ou d'une destination2 048 caractères4 096 caractères
Conditions par règle816 has et 16 missing
Hôtes externes autorisés50aucun
Historique90 jourscelui des déploiements

Ces limites sont les mêmes à tous les paliers.

Erreurs fréquentes

Symptôme ou codeCauseRemède
422 à la publicationLe simulateur a trouvé un conflit.Lire conflicts, corriger l'ordre ou la règle, rejouer avec dryRun.
409 conflictifVersion ne correspond plus à la version active.Relire avec routingrules.read, refaire vos modifications sur la version courante.
invalid sur une réécriture externeL'hôte n'est pas dans allowedHosts, ou n'est pas un domaine public.Ajouter l'hôte exact, en minuscules, sans port.
shadowedUne règle générale précède une règle précise.Placer la règle précise avant.
508 servi au visiteurUne chaîne de règles dépasse 8 sauts à l'exécution.Simplifier la chaîne ; le simulateur la signale en loop.
La construction échoue sur glowsoft.jsonUne route utilise une forme que l'edge n'applique pas.Lire le message, qui nomme le bloc et le rang de la règle.
Une réécriture du dépôt ne s'applique pasL'application répond autre chose que 404 sur le chemin demandé.C'est le comportement voulu : le contenu existant l'emporte.

Voir aussi

Signaler une erreur sur cette page