Le cycle d'une requête
Tout entre par une seule méthode hôte, appelée à chaque requête web. Elle fait environ 1600 lignes, et connaître son ordre vaut mieux que de la lire : la plupart des « mon code ne s'exécute jamais » sont en réalité des « il s'exécute avant, ou après, l'étape que je croyais ».
L'ordre des étapes
- Remise à zéro du contexte de la requête précédente. La V21 réutilise les process web d'un pool : les variables process survivent donc d'une requête à l'autre. Sans cette remise à zéro en tête, une page lirait l'entité, le cache de droits ou la langue du visiteur précédent.
- Résolution de la vraie adresse du client. Derrière nginx, l'adresse de la socket vaut 127.0.0.1 pour tout le monde ; c'est un en-tête qui porte l'adresse publique. Calculée tout en haut, parce que les étapes suivantes la lisent.
- Les routes particulières, servies directement et qui rendent la main immédiatement : les vignettes du gestionnaire de fichiers, le fichier original, les données du sélecteur d'icônes, les aperçus du tableau de bord.
- Chargement de l'entité quand l'URL porte une clé primaire.
- Crochet hôte : la base hôte a son mot à dire avant le routage.
- Contrôle de sécurité sur toute requête portant des données de formulaire.
- Rendu, ou réponse JSON.
Le contrôle de sécurité n'est pas facultatif
Toute soumission de formulaire passe par le contrôle de sécurité avant que quoi que ce soit ne s'exécute. Un refus a une forme visible, et c'est voulu :
- sur une page normale : la page d'erreur, avec son code ;
- sur l'appel d'action : du JSON, pas du HTML. Renvoyer la page d'erreur complète avec un code 200 faisait échouer le fetch du navigateur sur une erreur de syntaxe — un message qui ne dit rien du vrai refus. La réponse porte aujourd'hui le code et une notification.
À savoir : si un bouton ne fait rien et que l'onglet réseau montre un refus, lisez le code de refus plutôt que de chercher un bug dans votre fonction : votre fonction n'a jamais été appelée.
Le rendu
Le gabarit de page vient du domaine : un même site peut avoir plusieurs enveloppes de page. À partir de là, l'arbre des blocs est parcouru, et chaque bloc est rendu par son gabarit ou par sa fonction 4D selon ce que déclare son type.
Deux formes de réponse
| Requête | Réponse |
|---|---|
| Page normale | Du HTML, avec le contrôleur de formulaire sérialisé et injecté juste avant la fin du document. C'est par là que les actions décidées côté serveur — notifications, rechargements de blocs — atteignent le navigateur. |
| Appel d'action ou WebSocket | Du JSON : le contrôleur de formulaire lui-même. |
Une redirection est une 302 par défaut ; une équivalence de langue utilise une 301.
Les variables process : le piège dans les deux sens
Les variables process sont ce qui permet aux expressions 4D d'un bloc de lire le contexte — l'entité de la page, l'URL, la langue courante. Deux erreurs symétriques se rencontrent :
- Croire qu'elles persistent d'une requête à l'autre. Elles ne doivent surtout pas — d'où la remise à zéro. Pour transporter un état d'une requête à la suivante, utilisez la session.
- Croire qu'elles sont propres. Une variable que la remise à zéro ne couvre pas garde sa valeur précédente.
Piège : l'hôte et le composant ne partagent pas leurs variables process. En poser une depuis le composant ne la rend pas visible depuis l'hôte — c'est la raison d'être du crochet dédié à cette transmission.
L'URL lue par le code est celle de la requête
Pendant un rendu déclenché par le panneau de développement, l'URL de la requête est celle de l'appel d'action, pas celle de la page en cours d'édition. Du code qui découpe cette URL pour deviner où il se trouve lira donc autre chose que ce qu'il croit — et un index hors bornes en est le symptôme habituel.
Piège : ne jamais identifier un écran à partir de l'URL de la requête. Le contexte d'édition a ses propres variables, faites pour ça.
La suite
Les événements et la soumission des formulaires, le contrôle de sécurité, les traductions : tout cela est détaillé dans la section Les mécanismes.

