Pourquoi Déployer FastAPI sur Firebase ?
FastAPI est une framework Python pour construire des APIs rapides et efficaces. Firebase, de son côté, est un ensemble d'outils et de services de Google qui permettent de développer, tester, déployer et gérer des applications en temps réel. L'intégration de FastAPI avec Firebase peut offrir plusieurs avantages :
- Déploiement rapide : Firebase offre une infrastructure pour le déploiement rapide et facile des applications.
- Scalabilité : Firebase est conçu pour s'adapter à la croissance de votre application.
- Sécurité : Firebase propose des fonctionnalités de sécurité robustes, permettant de protéger vos données.
- Intégration : Firebase peut être facilement intégré avec d'autres services Google et tiers.
Un cas d'utilisation concret serait le développement d'une API pour une application mobile ou web qui nécessite une base de données réactive et des fonctionnalités en temps réel.
Prerequisites
Avant de commencer ce tutoriel, vous aurez besoin des éléments suivants :
- Python 3.6+ : Pour exécuter FastAPI.
- Node.js et npm : Pour Firebase CLI.
- Google Cloud Account : Compte gratuit disponible pour tester Firebase.
Concepts Fondamentaux
1. FastAPI
FastAPI est un framework pour construire des APIs rapides en utilisant Python 3.7+ et les types de données. Il utilise le format JSON pour la communication avec le client et offre une meilleure performance que d'autres frameworks comme Flask ou Django.
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
2. Firebase CLI
Firebase Command Line Interface permet de gérer votre projet Firebase à partir de la ligne de commande. Vous pouvez installer et configurer Firebase CLI avec les commandes suivantes :
npm install -g firebase-tools
firebase login
3. Firebase Functions
Firebase Functions vous permettent d'exécuter du code JavaScript sur le backend sans avoir besoin de gérer les serveurs.
const functions = require('firebase-functions');
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send("Hello from Firebase Functions!");
});
exports.app = functions.https.onRequest(app);
Mise en Pratique : Projet Fil Rouge
Nous allons construire un gestionnaire de tâches simple avec FastAPI et Firebase.
Étape 1 : Configuration du projet
Créez un nouveau dossier pour votre projet et initialisez-le :
mkdir fastapi-firebase-todo
cd fastapi-firebase-todo
Initialisez un environnement virtuel Python et installez FastAPI et Uvicorn (pour le serveur ASGI) :
python3 -m venv venv
source venv/bin/activate # Sur Windows : venv\Scripts\activate
pip install fastapi uvicorn
Étape 2 : Création de l'application FastAPI
Créez un fichier main.py et ajoutez le code suivant :
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import uuid
app = FastAPI()
## Mock database
todos = {}
class Todo(BaseModel):
id: str = None
task: str
completed: bool = False
@app.post("/todos/")
def create_todo(todo: Todo):
todo.id = str(uuid.uuid4())
todos[todo.id] = todo
return todo
@app.get("/todos/{todo_id}")
def read_todo(todo_id: str):
if todo_id in todos:
return todos[todo_id]
raise HTTPException(status_code=404, detail="Todo not found")
@app.put("/todos/{todo_id}")
def update_todo(todo_id: str, todo: Todo):
if todo_id in todos:
todos[todo_id] = todo
return todo
raise HTTPException(status_code=404, detail="Todo not found")
@app.delete("/todos/{todo_id}")
def delete_todo(todo_id: str):
if todo_id in todos:
del todos[todo_id]
return {"message": "Todo deleted"}
raise HTTPException(status_code=404, detail="Todo not found")
Étape 3 : Lancement de l'application
Exécutez votre application avec Uvicorn :
uvicorn main:app --reload
Étape 4 : Configuration Firebase Functions
Créez un nouveau dossier functions et initialisez-le avec Firebase CLI :
firebase init functions
Suivez les instructions pour choisir le language (JavaScript) et installer les dépendances.
Étape 5 : Intégration de FastAPI dans Firebase Functions
Créez un fichier index.js dans le dossier functions et ajoutez le code suivant :
const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors');
const { createClient } = require('@supabase/supabase-js');
// Initialize Supabase client (Mock database for Firebase Functions)
const supabaseUrl = 'https://your-supabase-url.supabase.co';
const supabaseAnonKey = 'your-supabase-anon-key';
const supabase = createClient(supabaseUrl, supabaseAnonKey);
const app = express();
app.use(cors());
// Mock database operations
async function getTodo(todoId) {
const { data, error } = await supabase.from('todos').select('*').eq('id', todoId);
if (error) throw new Error(error.message);
return data[0];
}
async function createTodo(todo) {
if (error) throw new Error(error.message);
return data[0];
}
// FastAPI endpoints in Firebase Functions
app.get('/todos/:id', async (req, res) => {
try {
const todo = await getTodo(req.params.id);
res.json(todo);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post('/todos/', async (req, res) => {
try {
const { task } = req.body;
const todo = await createTodo({ id: uuid.v4(), task, completed: false });
res.json(todo);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
exports.app = functions.https.onRequest(app);
Étape 6 : Déploiement des fonctions Firebase
Déployez vos fonctions Firebase :
firebase deploy --only functions
Erreurs Fréquentes et Debugging
1. TypeError: Cannot read property 'id' of undefined
Ce code cause une erreur car todo n'est pas défini correctement.
## ❌ Mauvais
@app.post("/todos/")
def create_todo(todo):
todo.id = str(uuid.uuid4())
todos[todo.id] = todo
return todo
## ✅ Correct
@app.post("/todos/")
def create_todo(todo: Todo):
todo.id = str(uuid.uuid4())
todos[todo.id] = todo
return todo
2. AttributeError: module 'uuid' has no attribute 'uuid4'
Ce code cause une erreur car uuid4 est incorrectement importé.
## ❌ Mauvais
import uuid
@app.post("/todos/")
def create_todo(todo):
todo.id = str(uuid.uuid4())
todos[todo.id] = todo
return todo
## ✅ Correct
from uuid import uuid4
@app.post("/todos/")
def create_todo(todo):
todo.id = str(uuid4())
todos[todo.id] = todo
return todo
3. 500 Internal Server Error: 'NoneType' object is not iterable
Ce code cause une erreur car il tente d'itérer sur un objet None.
## ❌ Mauvais
@app.get("/todos/")
def read_todos():
return todos
## ✅ Correct
@app.get("/todos/")
def read_todos():
if todos:
return todos
raise HTTPException(status_code=404, detail="No todos found")
Pour Aller Plus loin
- Intégration avec Firebase Authentication : Ajoutez une couche de sécurité en intégrant Firebase Authentication pour gérer les utilisateurs.
- Déploiement sur Google Cloud Run : Déployez votre application FastAPI sur Google Cloud Run pour un hébergement plus robuste.
- Tests unitaires et d'intégration : Ajoutez des tests unitaires et d'intégration pour assurer la qualité de votre code.
Défi Pratique
Créez une application FastAPI qui utilise Firebase Firestore pour stocker les données, et ajoutez des fonctionnalités comme l'ajout, la lecture, la mise à jour et la suppression de documents.