bohea / sanic-limiter

Provides rate limiting features for Sanic. Supports in-memory, redis and memcache as storage.
MIT License
85 stars 14 forks source link

[Bug] sanic-limiter not working with websocket routes #21

Open pansila opened 3 years ago

pansila commented 3 years ago

websocket routes are wrapped by sanic.

Error log

Traceback (most recent call last):
  File "C:\Users\abc\AppData\Local\pypoetry\Cache\virtualenvs\ember-VqhvFD7x-py3.9\lib\site-packages\sanic\app.py", line 908, in handle_request
    response = await self._run_request_middleware(
  File "C:\Users\abc\AppData\Local\pypoetry\Cache\virtualenvs\ember-VqhvFD7x-py3.9\lib\site-packages\sanic\app.py", line 1265, in _run_request_middleware
    response = middleware(request)
  File "C:\Users\abc\AppData\Local\pypoetry\Cache\virtualenvs\ember-VqhvFD7x-py3.9\lib\site-packages\sanic_limiter\extension.py", line 160, in __check_request_limit
    name = ("{}.{}".format(view_func.__module__, view_func.__name__) if view_func else "")
AttributeError: 'functools.partial' object has no attribute '__module__'

sanic_limiter\extension.py

    def __check_request_limit(self, request):
        endpoint = request.path or ""
        view_handler = self.app.router.routes_static.get(endpoint, None)
        if view_handler is None:
            return
        view_func = view_handler.handler
        view_bpname = view_func.__dict__.get('__blueprintname__', None)
        name = ("{}.{}".format(view_func.__module__, view_func.__name__) if view_func else "")
        ...

sanic\app.py

    # Decorator
    def websocket(
        self,
        uri,
        host=None,
        strict_slashes=None,
        subprotocols=None,
        version=None,
        name=None,
    ):
    ...
        def response(handler):
            if isinstance(handler, tuple):
                # if a handler fn is already wrapped in a route, the handler
                # variable will be a tuple of (existing routes, handler fn)
                routes, handler = handler
            else:
                routes = []
            websocket_handler = partial(
                self._websocket_handler, handler, subprotocols=subprotocols
            )