FastAPI en 2026 : ce qui a changé dans le routing et la validation
FastAPI 0.139 affine la façon dont les routers matchent les requêtes et durcit la validation JSON par défaut. Voici ce qui compte si vous maintenez un service FastAPI.
FastAPI n'a toujours pas atteint la 1.0, et c'est voulu,Sebastián Ramírez livre des améliorations incrémentales plutôt qu'une réécriture big-bang. La version 0.139, sortie le 1er juillet 2026, donne un bon aperçu de la direction du framework : plus de contrôle sur le routing, une validation plus stricte par défaut, et une transition plus douce pour les gros codebases encore sur Pydantic v1.
Matching de routes custom avec APIRouter.matches() et .handle()
APIRouter gagne deux nouvelles méthodes qui permettent de personnaliser la façon dont un router décide s'il doit traiter une requête. Un cas d'usage courant : router par header plutôt que par préfixe d'URL, utile pour versionner une API sans polluer chaque route avec /v1, /v2.
from fastapi import APIRouter, Request
class HeaderVersionedRouter(APIRouter):
def __init__(self, *args, version: str, **kwargs):
super().__init__(*args, **kwargs)
self.version = version
def matches(self, request: Request) -> bool:
return request.headers.get("X-API-Version") == self.version
router_v1 = HeaderVersionedRouter(version="1")
router_v2 = HeaderVersionedRouter(version="2")Ajouter des routes à un router déjà inclus
Les routes ajoutées à un router après son inclusion dans l'app apparaissent désormais correctement,avant elles étaient copiées au moment de l'inclusion et les ajouts ultérieurs étaient silencieusement ignorés. Les sous-routers peuvent aussi être inclus dans un router parent avant même d'avoir des routes, ce qui économise de la mémoire dans les apps qui construisent leurs routers dynamiquement.
Validation JSON plus stricte par défaut
FastAPI vérifie désormais que les requêtes JSON entrantes portent un header Content-Type valide avant de tenter de parser le body. Une requête qui prétend envoyer du JSON sans le bon header est rejetée plutôt que mal interprétée silencieusement,ça ferme une classe de bugs client subtils. Si certains de vos clients ne fixent pas correctement ce header, vous pouvez désactiver ce comportement.
from fastapi import FastAPI
app = FastAPI()
@app.post("/webhooks/legacy-partner")
async def legacy_webhook(payload: dict):
# Certaines intégrations partenaires envoient encore du JSON
# sans header Content-Type. On désactive explicitement le nouveau
# comportement par défaut plutôt que d'échouer silencieusement.
...La désactivation se fait via un flag strict_content_type=False par route, sur le décorateur. À utiliser de façon délibérée pour les intégrations legacy, pas comme réglage par défaut global,le comportement strict attrape de vrais bugs.
Mixer Pydantic v1 et v2 dans la même app
Les gros codebases FastAPI qui n'ont jamais fini leur migration hors de Pydantic v1 ont maintenant un pont officiel : importer depuis pydantic.v1 permet aux modèles v1 et v2 de coexister dans la même application. Ça transforme une migration big-bang risquée en migration incrémentale, modèle par modèle.
from pydantic.v1 import BaseModel as LegacyModel # anciens modèles pas encore migrés
from pydantic import BaseModel # les nouveaux endpoints utilisent directement Pydantic v2
class LegacyOrder(LegacyModel):
id: int
total: float
class Order(BaseModel):
id: int
total: float
currency: str = "EUR"Support de Python 3.14
FastAPI a retiré Python 3.8 de sa CI et ajouté le support de Python 3.14, tandis que sa syntaxe interne a été mise à niveau pour cibler Python 3.9+. Si vous êtes encore bloqués sur Python 3.8, c'est cette release qui impose la conversation sur la mise à niveau du runtime.
Aucun de ces changements n'est cassant par défaut,la vérification stricte du Content-Type est celle à tester si vos clients sont peu typés. Le reste est additif : plus de contrôle sur le routing, un pont de migration, et une plage Python supportée plus large.
Besoin d'aide sur ce sujet ? Conception d'API REST
Découvrir ce service →