GET请求URI保留字符经encodeURIComponent编码后FastAPI报404问题咨询
出现该问题的核心原因是Uvicorn等ASGI服务器会先对URL路径做一次解码,将%2F转为/后再交给FastAPI做路由匹配,导致原本的单段路径被拆分为多段,无法匹配预设路由。可通过以下方式解决:
方案1(最推荐):改用查询参数传递特殊标识
将原本放在路径中需要保留%2F等编码字符的参数挪到查询参数中传递,例如修改请求格式为:
http://localhost:4200/api/verifiers?target=https%3A%2F%2Fwww.web.com%2Fdev%2F0&service=xx%3Ayy%3AV00000000000000000000000000000000000000000000000000000000000000000000000000000000%23read-device
FastAPI接收查询参数时不会提前对内容做路径拆分,可完整读取编码后的内容,符合HTTP设计规范,无兼容风险。
方案2:使用path路径转换器捕获全段内容
如果必须将参数放在路径中,可在路由定义时使用FastAPI提供的path类型转换器,将可变路径段全部捕获后自行拆分解析:
from fastapi import FastAPI app = FastAPI() @app.get("/verifiers/{full_path:path}") async def handle_verifier(full_path: str): # 手动拆分full_path,提取目标url和service标识 target_url, service_id = full_path.rsplit("/services/", 1) # 后续业务逻辑
该方案会匹配/verifiers/之后的所有路径内容,不会因为编码后的%2F被解码为/导致路由匹配失败。
方案3:前端对路径参数做二次编码
前端在拼接路径前,对需要放入路径的参数执行两次encodeURIComponent处理:
// 前端Angular代码示例 const target = "https://www.web.com/dev/0"; const encodedTarget = encodeURIComponent(encodeURIComponent(target)); const serviceId = "xx:yy:V00000000000000000000000000000000000000000000000000000000000000000000000000000000#read-device"; const encodedService = encodeURIComponent(encodeURIComponent(serviceId)); // 拼接后路径中的%2F会被转为%252F,服务器解码一次后保留为%2F不会拆分路径 const requestUrl = `/api/verifiers/${encodedTarget}/services/${encodedService}`;
后端拿到参数后,执行一次urllib.parse.unquote即可得到原始内容。
该方案需要前后端配合修改,适合不想调整路由结构的场景,但不如方案1通用稳妥。
内容的提问来源于stack exchange,提问作者Antonio Santoro
相关产品推荐
相关产品推荐

