YchKhan commited on
Commit
e3fc855
·
verified ·
1 Parent(s): 6a74cc8

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +125 -0
app.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ from fastapi import FastAPI, WebSocket, WebSocketDisconnect, Request
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.middleware.cors import CORSMiddleware
5
+ from typing import List, Dict
6
+ import uvicorn
7
+
8
+ # Initialiser l'application FastAPI
9
+ app = FastAPI()
10
+
11
+ # Configurer CORS pour autoriser toutes les origines
12
+ # Permet à n'importe quel site web d'appeler votre API
13
+ app.add_middleware(
14
+ CORSMiddleware,
15
+ allow_origins=["*"], # Autorise toutes les origines
16
+ allow_credentials=True,
17
+ allow_methods=["*"], # Autorise toutes les méthodes (GET, POST, etc.)
18
+ allow_headers=["*"], # Autorise tous les en-têtes
19
+ )
20
+
21
+ # Monter un répertoire statique pour servir le fichier index.html
22
+ app.mount("/static", StaticFiles(directory="static"), name="static")
23
+
24
+ class ConnectionManager:
25
+ """Gère les connexions WebSocket actives."""
26
+ def __init__(self):
27
+ self.active_connections: List[WebSocket] = []
28
+ # Dictionnaire pour attendre les réponses des clients
29
+ self.response_futures: Dict[str, asyncio.Future] = {}
30
+
31
+ async def connect(self, websocket: WebSocket):
32
+ """Accepte une nouvelle connexion WebSocket."""
33
+ await websocket.accept()
34
+ self.active_connections.append(websocket)
35
+ print(f"Nouvelle connexion WebSocket. Total: {len(self.active_connections)}")
36
+
37
+ def disconnect(self, websocket: WebSocket):
38
+ """Ferme une connexion WebSocket."""
39
+ self.active_connections.remove(websocket)
40
+ print(f"Déconnexion WebSocket. Total: {len(self.active_connections)}")
41
+
42
+ async def broadcast(self, message: str):
43
+ """Envoie un message à tous les clients connectés."""
44
+ # Pour ce cas simple, nous n'envoyons qu'au premier client connecté
45
+ if self.active_connections:
46
+ websocket = self.active_connections[0]
47
+ await websocket.send_text(message)
48
+ # Créer un Future pour attendre la réponse
49
+ future = asyncio.get_event_loop().create_future()
50
+ # Utilise l'identifiant du client comme clé, bien que simple, c'est plus robuste
51
+ client_id = str(id(websocket))
52
+ self.response_futures[client_id] = future
53
+ return future
54
+ return None
55
+
56
+ manager = ConnectionManager()
57
+
58
+ @app.post("/v1/mock")
59
+ async def mock_endpoint(request: Request):
60
+ """
61
+ Endpoint API qui prend un string, le transmet via WebSocket,
62
+ attend une réponse et la retourne.
63
+ """
64
+ try:
65
+ # Récupérer les données JSON du corps de la requête
66
+ data = await request.json()
67
+ input_string = data.get("parameter")
68
+
69
+ if input_string is None:
70
+ return {"error": "Le paramètre 'parameter' est manquant."}
71
+
72
+ print(f"Endpoint /v1/mock appelé avec: '{input_string}'")
73
+
74
+ if not manager.active_connections:
75
+ return {"error": "Aucun client WebSocket n'est connecté."}
76
+
77
+ # Envoyer le message via WebSocket et obtenir un "future" pour la réponse
78
+ print("Envoi du message au client WebSocket...")
79
+ response_future = await manager.broadcast(input_string)
80
+
81
+ if response_future is None:
82
+ return {"error": "Échec de la diffusion du message."}
83
+
84
+ try:
85
+ # Attendre la réponse du client WebSocket avec un timeout de 10 secondes
86
+ websocket_response = await asyncio.wait_for(response_future, timeout=10.0)
87
+ print(f"Réponse reçue du WebSocket: '{websocket_response}'")
88
+ return {"response_from_client": websocket_response}
89
+
90
+ except asyncio.TimeoutError:
91
+ print("Timeout: Aucune réponse du client WebSocket.")
92
+ return {"error": "Timeout: Le client n'a pas répondu à temps."}
93
+
94
+ except Exception as e:
95
+ print(f"Erreur dans /v1/mock: {e}")
96
+ return {"error": f"Une erreur interne est survenue: {str(e)}"}
97
+
98
+
99
+ @app.websocket("/ws")
100
+ async def websocket_endpoint(websocket: WebSocket):
101
+ """Gère la communication WebSocket avec le client."""
102
+ await manager.connect(websocket)
103
+ try:
104
+ while True:
105
+ # Attendre un message du client
106
+ data = await websocket.receive_text()
107
+ print(f"Message reçu du client: '{data}'")
108
+
109
+ # Trouver le "future" correspondant et y mettre le résultat
110
+ client_id = str(id(websocket))
111
+ if client_id in manager.response_futures:
112
+ manager.response_futures[client_id].set_result(data)
113
+ del manager.response_futures[client_id] # Nettoyer après utilisation
114
+
115
+ except WebSocketDisconnect:
116
+ manager.disconnect(websocket)
117
+ print("Client déconnecté.")
118
+ except Exception as e:
119
+ print(f"Erreur dans le WebSocket: {e}")
120
+ manager.disconnect(websocket)
121
+
122
+
123
+ if __name__ == "__main__":
124
+ # Lance le serveur sur le port 8000
125
+ uvicorn.run(app, host="0.0.0.0", port=8000)