繁体   English   中英

如何将 URL 作为路径参数传递给 FastAPI 路由?

[英]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

选项1

您可以简单地使用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

选项 2

正如评论部分中提到的@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))}  

选项 3

由于您的端点似乎接受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 Requesthttps://www.starlette.io/requests/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM