DocsPython API et erreurs
Exceptions et erreurs
Une demande peut échouer à quatre endroits, et Nexy répond à chacun différemment. Cette page est l'index : recherchez le statut que vous voyez, puis la ligne qui l'a produit, puis le fichier qui décide du corps.
La version courte
| Que s'est-il passé | Statut | Le navigateur voit | Le client API voit |
|---|---|---|---|
| aucun itinéraire ne correspond à l'URL | 404 |
notfound.nexy, sinon la page intégrée |
{"detail": "Not Found"} |
| un segment de chemin ne correspond pas à son annotation | 404 |
la même page | {"detail": "Not Found"} |
| une requête, un en-tête, un cookie ou un champ de corps est manquant ou invalide | 422 |
Corps JSON de FastAPI | Corps JSON de FastAPI |
notFound() |
404 |
la page | {"detail": ...} |
unauthorized() |
401 |
la page intégrée | {"detail": ...} |
forbidden() |
403 |
la page intégrée | {"detail": ...} |
raise HTTPException(409, ...) |
409 |
la page intégrée | {"detail": ...} |
| une exception, rien n'a été pris | 500 |
errors.nexy, sinon la page intégrée |
{"detail", "reference"} |
redirect(url) |
307 |
la destination, pas de page | la destination, pas de corps |
permanentRedirect(url) |
308 |
la destination, pas de page | la destination |
Un client API est une requête dont l'entête Accept demande du JSON et non une page :
curl -H "Accept: application/json" http://localhost:3000/api/items/500# {"detail":"Out of range"}
D'où vient un échec
Browser ──► Middleware ──► Router ──► Page or handler
│ │ │
│ │ ├─ return ───────────► 200
│ │ ├─ HTTPException ────► its status
│ │ └─ other exception ───► 500
│ └─ no match ────────────────────────► 404
└─ raises ──────────────────────────────────────► 500| Scène | Qu'est-ce qui peut échouer | La réponse |
|---|---|---|
| Intergiciel | vos middleware.py, CORS, sessions |
le statut de l'exception, sinon 500 |
| Routeur | l'URL ne correspond à aucun fichier | 404 |
| Validation | un segment de chemin ne peut pas être converti | 404 |
| Validation | une requête, un en-tête, un cookie ou un champ de corps | 422 |
| Page, gestionnaire, action, garde | HTTPException |
son statut |
| Page, gestionnaire, action, garde | autre chose | 500 |
Partez de n'importe où
redirect, permanentRedirect, notFound, forbidden et unauthorized déclenchent une exception HTTP, donc le même appel fonctionne dans une page .nexy, un gestionnaire d'API, un contrôleur modulaire, un garde, un dependencies.py et une action.
from nexy import notFound, redirect from src.posts import find async def GET(slug: str): post = find(slug) if post is None: notFound("No such post") if post.moved_to: redirect(post.moved_to) return postfrom nexy import notFound, redirectfrom nexy.decorators import Controller from src.posts import find @Controller("/posts/{slug}")class PostsBySlugController: async def get(self, slug: str): post = find(slug) if post is None: notFound("No such post") if post.moved_to: redirect(post.moved_to) return postRépertoriez le contrôleur dans le controllers du module racine.
| Appeler | Réponse | Quand |
|---|---|---|
notFound(detail=None) |
404 |
la ressource n'existe pas |
unauthorized(detail=None, scheme=None) |
401 |
le visiteur doit d'abord se connecter |
forbidden(detail=None) |
403 |
le visiteur est connu mais ne le verra peut-être pas |
redirect(url, status=307) |
307 |
envoyez-les ailleurs en gardant la méthode |
redirect(url, status=303) |
303 |
après un formulaire : la requête suivante est un GET |
permanentRedirect(url) |
308 |
une page déplacée dont les moteurs de recherche devraient se souvenir |
Construisez la destination à partir de valeurs auxquelles vous faites confiance. redirect(request.query_params["next"]) envoie les visiteurs là où le lien l'indique ; c'est une redirection ouverte. Une destination qui contient un saut de ligne est refusée.
Validation : 422 ou 404
Les paramètres du gestionnaire sont validés par FastAPI par rapport à leurs annotations.
from nexy.http import Header async def GET(q: str, limit: int = 10, x_token: str = Header(...)): return {"q": q, "limit": limit}from nexy.decorators import Controllerfrom nexy.http import Header @Controller("/api/search")class SearchApiController: async def get(self, q: str, limit: int = 10, x_token: str = Header(...)): return {"q": q, "limit": limit}Répertoriez le contrôleur dans le controllers du module racine.
| Problème | Statut | Pourquoi |
|---|---|---|
| requête, en-tête, cookie ou champ de corps manquant ou invalide | 422 |
la demande a atteint le gestionnaire, les données sont fausses |
segment de chemin non valide (/api/users/abc pour id: int) |
404 |
le dossier n'a pas de route pour un non-numéro, donc l'URL n'existe pas |
Le corps de 422 est la forme standard de FastAPI, donc les clients et les SDK générés continuent de fonctionner :
{"detail": [{"loc": ["query", "q"], "msg": "Field required", "type": "missing"}]}
Pour un formulaire ou une action, le client reçoit un ActionError avec status et detail ; un 422 remplit également error.fields avec un message par champ. Voir Actions.
Pages d'erreur personnalisées
<h1>Page not found</h1><p>The link may be old. <a href="/">Start from the home page</a>.</p><h1>Something went wrong</h1><p>Try again in a moment.</p>| Fichier | Statut | Portée |
|---|---|---|
src/routes/notfound.nexy |
404 |
chaque itinéraire du projet |
src/routes/errors.nexy |
500 |
chaque itinéraire du projet |
src/routes/forbidden.nexy |
403 |
chaque itinéraire du projet |
src/routes/unauthorized.nexy |
401 |
chaque itinéraire du projet |
src/routes/blog/notfound.nexy |
404 |
/blog et inférieur |
src/routes/blog/errors.nexy |
500 |
/blog et inférieur |
src/routes/loading.nexy |
- | réservé, pas encore d'effet d'exécution |
Un fichier quelque part dans les routes installe la réponse à son statut : une copie à la racine répond à l'ensemble du projet, une copie dans un dossier répond à ce dossier et le fichier le plus profond qui correspond à l'URL l'emporte. Une URL en dehors de chaque copie et un statut sans aucun fichier obtiennent les pages stylisées intégrées. Voir Pages d'erreur par dossier.
Le routeur modulaire n'a pas de page d'erreur dans un fichier : un 404, 500, 403 ou 401 obtient la page stylisée intégrée. Les pages d'erreur par dossier sont une convention du routeur basé sur des fichiers.
Exceptions non gérées
Une exception qui n'a rien détecté est enregistrée une seule fois, avec sa référence, son origine et le code qui l'entoure. Le statut est 500, et le corps dépend de l'environnement.
nexy dev |
nexy build puis nexy start |
|
|---|---|---|
| Navigateur | l'erreur, les lignes de votre code et le traçage | errors.nexy, sinon la page intégrée, avec une référence |
| Client API | {"detail", "reference", "error"} |
{"detail", "reference"} |
| Borne | l'exception et les lignes de votre code | l'exception, tout le traçage et la référence |
x ZeroDivisionError: division by zero GET /boom ref fe6a5217 at src/routes/boom.py:2 in GET 1 | def GET(): 2 | return {"a": 1 / 0}
La référence est de huit caractères, nouveaux à chaque échec. Un visiteur peut le citer et vous trouvez le traçage en le recherchant dans le journal. Ni l'exception ni le code n'atteignent le visiteur en production.
Actions et formulaires
Une action est un point de terminaison POST avec un chemin généré. Ses échecs suivent les mêmes règles :
| Situation | Statut | Client |
|---|---|---|
| un champ est manquant ou invalide | 422 |
ActionError avec fields |
HTTPException(403) soulevés dans l'action |
403 |
ActionError avec status et detail |
| une exception non gérée | 500 |
ActionError; la référence est dans le journal du serveur |
l'en-tête Origin est un autre site |
403 |
refusé avant le déroulement de l'action |
Un formulaire sans JavaScript publié dans le chemin d'action ; un succès répond 303 retour à la page, un échec affiche la page d'erreur. Voir Actions.
Une liste de contrôle lorsqu'une page répond à la mauvaise chose
- Regardez le statut, pas la page. Un
notfound.nexypersonnalisé répond toujours à404. - Lisez le terminal. Une page dont l'importation échoue n'est pas enregistrée, donc son URL répond
404tant que le fichier existe. L'erreur d'importation est dans le journal. - Vérifiez l'extension. Avec
useCSR = True, les pages.nexyappartiennent au mode serveur ; une page dans le mauvais mode n'est pas un itinéraire. - Vérifiez la profondeur. Un
notfound.nexyouerrors.nexyne fonctionne que lorsque la copie racine existe. - Demandez JSON avec
Accept: application/jsonpour voir la forme que reçoit votre client API. - Citez la référence d'un
500lorsque vous ouvrez un problème ou effectuez une recherche dans le journal.
Prochaines étapes
- Pages d'erreur : le comportement de la page entière, avec des exemples
- Validation et erreurs : gestionnaires d'API
- Dépannage : les erreurs que les gens rencontrent réellement
- Tester : affirmer un statut et un corps