I am trying to run a websocket from a server where it watches a file and broadcasts any changes to the file over the websocket. This is my code:
import os
import json
import uvicorn
import asyncio
from fastapi import FastAPI, WebSocket
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from config import CONFIG
WATCHED_FILE = CONFIG["WATCHED_FILE"]
# FastAPI App
app = FastAPI()
# WebSocket clients
active_connections = set()
class FileChangeHandler(FileSystemEventHandler):
""" Watches a file for changes and sends updates via WebSocket """
def on_modified(self, event):
""" Called when the file is modified """
if event.src_path == os.path.abspath(WATCHED_FILE):
with open(WATCHED_FILE, "r") as f:
content = f.read()
asyncio.run(send_to_websockets(content))
async def send_to_websockets(content):
""" Sends the file content to all connected WebSocket clients """
if active_connections:
message = json.dumps({"file_content": content})
await asyncio.gather(*(conn.send_text(message) for conn in active_connections))
print(f"Sent to WebSockets: {content}")
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
""" WebSocket endpoint to send file changes """
await websocket.accept()
active_connections.add(websocket)
try:
while True:
await websocket.receive_text() # Keep connection open
except:
pass
finally:
active_connections.remove(websocket)
# API Route to Check Status
@app.get("/")
def root():
return {"message": "File Watcher WebSocket API is running..."}
# Background Task to Watch File
@app.on_event("startup")
def start_watcher():
""" Starts the file watcher when the FastAPI server starts """
observer = Observer()
event_handler = FileChangeHandler()
observer.schedule(event_handler, path=os.path.dirname(os.path.abspath(WATCHED_FILE)), recursive=False)
observer.start()
print(f"Watching file: {WATCHED_FILE}")
# Run FastAPI Server
if __name__ == "__main__":
port = CONFIG.get('PORT', 8000) # Default to 8000 if PORT is not set
uvicorn.run("main:app", host="0.0.0.0", port=port)
When trying to connect to this via Postman ws://10.80.yyy.xxx:30pq/ws
I keep getting 403 Forbidden errors. I put debug statements around websocket.accept()
but they do not get printed on the server logs, indicating the request is rejected before reaching the endpoint function.
How to solve this problem? What configurations do I need to change?
I'm a novice at this. Any help would be much appreciated.
I am trying to run a websocket from a server where it watches a file and broadcasts any changes to the file over the websocket. This is my code:
import os
import json
import uvicorn
import asyncio
from fastapi import FastAPI, WebSocket
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from config import CONFIG
WATCHED_FILE = CONFIG["WATCHED_FILE"]
# FastAPI App
app = FastAPI()
# WebSocket clients
active_connections = set()
class FileChangeHandler(FileSystemEventHandler):
""" Watches a file for changes and sends updates via WebSocket """
def on_modified(self, event):
""" Called when the file is modified """
if event.src_path == os.path.abspath(WATCHED_FILE):
with open(WATCHED_FILE, "r") as f:
content = f.read()
asyncio.run(send_to_websockets(content))
async def send_to_websockets(content):
""" Sends the file content to all connected WebSocket clients """
if active_connections:
message = json.dumps({"file_content": content})
await asyncio.gather(*(conn.send_text(message) for conn in active_connections))
print(f"Sent to WebSockets: {content}")
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
""" WebSocket endpoint to send file changes """
await websocket.accept()
active_connections.add(websocket)
try:
while True:
await websocket.receive_text() # Keep connection open
except:
pass
finally:
active_connections.remove(websocket)
# API Route to Check Status
@app.get("/")
def root():
return {"message": "File Watcher WebSocket API is running..."}
# Background Task to Watch File
@app.on_event("startup")
def start_watcher():
""" Starts the file watcher when the FastAPI server starts """
observer = Observer()
event_handler = FileChangeHandler()
observer.schedule(event_handler, path=os.path.dirname(os.path.abspath(WATCHED_FILE)), recursive=False)
observer.start()
print(f"Watching file: {WATCHED_FILE}")
# Run FastAPI Server
if __name__ == "__main__":
port = CONFIG.get('PORT', 8000) # Default to 8000 if PORT is not set
uvicorn.run("main:app", host="0.0.0.0", port=port)
When trying to connect to this via Postman ws://10.80.yyy.xxx:30pq/ws
I keep getting 403 Forbidden errors. I put debug statements around websocket.accept()
but they do not get printed on the server logs, indicating the request is rejected before reaching the endpoint function.
How to solve this problem? What configurations do I need to change?
I'm a novice at this. Any help would be much appreciated.
Share Improve this question edited Apr 2 at 9:40 Christian Baumann 3,5434 gold badges24 silver badges45 bronze badges asked Apr 1 at 12:17 AnandaAnanda 1066 bronze badges1 Answer
Reset to default 0Turns out the problem was simply that my python script was not named main
, and there was another python app main.py on the same working directory.
For anyone else who may face similar issues in the future:
Please note that the name of your python script should match the uvicorn.run("<filename>:app", ...)
part.