最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

FastAPI WebSocket returns 403 Forbidden when trying to access via Postman - Stack Overflow

programmeradmin2浏览0评论

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 badges
Add a comment  | 

1 Answer 1

Reset to default 0

Turns 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.

发布评论

评论列表(0)

  1. 暂无评论
ok 不同模板 switch ($forum['model']) { /*case '0': include _include(APP_PATH . 'view/htm/read.htm'); break;*/ default: include _include(theme_load('read', $fid)); break; } } break; case '10': // 主题外链 / thread external link http_location(htmlspecialchars_decode(trim($thread['description']))); break; case '11': // 单页 / single page $attachlist = array(); $imagelist = array(); $thread['filelist'] = array(); $threadlist = NULL; $thread['files'] > 0 and list($attachlist, $imagelist, $thread['filelist']) = well_attach_find_by_tid($tid); $data = data_read_cache($tid); empty($data) and message(-1, lang('data_malformation')); $tidlist = $forum['threads'] ? page_find_by_fid($fid, $page, $pagesize) : NULL; if ($tidlist) { $tidarr = arrlist_values($tidlist, 'tid'); $threadlist = well_thread_find($tidarr, $pagesize); // 按之前tidlist排序 $threadlist = array2_sort_key($threadlist, $tidlist, 'tid'); } $allowpost = forum_access_user($fid, $gid, 'allowpost'); $allowupdate = forum_access_mod($fid, $gid, 'allowupdate'); $allowdelete = forum_access_mod($fid, $gid, 'allowdelete'); $access = array('allowpost' => $allowpost, 'allowupdate' => $allowupdate, 'allowdelete' => $allowdelete); $header['title'] = $thread['subject']; $header['mobile_link'] = $thread['url']; $header['keywords'] = $thread['keyword'] ? $thread['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>