英文:
"AttributeError: 'property' object has no attribute 'get'" when using Depends in FastAPI
问题
为了在FastAPI端点中实现身份验证,我想要利用FastAPI最新版本(>=0.95)提供的Depends
功能。我已经尝试了几种实现方式,但遇到了一个错误:“AttributeError: 'property' object has no attribute 'get'”。这意味着在使用Depends
时,Starlette的Request
对象未被识别为这样的对象。
端点实现:
@app.get("/")
async def home(user: Annotated[User, Depends(authenticate_request(Request))]):
"""
status _summary_
Returns status message if service is running
"""
if isinstance(user, User):
return {"Welcome, service is running ok!"}
raise HTTPException(
status_code=401,
detail="User not authorized!",
)
authenticate_request
函数检查基于提供的 Request
的 cookie 的有效性:
def authenticate_request(request: Request) -> User:
cookie1 = request.cookies.get("x")
cookie2 = request.cookies.get("y")
if cookie1 is not None and cookie2 is not None:
tenant = get_tenant(request)
if user := authenticate_cookies(cookie1, cookie2, tenant):
if not tenant.startswith(user.tenant):
print("Unauthorized: Token hostname mismatch")
raise Exception("Token hostname mismatch")
return user
print("Unauthorized: please login")
raise HTTPException(status_code=401, detail="Unauthorized: please login")
这导致错误:“AttributeError: 'property' object has no attribute 'get'”。这意味着 Request
对象未正确传递或未被正确识别。
然后,我尝试解决这个问题,而不使用 Depends
:
@app.get("/")
async def home(request: Request):
"""
status _summary_
Returns status message if service is running
"""
user = authenticate_request(request=request)
if isinstance(user, User):
return {"Welcome, service is running ok!"}
raise HTTPException(
status_code=401,
detail="User not authorized!",
)
这个方法是正常工作的。如果没有提供有效的 cookie,就会返回 401 错误。基于这一点,我得出结论,我的 authenticate_request()
函数是正常工作的。
有人知道为什么在 Depends()
和另一种解决方案之间存在行为差异吗?
非常感谢帮助!
致敬,
Laurens
英文:
To implement authentication for a FastAPI endpoint, I want to make use of the Depends
functionality offered in the latest versions (>=0.95) of FastAPI. I have tried several ways to implement it but I am facing an error "AttributeError: 'property' object has no attribute 'get'"
. This implies that the starlette Request
object is not recognised as such when using Depends
.
Endpoint implementation:
@app.get("/")
async def home(user: Annotated[User, Depends(authenticate_request(Request))]):
"""
status _summary_
Returns status message if service is running
"""
if isinstance(user, User):
return {"Welcome, service is running ok!"}
raise HTTPException(
status_code=401,
detail="User not authorized!",
)
Function authenticate_request
checks validity of cookies based on provided Request:
def authenticate_request(request: Request) -> User:
cookie1 = request.cookies.get("x")
cookie2 = request.cookies.get("y")
if cookie1 is not None and cookie2 is not None:
tenant = get_tenant(request)
if user := authenticate_cookies(cookie1, cookie2, tenant):
if not tenant.startswith(user.tenant):
print("Unauthorized: Token hostname mismatch")
raise Exception("Token hostname mismatch")
return user
print("Unauthorized: please login")
raise HTTPException(status_code=401, detail="Unauthorized: please login")
This results in error "AttributeError: 'property' object has no attribute 'get'"
. This implies that the Request
object is not passed correctly or is not recognised as such.
I then tried to solve this without using Depends
:
@app.get("/")
async def home(request: Request):
"""
status _summary_
Returns status message if service is running
"""
user = authenticate_request(request=request)
if isinstance(user, User):
return {"Welcome, service is running ok!"}
raise HTTPException(
status_code=401,
detail="User not authorized!",
)
This is working correctly. If no valid cookie is provided a 401 is returned. Based on this I come to the conclusion that my authenticate_request() function is working correctly.
Does anybody know why there is a difference in behaviour between Depends()
and the alternative solution?
Help is much appreciated!
Regards,
Laurens
答案1
得分: 1
当使用 Depends()
时,您只需在括号内传递依赖函数的名称。如 文档 中所述:
> 首先,让我们专注于依赖项。
>
> 它只是一个函数,可以接受与路径操作函数相同的所有参数。
>
> 它具有与所有路径操作函数相同的形状和结构。
>
> 您可以将其视为一个没有“装饰器”的路径操作函数(没有 @app.get("/some-path")
)。
>
> 它可以返回您想要的任何内容。
因此,您的依赖函数需要使用的任何其他参数,您只需在该函数中声明它们,而不是通过 Depends()
传递它们。同样适用于 Request
对象。
因此,您的路径操作函数(也称为端点)应如下所示:
@app.get("/")
async def home(user: Annotated[User, Depends(authenticate_request)]):
pass
您的 authenticate_request
依赖函数应如下所示:
def authenticate_request(request: Request) -> User:
pass
英文:
When using Depends()
, you just need to pass the name of the dependency function within the brackets. As described in the documentation:
> Let's first focus on the dependency.
>
> It is just a function that can take all the same parameters that a
> path operation function can take.
>
> And it has the same shape and structure that all your path operation
> functions have.
>
> You can think of it as a path operation function without the
> "decorator" (without the @app.get("/some-path")
).
>
> And it can return anything you want.
Thus, any other parameters that your dependency function takes, you simply need to declare them in that function and not passing them through Depends()
. Same applies to the Request
object.
Hence, your path operation function (also known as endpoint) should look like this:
@app.get("/")
async def home(user: Annotated[User, Depends(authenticate_request)]):
pass
and your authenticate_request
dependency function should be as follows:
def authenticate_request(request: Request) -> User:
pass
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论