Traduction de la page originale en anglais. En cas de divergence, la version anglaise fait foi.
Routage
DaloyJS utilise un trie de segments avec un chemin rapide pour les routes statiques. Après les contrôles de sûreté du chemin, les routes statiques exactes se résolvent en un seul Map.get. Les recherches dynamiques privilégient les segments littéraux, puis les paramètres, puis les jokers. Une recherche sans retour arrière est linéaire en fonction de la longueur du chemin ; des routes qui se chevauchent peuvent obliger à visiter des branches supplémentaires du trie.
Seules les routes complètes comptent comme correspondances. Par exemple, enregistrer /users/me/details/:field n’empêche pas /users/:id de correspondre à /users/me. Dans le trie dynamique, un chemin complet de priorité supérieure l’emporte même s’il n’a pas de handler pour la méthode demandée. Une route statique exacte l’emporte pour ses méthodes enregistrées ; les autres méthodes peuvent encore correspondre au trie dynamique.
Raccourcis progressifs
Les raccourcis de méthode réduisent la cérémonie sans supprimer le contrat. DaloyJS dérive un identifiant d’opération stable à partir de la méthode et du chemin, comme getRoot ou postBookItemsByItemId. Un operationId explicite reste prioritaire.
Les raccourcis conservent la même validation, le même OpenAPI, la même sécurité et le même comportement du client typé que route(). Il n’existe pas de forme à deux arguments qui ignorerait silencieusement le contrat de réponse. Pour un corps volontairement opaque, passez explicitement acknowledgeNoResponseBodySchema: true. Les réponses brutes de succès renvoyées par preBody ou beforeHandle exigent la même confirmation. Les refus ordinaires 4xx/5xx des hooks, non. Les descriptions de réponse restent facultatives. Les valeurs omises deviennent dans OpenAPI une description stable HTTP <status> response.
Définir des routes
Une déclaration de route est la source de vérité pour la correspondance, la validation des requêtes, la validation des réponses, la sortie OpenAPI et les clients typés. Fournissez un operationId lorsque vous utilisez route() pour une route publique que vous voulez voir dans le client typé ou dans le SDK généré. Les raccourcis HTTP en dérivent un automatiquement. DaloyJS rejette les valeurs operationId en double à l’enregistrement.
Inférence de types sur plusieurs fichiers
Exportez chaque route avec defineRoute(), puis composez les contrats importés avec registerRoutes(). Le tuple littéral survit aux frontières de fichiers et de modules : le client sans génération de code conserve donc chaque identifiant d’opération et chaque schéma.
Les appels route() chaînés s’accumulent aussi correctement. Évitez une simple annotation const app: App sur l’application finale composée, car elle élargit explicitement le type et efface le tuple de routes.
group() en style callback et register() des plugins assurent toujours la portée à l’exécution, mais TypeScript ne peut pas élargir la variable parente depuis l’intérieur de leurs callbacks. Pour un client entièrement typé sans génération de code sur de gros modules, exportez des tuples de routes littéraux et faites de registerRoutes() la frontière finale de composition.
Méthodes HTTP
Les méthodes prises en charge sont GET, POST, PUT, PATCH, DELETE, HEAD et OPTIONS. Les méthodes personnalisées comme TRACE, CONNECT et les verbes WebDAV sont rejetées à l’enregistrement.
HEAD se rabat sur la route GET correspondante lorsqu’aucune route HEAD explicite n’existe, et renvoie les mêmes en-têtes avec un corps vide. OPTIONS renvoie un preflight 204 avec un en-tête Allow lorsqu’un chemin existe mais qu’aucune route OPTIONS explicite n’est enregistrée.
Des méthodes raccourcies existent pour GET, POST, PUT, PATCH, DELETE et HEAD. Enregistrez une route OPTIONS explicite avec route(). Sinon, DaloyJS gère automatiquement le preflight.
Paramètres de chemin
Les valeurs de chemin sont décodées avant la validation. Si vous omettez le schéma request.params, ctx.params est inféré à partir du chemin sous forme de chaînes brutes. Des noms de paramètres en conflit à la même position du trie, comme /a/:x et /a/:y, lèvent une erreur à l’enregistrement.
Les noms de capture doivent être non vides et uniques au sein d’une route. Les noms __proto__, constructor et prototype sont rejetés pour que les objets de paramètres restent sûrs en aval. Un enregistrement rejeté ne réserve pas son operationId.
Captures joker
Un segment final *name capture le reste du chemin dans une seule chaîne décodée et exige au moins un segment restant. Un * seul utilise le nom wildcard. Les jokers doivent être terminaux : /assets/*path/private lève une erreur à l’enregistrement au lieu de correspondre silencieusement à un chemin plus large. Plusieurs méthodes peuvent partager une route joker si le nom de capture concorde. Les méthodes en double et les noms de joker en conflit lèvent une erreur.
Les segments bruts de traversée de chemin (..), les segments vides // et les échappements pourcentage malformés dans les captures ne correspondent tout simplement pas. La découverte des méthodes applique les mêmes contrôles : les chemins rejetés n’annoncent donc pas d’en-tête Allow. Depuis la 1.3.7, un segment de paramètre ou de joker ne se lie jamais à . ou .., y compris sous les formes encodées %2e et %2e%2e. Un analyseur d’URL les résoudrait comme des déplacements de répertoire : les laisser se lier donnerait au handler un chemin différent de celui qu’a vu le middleware. Une capture refuse aussi une valeur décodée contenant un composant . ou .. derrière un séparateur encodé (..%2F..%2Fsecret, ..%5C), ou tout caractère de contrôle (%00, %0A, %09, %7F). Ces requêtes reçoivent un 404.
Une capture qui décode un / ou un \ encodé (%2F, %5C) est aussi refusée par défaut avec un 404, car une seule valeur capturée couvrirait alors plusieurs segments de chemin pour tout consommateur en aval (système de fichiers, URL ou proxy). Si une route utilise réellement des identifiants contenant une barre oblique, activez l’option route par route :
Cette option ne réadmet jamais les composants .. ni les caractères de contrôle. Les paramètres décodés restent des données non fiables et ne sont pas des chemins de système de fichiers assainis : validez donc séparément les accès au système de fichiers.
Les adaptateurs maintiennent aussi le routeur et le middleware sur une même vue du chemin (depuis la 1.3.7). L’adaptateur Node canonicalise, avant le routage, les cibles de requête contenant \, des segments point ou leurs formes %2e, comme le ferait new URL(). Les adaptateurs Node et AWS Lambda refusent tous deux avec un 400 un en-tête Host qui n’est pas un simple host[:port] (par exemple s’il contient \ / ? # @ % ou des espaces). Les garde-fous fondés sur le chemin, comme except(), correspondent donc exactement à la route qui s’exécute. Voir l’adaptateur Node (en anglais) pour les détails.
Groupes
Les groupes fusionnent préfixes, tags, hooks et valeurs d’authentification par défaut dans les routes enregistrées à l’intérieur du callback. L’application enfant est encapsulée : un middleware ajouté dans un groupe ne déborde pas sur les routes extérieures à ce groupe. Les routes groupées sont visibles par le routage à l’exécution et par OpenAPI. Pour des contrats /api/v1 et /api/v2 parallèles, une politique de migration et des SDK générés séparément, lisez le guide de versionnage d’API (en anglais).
Options de route
request: schémas pourparams,query,headersetbody.responses: codes de statut déclarés et schémas facultatifs de corps et d’en-têtes de réponse.accepts: liste d’autorisationContent-Typepar route, pour les routes ayant un schéma de corps de requête.auth: exigence de sécurité OpenAPI de la route. Associez-la à un hook d’authentification commebearerAuth().internal: masque une route aux adaptateurs publics tout en autorisant les appels en processus viaapp.inject().deprecatedetsunset: marquent un endpoint comme obsolète et émettent les en-têtes de réponse correspondants.callbacksetmeta: ajoutent des callbacks OpenAPI, des exemples et des métadonnées de route adaptées à l’IA.
Hooks
Les hooks attachent un comportement à des points fixes du cycle de vie :
onRequest: le plus tôt, avant l’analyse.preBody: après la correspondance de route, avant la validation des schémas ou toute E/S sur le corps. L’authentification intégrée par en-tête, JWT, basic ou mTLS s’exécute ici.beforeHandle: après la validation, avant votre handler. Renvoyez uneResponsepour court-circuiter.afterHandle: enveloppe ou transforme le résultat du handler avant la sérialisation de la réponse.onError: observe ou remplace la réponse d’erreur.onSend: modifie en place les en-têtes sortants ou renvoie une nouvelleResponse. S’exécute sur les chemins de succès, d’erreur et de preflightOPTIONS.onResponse: observateur final. Utilisez-le pour les logs et les métriques. Ne modifiez pas la réponse ici.
- 01le plus tôtonRequestavant l’analyse
- 02rejet le moins coûteuxpreBodyroute trouvée · corps intact
- 03frameworkvalidateparams · query · body · headers
- 04beforeHandlerenvoyez une Response pour court-circuiter
- 05handlerla logique de votre route
- 06afterHandleenvelopper / transformer le résultat
- 07onSendmodifier ou remplacer la Response
- 08toujoursonResponseobservabilité uniquement
Transformer les réponses avec onSend
Utilisez onSend lorsque vous devez réécrire la réponse sortante, par exemple pour ajouter un en-tête, retirer un en-tête interne ou remplacer entièrement la réponse. Renvoyer void conserve la réponse actuelle. Plusieurs hooks onSend se composent en pipeline (global -> groupe -> route).
onSend s’exécute après la validation de la réponse et après la fusion des en-têtes propres à la requête, dont x-request-id. Il s’exécute avant onResponse, qui reste le bon endroit pour les logs et les métriques.
405 Method Not Allowed
Si un chemin est enregistré pour une méthode mais appelé avec une autre, le routeur renvoie 405 avec un en-tête Allow correct, jamais un 404 trompeur. Les routes marquées internal: true sont filtrées des réponses 405 et Allow publiques, pour que des endpoints d’administration ou de cron cachés ne fuient pas par sondage des méthodes.
La découverte des méthodes inclut à la fois une route statique exacte et la route dynamique sélectionnée. Avec GET /users/me et POST /users/:id, le chemin /users/me annonce les deux méthodes enregistrées. L’en-tête liste les enregistrements explicites ; la gestion synthétisée de HEAD et OPTIONS n’y ajoute pas d’entrées.
Performances
Dernière mise à jour :