[英]How to pass URL as a path parameter to a FastAPI route?
我使用 FastAPI 创建了一个简单的 API,我正尝试将 URL 作为任意path
参数传递给 FastAPI 路由。
from fastapi import FastAPI
app = FastAPI()
@app.post("/{path}")
def pred_image(path:str):
print("path",path)
return {'path':path}
当我测试它时,它不起作用并抛出错误。 我正在这样测试它:
http://127.0.0.1:8000/https://raw.githubusercontent.com/ultralytics/yolov5/master/data/images/zidane.jpg
您可以简单地使用path
转换器(如Starlette 文档中所述)来获取path
,包括任何额外的/
字符。
@app.api_route('/{_:path}', methods=["GET", "POST"])
def pred_image(request: Request):
return {"path": request.url.path[1:]}
使用以下测试:
http://127.0.0.1:8000/https://raw.githubusercontent.com/ultralytics/yolov5/master/data/images/zidane.jpg
正如评论部分中提到的@luk2302,您的客户端(即最终用户、javascript 等)需要对 URL 进行编码。 但是,@luk2302 提供的编码 URL 似乎不起作用,导致"detail": "Not Found"
错误。 事实证明,您需要对其进行两次编码才能工作。 那是:
http://127.0.0.1:8000/https%253A%252F%252Fraw.githubusercontent.com%252Fultralytics%252Fyolov5%252Fmaster%252Fdata%252Fimages%252Fzidane.jpg
在服务器端,您可以对 URL 进行解码(两次),如下所示:
from urllib.parse import unquote
@app.post("/{path}")
def pred_image(path: str):
return {'path':unquote(unquote(path))}
由于您的端点似乎接受POST
请求,您可能会考虑让客户端在请求正文中发送图像 URL,而不是将其作为路径参数发送。 请查看此处和此处的答案,以及FastAPI 的文档,了解如何执行此操作。
如果您通过在浏览器的地址栏中键入上述 URL 来测试这一点 - 而不是某种其他客户端,例如通过 Javascript、Python 请求等 - 您需要将端点的方法更改为仅GET
(即,对于选项 1: @app.api_route('/{_:path}', methods=["GET"])
和对于选项 2: @app.get("/{path}")
)。 否则,如果尝试通过浏览器的地址栏进行测试,您将遇到{"detail":"Method Not Allowed"}
错误(当您在浏览器的地址栏中键入 URL 时,它会执行GET
请求)。
示例: http://127.0.0.1:8000/porxy/https://raw.githubusercontent.com/ultralytics/yolov5/master/data/images/zidane.jpg
这个通过了 url 没有?
查询参数,只需要
@app.get('/proxy/{url:path}')
async def proxy(url:str):
# url:https://raw.githubusercontent.com/ultralytics/yolov5/master/data/images/zidane.jpg
return url
{var:path}
可以匹配:
和/
,但会停止在?
,所以如果你想得到完整的 url,你需要from fastapi import Request
。 req.val
包含完整的 url,包括主机。 示例: http://127.0.0.1:8000/porxy/http://www.xx.com/abc?query=abc
PS: HttpUrl
用于检查传递的url是否合法
from pydantic import HttpUrl
from fastapi import FastAPI, Request
app = FastAPI()
# example request url http://127.0.0.1:8000/proxy/http://www.xx.com/abc?query=abc
@app.get('/proxy/{url:path}', )
async def proxy(url: HttpUrl, req: Request):
# url: http://www.xx.com/abc
# req.url: http://127.0.0.1:8000/porxy/http://www.xx.com/abc?query=abc
# wanted_url: http://www.xx.com/abc?query=abc
wanted_url = str(req.url).partition('/proxy/')[-1]
return {'url': url, 'req_url': str(req.url), 'wanted_url': wanted_url}
if __name__ == '__main__':
import uvicorn
uvicorn.run('main:app', port=8000)
Path convertor
https://fastapi.tiangolo.com/tutorial/path-params/#path-convertor
使用直接来自 Starlette 的选项,您可以使用 URL 声明包含路径的路径参数,例如:
/files/{file_path:path}
在这种情况下,参数的名称是file_path
,最后一部分:path
告诉它参数应该匹配任何路径。
所以,你可以使用它:
from fastapi import FastAPI app = FastAPI()
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}
starlette Request
: https://www.starlette.io/requests/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.