Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Encountered an error reporting: AttributeError: 'State' object has no attribute 'view_rate_limit' #114

Closed
239144498 opened this issue Oct 11, 2022 · 4 comments

Comments

@239144498
Copy link

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.

@laurentS
Copy link
Owner

@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
Copy link
Author

@239144498谢谢你打开这个。 您可以尝试更改路由处理程序的名称以使它们不同吗? 喜欢 channelachannelb例如?

即使它们是 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?

@laurentS
Copy link
Owner

This should help #13

@239144498
Copy link
Author

这应该有助于 #13

这应该有助于 #13

Thank you very much, this is a workable solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants