我有一个带有下载终结点的FastAPI应用。此下载终结点的作用是使用BlobServiceClient
(用于Azure Blob存储)生成令牌和请求中指定的文件的Blob URL。我想要做的是将用户重定向到该URL。以下是下载终结点的代码片段(我注解掉了一些内容,因为不允许我显示代码)。
@router.get("..path", tags=["some tags"], summary=..., responses={404: {"model": ...}, 403: {"model": ...}, 307: {"model": ...}}, response_model_exclude_none=True)
async def download_file(
# there's a depends on an API key
blob_path: str = Query(
...
)):
credential = ClientSecretCredential(...) //secrets
blob_service_client = BlobServiceClient(f"https://{storage_account}.blob.core.windows.net", credential=credential)
user_delegation_key = blob_service_client.get_user_delegation_key(key_start_time=datetime.utcnow(),key_expiry_time=datetime.utcnow() + timedelta(minutes=30))
token = generate_blob_sas(account_name=...,
container_name=...,
blob_name=blob_path,
user_delegation_key=user_delegation_key,
permission=BlobSasPermissions(read=True),
expiry=datetime.utcnow() + timedelta(minutes=30))
blob_url = f'https://{storage_account}.blob.core.windows.net/{container_name}/{blob_path}?{token}'
print(blob_url)
response = RedirectResponse(blob_url)
return response
我所期望的是查询被执行,响应返回后,下载在后台或单独的选项卡中开始,而我得到的是一个不同的响应,正如您在Swagger中所看到的:
第一节第一节第一节第一节第一次
我还查看了Network选项卡,以了解该请求的情况:
第一节第二节第一节第三节第一节
看起来有一个OPTIONS
请求,我认为我得到了该请求的响应。不确定这是否是Swagger处理请求的方式。任何想法如何/为什么会发生这种情况,以及如何修复它?谢谢!
1条答案
按热度按时间q5iwbnjs1#
首先,CORS中的HTTP OPTIONS是由浏览器在实际请求之前自动发出的preflight request,而不是返回
File
响应的preflight request。它请求给定服务器允许的通信选项,服务器使用包含一组允许方法的Access-Control-Allow-Methods
头进行响应(例如Access-Control-Allow-Methods: OPTIONS, GET, HEAD, POST, DELETE
)。对于在同一URL中创建的请求,可以使用Access-Control-Max-Age
报头选择性地缓存预检响应,从而允许服务器限制预检请求的数量。该报头的值以秒表示;因此,例如,允许高速缓存10分钟将看起来像Access-Control-Max-Age: 600
。对于
RedirectResponse
,Swagger UI总是跟随重定向响应,例如,在fetch
请求中,redirect
参数将被设置为follow
。表示应该遵循redirect
。这意味着Swagger UI遵循重定向并等待响应完全接收,然后再提供Download file
链接(如你上面提供的截图所示)来下载文件。这也是为什么你不能看到下载开始无论是在后台或一个新的标签页。正如上面的链接github帖子提到的,它是不可能的,例如,改变redirect
到manual
,所以Swagger不遵循重定向,这可能会让你有不同的处理方式。除了使用Swagger UI来测试特定的端点之外,您还可以通过在浏览器的地址栏中键入API端点的URL来直接测试它(因为它是
GET
端点,您可以这样做),或者创建您自己的自定义Template(或使用HTMLResponse
)并提交HTML<form>
,如this answer所示。