Dans le développement d'une API RESTful, les opérations CRUD (Créer, Lire, Mettre à jour, Supprimer) constituent le cœur de toute application de gestion des données. En utilisant FastAPI, nous pouvons facilement mettre en place ces opérations et les exposer via des endpoints HTTP. Dans ce chapitre, nous détaillerons le processus de création des fonctions nécessaires pour gérer une base de données de tâches et l'exposition de ces opérations via une API.
Créer des opérations CRUD de base
La première étape dans la gestion des tâches consiste à définir des fonctions permettant de récupérer et manipuler les données. Nous commencerons par la fonction permettant de récupérer le prochain identifiant unique (ID) pour une nouvelle tâche, basé sur les valeurs déjà présentes dans la base de données. Cette fonction inspecte un fichier CSV utilisé comme base de données, cherche le plus grand identifiant et ajoute 1 pour déterminer le nouvel ID :
Ensuite, il faut définir la fonction qui écrit les données d’une nouvelle tâche dans le fichier CSV. Cette fonction prend un objet TaskWithID, extrait ses données, et les écrit dans le fichier :
À partir de ces deux fonctions de base, nous pouvons créer une fonction qui permet de créer une tâche en générant un ID unique et en écrivant la tâche dans le fichier CSV :
De même, une autre fonction permet de modifier une tâche en fonction de son ID, en mettant à jour ses champs dans la base de données. Elle lit d'abord toutes les tâches existantes, met à jour celle qui correspond à l'ID donné, puis réécrit l'ensemble des tâches dans le fichier CSV :
Pour supprimer une tâche spécifique, nous devons d'abord rechercher la tâche correspondante à son ID, la supprimer, puis réécrire les tâches restantes dans le fichier CSV :
Exposer les opérations via FastAPI
Une fois les fonctions CRUD mises en place, il est temps de les exposer à travers des endpoints HTTP dans FastAPI. Nous allons créer une API permettant de lister, récupérer, ajouter, modifier et supprimer des tâches.
-
Lister toutes les tâches :
Un endpointGET /taskspermet de récupérer toutes les tâches stockées dans la base de données. -
Récupérer une tâche spécifique :
Un endpointGET /tasks/{task_id}permet de récupérer les détails d’une tâche à partir de son ID. Si la tâche n'existe pas, une exception est levée. -
Ajouter une nouvelle tâche :
L'endpointPOST /taskpermet de créer une nouvelle tâche en envoyant les données nécessaires dans le corps de la requête. -
Mettre à jour une tâche existante :
Un endpointPUT /tasks/{task_id}permet de modifier les informations d'une tâche existante. La mise à jour se fait en envoyant les nouveaux champs à modifier. -
Supprimer une tâche :
Enfin, l'endpointDELETE /tasks/{task_id}permet de supprimer une tâche spécifique en utilisant son ID.
Compléments essentiels pour la bonne gestion des tâches
Lors de l’implémentation de ces opérations, plusieurs aspects sont cruciaux pour assurer une gestion efficace des données :
-
Validation des données : Bien que FastAPI assure une validation automatique des types de données avec les annotations, il est essentiel de vérifier que les données envoyées via les requêtes POST ou PUT respectent les contraintes de l'application, comme la longueur du titre ou la validité du statut.
-
Gestion des erreurs : Lors de l’interaction avec les fichiers (comme l'ouverture du fichier CSV), il est important de prendre en compte les exceptions potentielles, telles que les erreurs d'I/O ou les erreurs liées à des données mal formées. Un système de gestion d’erreurs robuste peut améliorer l’expérience utilisateur et faciliter le débogage.
-
Tests unitaires : Pour garantir la stabilité de l’API, il est crucial d'écrire des tests unitaires pour chaque endpoint. Utiliser un cadre de test comme
pytestpermet de s’assurer que chaque opération fonctionne correctement et de valider la fiabilité des fonctionnalités à long terme. -
Performance et Scalabilité : Bien que l’utilisation d’un fichier CSV pour stocker les données soit simple et pratique pour un prototype, il devient rapidement inadapté à des systèmes de plus grande envergure. Il est recommandé de passer à une base de données relationnelle (comme PostgreSQL ou MySQL) pour des applications plus complexes.
Comment sécuriser vos applications FastAPI : Authentification, autorisation et gestion des utilisateurs
La sécurité des applications web modernes est un domaine complexe et essentiel, particulièrement lorsque nous travaillons avec des API. Dans le contexte de FastAPI, une des solutions les plus efficaces consiste à utiliser des techniques d'authentification et d'autorisation robustes, combinées à des méthodes de protection des données sensibles. Ce chapitre vous guidera à travers les différentes étapes nécessaires pour mettre en place un système d'enregistrement d'utilisateurs sécurisé, intégrer OAuth2 avec JSON Web Tokens (JWT), gérer l'authentification multi-facteurs (MFA), et bien plus encore.
L’un des aspects fondamentaux dans la mise en place d’une application SaaS (Software as a Service) est la gestion des utilisateurs, depuis leur inscription jusqu'à la sécurisation des points d’accès avec des clés d’API et des protocoles d’authentification externes. Nous verrons comment implémenter un système d'enregistrement simple, ajouter la gestion des rôles avec contrôle d'accès basé sur les rôles (RBAC), et utiliser des services tiers tels que GitHub pour faciliter l'authentification des utilisateurs. Nous aborderons également la mise en œuvre de la double authentification pour renforcer la sécurité.
Mise en place de l'enregistrement des utilisateurs
Le processus d'enregistrement des utilisateurs dans une application FastAPI commence par la collecte et le stockage sécurisé des informations sensibles, comme le mot de passe. Pour ce faire, il est impératif d'utiliser des techniques de hachage pour transformer le mot de passe en une forme irrécupérable, assurant ainsi la sécurité des données.
Dans cette étape, nous allons stocker les informations des utilisateurs dans une base de données SQL, en utilisant SQLAlchemy comme ORM et bcrypt pour le hachage des mots de passe. Tout d'abord, nous devons créer une classe User qui mappe la table des utilisateurs dans la base de données. Cette table contiendra des champs tels que l'identifiant, le nom d'utilisateur, l'email et le mot de passe haché.
Voici un extrait de code pour cette opération :
Dans cet exemple, la fonction add_user ajoute un utilisateur à la base de données après avoir haché son mot de passe. Si un utilisateur avec le même nom d'utilisateur ou email existe déjà, une exception IntegrityError est levée.
Ensuite, nous devons définir un point d'API pour gérer l'enregistrement des utilisateurs. Nous allons utiliser FastAPI pour créer un endpoint de type POST, qui recevra les données de l'utilisateur (nom d'utilisateur, email et mot de passe), effectuera les validations nécessaires et renverra une réponse adéquate.
Le point d'API pourrait ressembler à ceci :
Ici, UserCreateBody est une structure de données contenant les informations nécessaires pour l'inscription d'un utilisateur. Si un utilisateur avec un email ou un nom d'utilisateur déjà existant tente de s'enregistrer, une exception HTTP 409 (Conflit) sera levée.
Intégration d’OAuth2 et JWT pour l’authentification
Une fois l’enregistrement des utilisateurs mis en place, la prochaine étape consiste à gérer leur authentification. OAuth2 avec JSON Web Tokens (JWT) est une méthode courante et robuste pour gérer l'authentification. OAuth2 permet une gestion centralisée des autorisations, et JWT sert à générer des tokens d’accès sécurisés.
Pour intégrer OAuth2 et JWT, nous devons définir un mécanisme permettant de générer un token pour les utilisateurs une fois leur identité vérifiée. Ce token pourra ensuite être utilisé pour effectuer des requêtes authentifiées vers les points d'API.
Un exemple simplifié de code pour générer et vérifier un JWT serait le suivant :
L’utilisation de JWT permet à vos utilisateurs de se connecter en toute sécurité et de maintenir leurs sessions actives sans nécessiter de nouvelles connexions à chaque requête. Le token peut être stocké côté client (dans les cookies ou le stockage local), et transmis via les entêtes HTTP.
Authentification multi-facteurs (MFA)
L'ajout d'une couche de sécurité supplémentaire à l'authentification par mot de passe est fortement recommandé. L'authentification multi-facteurs (MFA) permet de renforcer la sécurité en demandant à l'utilisateur de valider son identité via un second facteur, comme un code envoyé par SMS ou généré par une application d'authentification.
L'implémentation de la MFA nécessite de configurer un mécanisme pour gérer ces codes et vérifier leur validité avant de permettre l'accès à l'application. FastAPI, avec ses points d'API et ses capacités de gestion des sessions, est bien adapté pour cela.
Authentification via des services tiers
De plus en plus d’applications intègrent des services tiers tels que GitHub, Google, ou Facebook pour simplifier l’authentification des utilisateurs. Cela permet à vos utilisateurs de se connecter rapidement sans avoir à créer de nouveaux identifiants, et vous permet également de déléguer la gestion de la sécurité à des plateformes éprouvées.
L’intégration de services tiers se fait en utilisant des protocoles standards comme OAuth2, qui sont pris en charge par des bibliothèques comme Authlib ou FastAPI.
Contrôle d’accès basé sur les rôles (RBAC)
Pour gérer l’accès à vos API de manière granulaire, vous pouvez mettre en place un système de contrôle d’accès basé sur les rôles (RBAC). Ce mécanisme vous permet de définir des rôles (par exemple, administrateur, utilisateur, modérateur) et d’attribuer des permissions spécifiques à chaque rôle.
En utilisant FastAPI, vous pouvez créer un système de vérification des rôles de vos utilisateurs via des dépendances, ce qui vous permet de restreindre l’accès aux points d’API en fonction du rôle de l’utilisateur.
Gestion des clés d’API
Pour protéger vos points d'API et vous assurer que seules des requêtes autorisées peuvent y accéder, vous pouvez mettre en place une authentification par clé d’API. Ce mécanisme est particulièrement utile pour l’intégration de services externes ou la création d’applications front-end qui doivent interagir avec votre API sans nécessiter de gestion complexe des sessions.
Les clés d’API peuvent être attribuées à des utilisateurs ou à des services spécifiques, et peuvent être stockées dans une base de données ou un système de gestion sécurisé.
Comment implémenter des tâches en arrière-plan dans FastAPI pour améliorer les performances
Lors de la création d'applications web modernes, l'optimisation des performances devient un élément clé. En particulier, la gestion des tâches en arrière-plan permet de traiter des processus complexes ou de longue durée sans bloquer l'exécution du serveur ou interférer avec l'expérience utilisateur. Dans le cadre de FastAPI, l'implémentation de tâches en arrière-plan peut grandement améliorer la réactivité de votre application, notamment pour des cas comme le stockage de données dans des bases externes ou l'exécution de traitements lourds.
Imaginons que nous avons une application de plateforme de voyages où nous souhaitons enregistrer des messages envoyés via un endpoint, tel que GET /v2/trips/{category}, dans une base de données externe à des fins d'analyse. L’implémentation de cette fonctionnalité s’effectue en deux étapes simples.
Dans un premier temps, nous définissons une fonction de traitement qui simule l’opération d'enregistrement dans un module dédié, par exemple background_tasks.py, dans le répertoire de l’application. Cette fonction pourrait ressembler à ceci :
L'opération de stockage est simulée par asyncio.sleep, une opération non-bloquante permettant de ne pas bloquer le fil d'exécution. Des messages de log sont ajoutés pour suivre l’exécution de cette fonction.
Ensuite, pour exécuter cette tâche en arrière-plan, nous modifions l'endpoint GET /v2/trips/{category} dans notre fichier principal main.py. Voici comment procéder :
Ici, nous avons ajouté la tâche en arrière-plan avec background_tasks.add_task, ce qui permet à la fonction store_query_to_external_db de s'exécuter de manière asynchrone après la réponse de l'API. Lorsque l'utilisateur effectue une requête, la tâche est mise en file d'attente et sera exécutée de manière concurrente sans bloquer le serveur.
Après avoir démarré le serveur avec uvicorn app.main:app, l'appel de l'endpoint GET /v2/trips/cruises déclenchera la tâche en arrière-plan, et vous pourrez observer dans les logs les messages relatifs à l’enregistrement du message.
Bien que cette approche soit suffisante pour des tâches relativement simples, pour des calculs plus intensifs ou des tâches longues, il peut être pertinent d'utiliser des outils dédiés comme Celery, qui permet de gérer les tâches en arrière-plan dans un processus séparé et ainsi éviter les problèmes de performance liés à l'exécution dans le même processus que le serveur web.
Le fonctionnement des tâches en arrière-plan dans FastAPI repose sur le principe de la boucle d’événements (event loop), qui permet d’exécuter les tâches de manière non-bloquante, en les inscrivant dans un objet BackgroundTasks. Cela garantit que l'exécution des tâches ne bloque pas la réponse HTTP et permet une gestion concurrente des tâches.
Dans certains cas, comme des calculs lourds nécessitant une puissance de traitement importante, utiliser des outils comme Celery peut s'avérer plus adapté. Celery permet de gérer des files d'attente et d'exécuter les tâches dans des processus séparés, assurant ainsi que les performances du serveur ne soient pas affectées par des traitements longs.
Outre l’aspect technique de l’implémentation, il est essentiel de comprendre que l’utilisation de tâches en arrière-plan dans une application FastAPI permet de mieux gérer les opérations de longue durée sans affecter l’expérience utilisateur. Cependant, une telle gestion nécessite également une attention particulière aux ressources du serveur, notamment lorsqu'il s'agit de gérer un grand nombre de tâches simultanées ou des opérations nécessitant des ressources importantes.
En somme, l’utilisation des tâches en arrière-plan dans FastAPI est un moyen efficace d’améliorer la réactivité d'une application. Toutefois, pour des scénarios plus complexes, l'usage de solutions comme Celery peut offrir une meilleure scalabilité et résilience. Une bonne gestion de ces tâches et une surveillance adéquate de leur exécution sont cruciales pour garantir des performances optimales.
Comment gérer les connexions WebSocket dans une application FastAPI
Lorsqu'une connexion WebSocket est établie entre un client et un serveur FastAPI, il est essentiel de bien comprendre le processus sous-jacent et les différentes étapes permettant d'assurer une communication bidirectionnelle fiable et fluide. Dans cet article, nous allons explorer la gestion des connexions WebSocket, l'envoi et la réception de messages en temps réel, ainsi que la gestion des déconnexions, un aspect crucial pour maintenir une interaction continue sans perturbations.
Les connexions WebSocket permettent une communication bidirectionnelle, ce qui signifie que les messages peuvent être envoyés et reçus simultanément entre le client et le serveur. Cela contraste avec le modèle traditionnel de requêtes et réponses HTTP, où la communication est unidirectionnelle. En configurant correctement un point de terminaison WebSocket, le serveur peut accepter des connexions clients, envoyer des messages, recevoir des données et fermer la connexion lorsque cela est nécessaire.
Lorsqu'un serveur reçoit une demande de connexion via WebSocket, il démarre un processus appelé "handshake" (serrement de main HTTP) pour établir la connexion avec le client. Cela commence par la méthode await websocket.accept() sur le serveur. Une fois la connexion établie, le serveur peut envoyer un message d'accueil à l'utilisateur grâce à la méthode await websocket.send_text("Bienvenue dans la salle de chat !"). Ce message informe le client que la connexion est réussie et qu'il peut maintenant interagir avec le serveur. L'étape suivante consiste à attendre des messages entrants, les traiter, puis envoyer une réponse. Pour ce faire, la méthode await websocket.receive_text() permet au serveur de recevoir les messages envoyés par le client, de les stocker dans une variable, puis de les traiter selon les besoins.
L'exemple de code suivant montre comment configurer un tel endpoint dans FastAPI :
Dans cet exemple, le serveur attend continuellement des messages du client et répond par un accusé de réception. Cette approche permet de maintenir une communication ouverte sans fermer la connexion après chaque message, ce qui est crucial pour les applications en temps réel comme les chats en ligne.
Il est important de noter que, bien que ce modèle de communication soit très utile, il existe plusieurs défis liés à la gestion de la connexion WebSocket, notamment les déconnexions et les erreurs qui peuvent survenir. Par exemple, lorsqu'un client se déconnecte, une exception WebSocketDisconnect peut être levée si la déconnexion n'est pas correctement gérée. Cela nécessite l'ajout de blocs try-except dans le code pour intercepter cette exception et ainsi éviter des erreurs non capturées sur le serveur. Voici un exemple pour gérer la déconnexion côté client :
Cette modification permet au serveur de capter les déconnexions des clients et de les traiter de manière appropriée, en enregistrant un avertissement dans les logs sans provoquer de crash du serveur.
De même, une déconnexion côté serveur peut se produire si le serveur décide de fermer la connexion pour une raison spécifique, comme la réception d’un message particulier. Par exemple, si le serveur reçoit le message "disconnect", il peut alors fermer la connexion. Cette gestion proactive des déconnexions côté serveur assure une meilleure stabilité et un contrôle accru sur le flux de communication.
Voici un exemple de gestion d'une déconnexion côté serveur :
Dans ce scénario, le serveur attend des messages et, lorsqu'il reçoit "disconnect", il répond avec un message et ferme la connexion avec await websocket.close(). Cela permet de contrôler explicitement la durée de la connexion.
L'échange de messages en temps réel via WebSocket est une fonctionnalité puissante dans le développement d'applications modernes. Il permet des interactions rapides et fluides, mais nécessite une gestion attentive des connexions et des erreurs. Lors de la conception de tels systèmes, il est crucial de penser à la gestion des déconnexions, tant côté client que serveur, pour garantir la stabilité et la réactivité de l'application.
Il est également important de noter que, bien que la gestion des WebSockets dans FastAPI soit relativement simple, elle nécessite des outils appropriés pour tester les connexions. Par exemple, Postman peut être utilisé pour simuler des connexions WebSocket et tester l'envoi et la réception de messages en temps réel. De plus, il existe des fonctionnalités avancées comme la validation des messages reçus au format JSON ou binaire, qui peuvent être utilisées pour rendre l'application encore plus robuste.
Enfin, bien que FastAPI ne supporte pas directement les WebSockets dans la documentation Swagger, vous pouvez toujours suivre les discussions en cours sur GitHub pour des mises à jour futures concernant cette fonctionnalité.
Comment intégrer FastAPI avec d'autres bibliothèques Python et GraphQL
Pour débuter l'intégration de FastAPI avec GraphQL, il est essentiel de configurer un environnement de développement adapté en installant les bibliothèques nécessaires. Vous pouvez utiliser le fichier requirements.txt du projet ou la commande pip pour installer FastAPI ainsi que d'autres dépendances comme Uvicorn et Strawberry-GraphQL :
Une fois l'installation terminée, vous pouvez entamer la création d'un point d'accès GraphQL en suivant plusieurs étapes.
La première consiste à définir un module database.py, où vous allez simuler une base de données avec une liste d'utilisateurs. Commencez par créer une classe User avec les attributs suivants : identifiant (id), nom d'utilisateur (username), numéro de téléphone (phone_number) et pays (country). Utilisez pydantic.BaseModel pour garantir la validation des données.
Ensuite, créez une liste d'objets User qui servira de source de données dans ce module. Par exemple, cette liste pourrait contenir plusieurs utilisateurs provenant de pays différents. Pour cet exemple, voici comment vous pourriez la définir :
Ensuite, dans un module séparé nommé graphql_utils.py, il vous faudra définir une requête GraphQL pour interroger cette "base de données". Pour ce faire, vous devez d'abord définir le modèle qui sera retourné par la requête. Par exemple, vous pouvez utiliser la bibliothèque Strawberry pour définir un type GraphQL correspondant à un utilisateur.
La prochaine étape consiste à définir la requête elle-même, qui permettra de filtrer les utilisateurs en fonction du pays passé en argument. Voici un exemple de cette requête GraphQL :
Cette requête retourne tous les utilisateurs d'un pays spécifié. Une fois la requête définie, vous pouvez créer un schéma GraphQL et l'intégrer à FastAPI via le routeur GraphQLRouter de Strawberry.
Enfin, dans un module main.py, vous allez inclure ce routeur GraphQL à l'application FastAPI. L'URL de l'endpoint sera /graphql, ce qui permettra d'accéder à l'interface interactive de GraphQL via le navigateur.
Lorsque vous lancez le serveur avec Uvicorn :
Vous pouvez accéder à l'interface interactive de GraphQL en vous rendant à l'adresse http://localhost:8000/graphql dans votre navigateur. Dans l'éditeur de requêtes GraphQL à gauche, vous pouvez saisir la requête suivante pour obtenir la liste des utilisateurs d'un pays spécifique, par exemple, les utilisateurs des États-Unis :
Le panneau de droite affichera les résultats sous forme JSON, vous permettant de visualiser les données extraites de la base.
En combinant les points d'accès RESTful et GraphQL, vous pouvez considérablement étendre les possibilités de requêtes et de modifications de données. Dans des scénarios réels, les points d'accès REST peuvent être utilisés pour modifier la base de données, tandis que GraphQL sert à extraire des informations spécifiques selon des critères définis. Cela permet une plus grande flexibilité dans la gestion et l'extraction des données.
Il est important de noter que l'utilisation conjointe de REST et de GraphQL dans une même application nécessite une gestion soigneuse des endpoints afin de ne pas dupliquer les responsabilités entre les deux technologies. Par ailleurs, l'intégration de GraphQL avec FastAPI permet de bénéficier de la rapidité de FastAPI tout en ayant la souplesse de GraphQL pour des requêtes de données complexes.
Comment la règle des trapèzes généralisée améliore la précision des intégrations dans les problèmes de barres axiales
Comment les étudiants développent-ils la maîtrise des compétences complexes?
L'expérience féministe et l'évolution de l'intersectionnalité : une approche méthodologique dynamique
Quelle place pour l'empirisme logique et le réalisme critique dans l'économie écologique ?
Quelles sont les leçons les plus importantes de l'anthropologie ?

Deutsch
Francais
Nederlands
Svenska
Norsk
Dansk
Suomi
Espanol
Italiano
Portugues
Magyar
Polski
Cestina
Русский