Encountered an error reporting: AttributeError: 'State' object has no attribute 'view_rate_limit'
239144498 opened this issue · 4 comments
Code reproduction:
slowapi code configuration
from slowapi.errors import RateLimitExceeded
from slowapi.middleware import SlowAPIMiddleware
def limiter_key_func(request: Request) -> str:
ip = request.headers.get("CF-Connecting-IP") or get_remote_address(request)
return ip
limiter = Limiter(key_func=limiter_key_func, default_limits=["1/second"])
def rate_limit_exceeded_handler(request: Request, exc: RateLimitExceeded) -> Response:
.
.
.
response = JSONResponse(content={"code": 429, "data": data, "msg": msg}, status_code=429)
response = request.app.state.limiter._inject_headers(response, request.state.view_rate_limit)
return response
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, rate_limit_exceeded_handler)
app.add_middleware(SlowAPIMiddleware)
This is my interface code
@app.get('/demo1')
@limiter.limit("100/day", override_defaults=False)
async def channel(request: Request):
return Response("A")
@app.get('/demo2')
@limiter.exempt
async def channel(request: Request):
return Response("B")
When I request the interface demo1 I get the error AttributeError: 'State' object has no attribute 'view_rate_limit', When I comment out the @limiter.exempt and then request the interface demo1, it works fine.
The following is the complete log of errors reported.
INFO: 127.0.0.1:12134 - "GET /demo1 HTTP/1.1" 500 Internal Server Error
ERROR 2022-10-11 13:22:55.444 - uvicorn.protocols.http.httptools_impl:run_asgi - Exception in ASGI application
Traceback (most recent call last):
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\anyio\streams\memory.py", line 81, in receive
return self.receive_nowait()
│ └ <function MemoryObjectReceiveStream.receive_nowait at 0x000001BAD1BD8280>
└ MemoryObjectReceiveStream(_state=MemoryObjectStreamState(max_buffer_size=0, buffer=deque([]), open_send_channels=0, open_rece...
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\anyio\streams\memory.py", line 76, in receive_nowait
raise WouldBlock
└ <class 'anyio.WouldBlock'>
anyio.WouldBlock
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 43, in call_next
message = await recv_stream.receive()
│ └ <function MemoryObjectReceiveStream.receive at 0x000001BAD1BD8310>
└ MemoryObjectReceiveStream(_state=MemoryObjectStreamState(max_buffer_size=0, buffer=deque([]), open_send_channels=0, open_rece...
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\anyio\streams\memory.py", line 101, in receive
raise EndOfStream
└ <class 'anyio.EndOfStream'>
anyio.EndOfStream
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "xxx\PycharmProjects\public_service2\app\main.py", line 10, in <module>
uvicorn.run(app=app, host="0.0.0.0", port=PORT, log_level="info", forwarded_allow_ips="*", access_log=True,
│ │ │ └ 8080
│ │ └ <fastapi.applications.FastAPI object at 0x000001BAD1ADC8B0>
│ └ <function run at 0x000001BACF787A30>
└ <module 'uvicorn' from 'xxx\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages\\uvicorn\\__init__....
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\uvicorn\main.py", line 447, in run
server.run()
│ └ <function Server.run at 0x000001BACF787D00>
└ <uvicorn.server.Server object at 0x000001BAD275D960>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\uvicorn\server.py", line 68, in run
return asyncio.run(self.serve(sockets=sockets))
│ │ │ │ └ None
│ │ │ └ <function Server.serve at 0x000001BACF787D90>
│ │ └ <uvicorn.server.Server object at 0x000001BAD275D960>
│ └ <function run at 0x000001BACF4FB250>
└ <module 'asyncio' from 'xxx\\AppData\\Local\\Programs\\Python\\Python310\\lib\\asyncio\\__init__.py'>
File "xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
│ │ └ <coroutine object Server.serve at 0x000001BAD273E030>
│ └ <function BaseEventLoop.run_until_complete at 0x000001BACF504CA0>
└ <_WindowsSelectorEventLoop running=True closed=False debug=False>
File "xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 628, in run_until_complete
self.run_forever()
│ └ <function BaseEventLoop.run_forever at 0x000001BACF504C10>
└ <_WindowsSelectorEventLoop running=True closed=False debug=False>
File "xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 595, in run_forever
self._run_once()
│ └ <function BaseEventLoop._run_once at 0x000001BACF506710>
└ <_WindowsSelectorEventLoop running=True closed=False debug=False>
File "xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\base_events.py", line 1881, in _run_once
handle._run()
│ └ <function Handle._run at 0x000001BACF4A5E10>
└ <Handle <TaskStepMethWrapper object at 0x000001BAD29004C0>()>
File "xxx\AppData\Local\Programs\Python\Python310\lib\asyncio\events.py", line 80, in _run
self._context.run(self._callback, *self._args)
│ │ │ │ │ └ <member '_args' of 'Handle' objects>
│ │ │ │ └ <Handle <TaskStepMethWrapper object at 0x000001BAD29004C0>()>
│ │ │ └ <member '_callback' of 'Handle' objects>
│ │ └ <Handle <TaskStepMethWrapper object at 0x000001BAD29004C0>()>
│ └ <member '_context' of 'Handle' objects>
└ <Handle <TaskStepMethWrapper object at 0x000001BAD29004C0>()>
> File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 375, in run_asgi
result = await app(self.scope, self.receive, self.send)
│ │ │ │ │ │ └ <function RequestResponseCycle.send at 0x000001BAD27CC8B0>
│ │ │ │ │ └ <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001BAD2886920>
│ │ │ │ └ <function RequestResponseCycle.receive at 0x000001BAD27CC940>
│ │ │ └ <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001BAD2886920>
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001BAD2886920>
└ <uvicorn.middleware.proxy_headers.ProxyHeadersMiddleware object at 0x000001BAD278ECE0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 75, in __call__
return await self.app(scope, receive, send)
│ │ │ │ └ <bound method RequestResponseCycle.send of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001BAD2...
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <fastapi.applications.FastAPI object at 0x000001BAD1ADC8B0>
└ <uvicorn.middleware.proxy_headers.ProxyHeadersMiddleware object at 0x000001BAD278ECE0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\fastapi\applications.py", line 269, in __call__
await super().__call__(scope, receive, send)
│ │ └ <bound method RequestResponseCycle.send of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001BAD2...
│ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
└ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\applications.py", line 124, in __call__
await self.middleware_stack(scope, receive, send)
│ │ │ │ └ <bound method RequestResponseCycle.send of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001BAD2...
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <starlette.middleware.errors.ServerErrorMiddleware object at 0x000001BAD278E830>
└ <fastapi.applications.FastAPI object at 0x000001BAD1ADC8B0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\errors.py", line 184, in __call__
raise exc
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\errors.py", line 162, in __call__
await self.app(scope, receive, _send)
│ │ │ │ └ <function ServerErrorMiddleware.__call__.<locals>._send at 0x000001BAD2848790>
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <starlette.middleware.cors.CORSMiddleware object at 0x000001BAD278E800>
└ <starlette.middleware.errors.ServerErrorMiddleware object at 0x000001BAD278E830>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\cors.py", line 84, in __call__
await self.app(scope, receive, send)
│ │ │ │ └ <function ServerErrorMiddleware.__call__.<locals>._send at 0x000001BAD2848790>
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <starlette.middleware.base.BaseHTTPMiddleware object at 0x000001BAD278E7A0>
└ <starlette.middleware.cors.CORSMiddleware object at 0x000001BAD278E800>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 68, in __call__
response = await self.dispatch_func(request, call_next)
│ │ │ └ <function BaseHTTPMiddleware.__call__.<locals>.call_next at 0x000001BAD2848820>
│ │ └ <starlette.requests.Request object at 0x000001BAD2835CC0>
│ └ <function mid at 0x000001BAD277E4D0>
└ <starlette.middleware.base.BaseHTTPMiddleware object at 0x000001BAD278E7A0>
File "xxx\PycharmProjects\public_service2\app\api\__init__.py", line 92, in mid
response = await call_next(request)
│ └ <starlette.requests.Request object at 0x000001BAD2835CC0>
└ <function BaseHTTPMiddleware.__call__.<locals>.call_next at 0x000001BAD2848820>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 46, in call_next
raise app_exc
└ AttributeError("'State' object has no attribute 'view_rate_limit'")
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 36, in coro
await self.app(scope, request.receive, send_stream.send)
│ │ │ │ │ │ └ <function MemoryObjectSendStream.send at 0x000001BAD1BD8A60>
│ │ │ │ │ └ MemoryObjectSendStream(_state=MemoryObjectStreamState(max_buffer_size=0, buffer=deque([]), open_send_channels=0, open_receive...
│ │ │ │ └ <property object at 0x000001BAD265D170>
│ │ │ └ <starlette.requests.Request object at 0x000001BAD2835CC0>
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <slowapi.middleware.SlowAPIMiddleware object at 0x000001BAD278E3B0>
└ <starlette.middleware.base.BaseHTTPMiddleware object at 0x000001BAD278E7A0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 68, in __call__
response = await self.dispatch_func(request, call_next)
│ │ │ └ <function BaseHTTPMiddleware.__call__.<locals>.call_next at 0x000001BAD2849630>
│ │ └ <starlette.requests.Request object at 0x000001BAD2900280>
│ └ <bound method SlowAPIMiddleware.dispatch of <slowapi.middleware.SlowAPIMiddleware object at 0x000001BAD278E3B0>>
└ <slowapi.middleware.SlowAPIMiddleware object at 0x000001BAD278E3B0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\slowapi\middleware.py", line 34, in dispatch
return await call_next(request)
│ └ <starlette.requests.Request object at 0x000001BAD2900280>
└ <function BaseHTTPMiddleware.__call__.<locals>.call_next at 0x000001BAD2849630>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 46, in call_next
raise app_exc
└ AttributeError("'State' object has no attribute 'view_rate_limit'")
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\middleware\base.py", line 36, in coro
await self.app(scope, request.receive, send_stream.send)
│ │ │ │ │ │ └ <function MemoryObjectSendStream.send at 0x000001BAD1BD8A60>
│ │ │ │ │ └ MemoryObjectSendStream(_state=MemoryObjectStreamState(max_buffer_size=0, buffer=deque([]), open_send_channels=0, open_receive...
│ │ │ │ └ <property object at 0x000001BAD265D170>
│ │ │ └ <starlette.requests.Request object at 0x000001BAD2900280>
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <starlette.exceptions.ExceptionMiddleware object at 0x000001BAD278E380>
└ <slowapi.middleware.SlowAPIMiddleware object at 0x000001BAD278E3B0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\exceptions.py", line 93, in __call__
raise exc
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\exceptions.py", line 82, in __call__
await self.app(scope, receive, sender)
│ │ │ │ └ <function ExceptionMiddleware.__call__.<locals>.sender at 0x000001BAD28FB880>
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <fastapi.middleware.asyncexitstack.AsyncExitStackMiddleware object at 0x000001BAD278E140>
└ <starlette.exceptions.ExceptionMiddleware object at 0x000001BAD278E380>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 21, in __call__
raise e
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\fastapi\middleware\asyncexitstack.py", line 18, in __call__
await self.app(scope, receive, send)
│ │ │ │ └ <function ExceptionMiddleware.__call__.<locals>.sender at 0x000001BAD28FB880>
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <fastapi.routing.APIRouter object at 0x000001BAD1ADC9A0>
└ <fastapi.middleware.asyncexitstack.AsyncExitStackMiddleware object at 0x000001BAD278E140>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\routing.py", line 670, in __call__
await route.handle(scope, receive, send)
│ │ │ │ └ <function ExceptionMiddleware.__call__.<locals>.sender at 0x000001BAD28FB880>
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <function Route.handle at 0x000001BAD2685750>
└ <fastapi.routing.APIRoute object at 0x000001BAD275DDE0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\routing.py", line 266, in handle
await self.app(scope, receive, send)
│ │ │ │ └ <function ExceptionMiddleware.__call__.<locals>.sender at 0x000001BAD28FB880>
│ │ │ └ <bound method RequestResponseCycle.receive of <uvicorn.protocols.http.httptools_impl.RequestResponseCycle object at 0x000001B...
│ │ └ {'type': 'http', 'asgi': {'version': '3.0', 'spec_version': '2.1'}, 'http_version': '1.1', 'server': ('127.0.0.1', 8080), 'cl...
│ └ <function request_response.<locals>.app at 0x000001BAD277CB80>
└ <fastapi.routing.APIRoute object at 0x000001BAD275DDE0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\routing.py", line 65, in app
response = await func(request)
│ └ <starlette.requests.Request object at 0x000001BAD2900670>
└ <function get_request_handler.<locals>.app at 0x000001BAD277CAF0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\fastapi\routing.py", line 227, in app
raw_response = await run_endpoint_function(
└ <function run_endpoint_function at 0x000001BAD26863B0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\fastapi\routing.py", line 160, in run_endpoint_function
return await dependant.call(**values)
│ │ └ {'x': '', 'x': 'xxx', 'x': 'xxx', 'request': <starlette.requests.Request object at 0x000001BAD2900670>}
│ └ <function channel at 0x000001BAD2705B40>
└ <fastapi.dependencies.models.Dependant object at 0x000001BAD275DED0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\slowapi\extension.py", line 646, in async_wrapper
response, request.state.view_rate_limit
│ │ └ <property object at 0x000001BAD265D080>
│ └ <starlette.requests.Request object at 0x000001BAD2900670>
└ <starlette.responses.Response object at 0x000001BAD29008E0>
File "xxx\AppData\Local\Programs\Python\Python310\lib\site-packages\starlette\datastructures.py", line 693, in __getattr__
raise AttributeError(message.format(self.__class__.__name__, key))
│ │ │ │ │ └ 'view_rate_limit'
│ │ │ │ └ <member '__name__' of 'getset_descriptor' objects>
│ │ │ └ <attribute '__class__' of 'object' objects>
│ │ └ <starlette.datastructures.State object at 0x000001BAD29008B0>
│ └ <method 'format' of 'str' objects>
└ "'{}' object has no attribute '{}'"
AttributeError: 'State' object has no attribute 'view_rate_limit'
SUCCESS 2022-10-11 13:22:56.883 - app.utile:init - init final
I don't know how to fix this error and I need help.
@239144498 thanks for opening this. Can you try to change the name of the route handlers so that they are different? Like channela
and channelb
for instance?
Even if they are fastapi routes, they are still python functions, and they should have different names, otherwise, you're essentially overriding one function definition with the other.
@239144498谢谢你打开这个。 您可以尝试更改路由处理程序的名称以使它们不同吗? 喜欢
channela
和channelb
例如?即使它们是 fastapi 路由,它们仍然是 python 函数,并且它们应该具有不同的名称,否则,您实际上是用另一个函数定义覆盖了一个函数定义。
Thanks for your answer, this problem is solved.
But I have one more question, the following code in
def check(request: Request):
ip = limiter_key_func(request)
if ip in whiteiplist:
return True
else:
return False
@app.get('/demo1')
@limiter.limit("100/day", override_defaults=False, exempt_when=check)
async def channel(request: Request):
return Response("A")
When I request interface demo1 the following error is reported.
File "xxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\slowapi\extension.py", line 635, in async_wrapper
self._check_request_limit(request, func, False)
File "xxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\slowapi\extension.py", line 535, in _check_request_limit
self.__evaluate_limits(request, endpoint, all_limits)
File "xxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\slowapi\extension.py", line 405, in __evaluate_limits
if lim.is_exempt:
File "xxxx\AppData\Local\Programs\Python\Python310\lib\site-packages\slowapi\wrappers.py", line 38, in is_exempt
return self.exempt_when() if self.exempt_when is not None else False
TypeError: check() missing 1 required positional argument: 'request'
What can I do to pass the request parameter to the check function?