FastAPI发送JSON请求报连接拒绝错误的原因与解决方法
结论
你的判断完全错误,连接拒绝异常和requests库是同步实现没有任何关系。
根因分析
报错核心原因是发送请求时FastAPI服务尚未完成启动,8000端口没有进程监听,代码逻辑时序完全错误:
- 你写的
if __name__ == 'webhook_fastapi'分支,只有当前文件被其他模块作为库导入时才会触发——直接运行脚本时Python固定将当前模块名设为__main__,这个分支不会在启动时立刻执行。 - 实际执行流程:运行脚本 → 进入
if __name__ == '__main__'分支调用uvicorn.run()→ uvicorn启动过程中会重新导入名为webhook_fastapi的模块 → 模块加载时触发if __name__ == 'webhook_fastapi'分支,立刻发起POST请求 → 此时uvicorn还在加载应用、未绑定8000端口启动监听,直接触发连接拒绝错误。
补充说明:同步requests和FastAPI异步模式不兼容的表现是请求处理过程中事件循环被阻塞,其他并发请求无法被处理,绝不会触发连接拒绝类错误。
额外的代码问题
if __name__ == '__main__'分支里手动实例化的BackgroundTasks是冗余代码,和FastAPI路由注入的对象完全无关,没有任何作用。- 用
requests发送JSON数据不需要手动序列化+加请求头,直接传json=data参数即可,库会自动处理。
FastAPI中发送JSON请求的最简实现
FastAPI官方推荐使用异步HTTP库httpx发送请求,不会阻塞事件循环,适配异步运行模式,步骤如下:
- 安装依赖:
pip install fastapi uvicorn httpx
- 修正后的可运行代码:
import time from fastapi import Request, FastAPI, BackgroundTasks import uvicorn import httpx def printmessage(job): time.sleep(5) print(job) app = FastAPI() # 服务启动完成后自动执行的钩子 @app.on_event("startup") async def send_test_req(): async with httpx.AsyncClient() as client: data = {'text': 'hello'} resp = await client.post( url='http://127.0.0.1:8000/webhook', json=data ) print(f"Request Sent! 响应状态码:{resp.status_code}") @app.post("/webhook") async def webhook(request: Request, background_tasks: BackgroundTasks): print("WEBHOOK RECEIVED") job = "doctor" background_tasks.add_task(printmessage, job) print('done') return 'WEBHOOK RECEIVED' if __name__ == '__main__': print("PROGRAM LAUNCH...") print("WEBHOOK RECEIVE READY...") uvicorn.run("webhook_fastapi:app", host="127.0.0.1", port=8000, reload=False)
其他可选方案
如果坚持要用同步的requests库,只需要把发送请求的逻辑放在同步函数中,不要在async标记的异步函数里直接调用即可:
- 路由如果定义为普通同步函数(不加
async关键字),FastAPI会自动将其调度到线程池执行,同步requests不会阻塞事件循环。 - 不要在模块顶层、启动/关闭钩子这些异步执行的上下文里直接调用同步
requests,否则会卡住事件循环。
内容的提问来源于stack exchange,提问作者Jimmy
相关产品推荐
相关产品推荐

