FastAPI TestClient发送POST/PUT请求时异常重定向问题
问题原因
该重定向问题是路由匹配规则和测试路径写法错误共同导致的:
- FastAPI底层基于Starlette实现,默认开启尾部斜杠自动修正逻辑:如果路由定义为不带尾部斜杠的格式(比如示例中的
@router.post("/test")),当请求携带尾部斜杠的对应路径时,服务端会自动返回307临时重定向,跳转至不带斜杠的正确路由地址。 - 你的测试代码中POST请求的路径存在两个错误:
- 路径缺少开头的前导斜杠
/,属于相对路径格式,TestClient处理重定向时的相对路径拼接逻辑会失效,最终跳转到测试服务的根地址http://testserver - 路径末尾多了多余的斜杠,刚好触发上述框架的斜杠重定向逻辑
- 路径缺少开头的前导斜杠
- GET请求未触发异常,通常是因为GET请求的路径写法符合规则,未触发重定向;即便GET请求路径带多余斜杠,TestClient对GET请求的重定向解析容错性更高,不会出现跳转到根地址的问题。
解决方法
你可以选择以下任意一种方案修复:
方案1:修正测试请求路径(推荐)
将测试代码中的请求路径改为和服务端路由完全匹配的格式:
- 路径开头必须加前导斜杠
/ - 尾部斜杠和服务端路由定义保持一致
- 路径前缀和APIRouter的挂载配置匹配:如果你的router挂载时设置了
prefix="/api",则完整路径为/api/test;如果没有设置前缀,完整路径为/test
修正后的测试代码示例:
from starlette.testclient import TestClient from app import app client = TestClient(app) def test_cookies(): res = client.post( # 注意前导斜杠,去掉末尾多余斜杠,根据实际挂载前缀调整路径 "/api/test", json={ "name": "test" }, # 调试阶段可以加这个参数关闭自动重定向,方便直接查看响应状态排查问题 # follow_redirects=False ) assert 200 == res.status_code
方案2:调整路由定义适配带斜杠的请求
如果你希望接口支持带尾部斜杠的访问,可以修改路由定义,在路径末尾加上斜杠,同时测试请求路径也对应保持一致即可:
# 路由定义改为带尾部斜杠 @router.post("/test/") async def test( request: Request, ): try: body = await request.json() except JSONDecodeError: return JSONResponse(content={}, status_code=HTTP_400_BAD_REQUEST) return JSONResponse(content=body)
对应测试请求路径改为/api/test/(同样需要加前导斜杠)即可。
内容的提问来源于stack exchange,提问作者Mahdi Sorkhmiri
相关产品推荐
相关产品推荐

