prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  There is an obvious bug in ASGI WebsocketConnection of Sanic
  ### Is there an existing issue for this?
  
  - [X] I have searched the existing issues
  
  ### Describe the bug
  
  I started my sanic app with UvicornWorker. The original websocket will become WebsocketConnection. When I call
  the ws.recv function will report an error if bytes data is received at this time.
  `KeyError：‘text’`
  [https://github.com/sanic-org/sanic/blob/main/sanic/server/websockets/connection.py](url)
  `    async def recv(self, *args, **kwargs) -> Optional[str]:
          message = await self._receive()
  
          if message["type"] == "websocket.receive":
              return message["text"]
          elif message["type"] == "websocket.disconnect":
              pass
  
          return None`
  There is no data of bytes type processed here.
  
  ### Code snippet
  
  _No response_
  
  ### Expected Behavior
  
  _No response_
  
  ### How do you run Sanic?
  
  ASGI
  
  ### Operating System
  
  ubuntu
  
  ### Sanic Version
  
  22.3
  
  ### Additional context
  
  _No response_
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `sanic/server/websockets/connection.py`
  Content:
  ```
  1 from typing import (
  2     Any,
  3     Awaitable,
  4     Callable,
  5     Dict,
  6     List,
  7     MutableMapping,
  8     Optional,
  9     Union,
  10 )
  11 
  12 
  13 ASIMessage = MutableMapping[str, Any]
  14 
  15 
  16 class WebSocketConnection:
  17     """
  18     This is for ASGI Connections.
  19     It provides an interface similar to WebsocketProtocol, but
  20     sends/receives over an ASGI connection.
  21     """
  22 
  23     # TODO
  24     # - Implement ping/pong
  25 
  26     def __init__(
  27         self,
  28         send: Callable[[ASIMessage], Awaitable[None]],
  29         receive: Callable[[], Awaitable[ASIMessage]],
  30         subprotocols: Optional[List[str]] = None,
  31     ) -> None:
  32         self._send = send
  33         self._receive = receive
  34         self._subprotocols = subprotocols or []
  35 
  36     async def send(self, data: Union[str, bytes], *args, **kwargs) -> None:
  37         message: Dict[str, Union[str, bytes]] = {"type": "websocket.send"}
  38 
  39         if isinstance(data, bytes):
  40             message.update({"bytes": data})
  41         else:
  42             message.update({"text": str(data)})
  43 
  44         await self._send(message)
  45 
  46     async def recv(self, *args, **kwargs) -> Optional[str]:
  47         message = await self._receive()
  48 
  49         if message["type"] == "websocket.receive":
  50             return message["text"]
  51         elif message["type"] == "websocket.disconnect":
  52             pass
  53 
  54         return None
  55 
  56     receive = recv
  57 
  58     async def accept(self, subprotocols: Optional[List[str]] = None) -> None:
  59         subprotocol = None
  60         if subprotocols:
  61             for subp in subprotocols:
  62                 if subp in self.subprotocols:
  63                     subprotocol = subp
  64                     break
  65 
  66         await self._send(
  67             {
  68                 "type": "websocket.accept",
  69                 "subprotocol": subprotocol,
  70             }
  71         )
  72 
  73     async def close(self, code: int = 1000, reason: str = "") -> None:
  74         pass
  75 
  76     @property
  77     def subprotocols(self):
  78         return self._subprotocols
  79 
  80     @subprotocols.setter
  81     def subprotocols(self, subprotocols: Optional[List[str]] = None):
  82         self._subprotocols = subprotocols or []
  83
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/sanic/server/websockets/connection.py b/sanic/server/websockets/connection.py
  --- a/sanic/server/websockets/connection.py
  +++ b/sanic/server/websockets/connection.py
  @@ -9,8 +9,10 @@
       Union,
   )
   
  +from sanic.exceptions import InvalidUsage
   
  -ASIMessage = MutableMapping[str, Any]
  +
  +ASGIMessage = MutableMapping[str, Any]
   
   
   class WebSocketConnection:
  @@ -25,8 +27,8 @@
   
       def __init__(
           self,
  -        send: Callable[[ASIMessage], Awaitable[None]],
  -        receive: Callable[[], Awaitable[ASIMessage]],
  +        send: Callable[[ASGIMessage], Awaitable[None]],
  +        receive: Callable[[], Awaitable[ASGIMessage]],
           subprotocols: Optional[List[str]] = None,
       ) -> None:
           self._send = send
  @@ -47,7 +49,13 @@
           message = await self._receive()
   
           if message["type"] == "websocket.receive":
  -            return message["text"]
  +            try:
  +                return message["text"]
  +            except KeyError:
  +                try:
  +                    return message["bytes"].decode()
  +                except KeyError:
  +                    raise InvalidUsage("Bad ASGI message received")
           elif message["type"] == "websocket.disconnect":
               pass
  
verification_info: {"golden_diff": "diff --git a/sanic/server/websockets/connection.py b/sanic/server/websockets/connection.py\n--- a/sanic/server/websockets/connection.py\n+++ b/sanic/server/websockets/connection.py\n@@ -9,8 +9,10 @@\n     Union,\n )\n \n+from sanic.exceptions import InvalidUsage\n \n-ASIMessage = MutableMapping[str, Any]\n+\n+ASGIMessage = MutableMapping[str, Any]\n \n \n class WebSocketConnection:\n@@ -25,8 +27,8 @@\n \n     def __init__(\n         self,\n-        send: Callable[[ASIMessage], Awaitable[None]],\n-        receive: Callable[[], Awaitable[ASIMessage]],\n+        send: Callable[[ASGIMessage], Awaitable[None]],\n+        receive: Callable[[], Awaitable[ASGIMessage]],\n         subprotocols: Optional[List[str]] = None,\n     ) -> None:\n         self._send = send\n@@ -47,7 +49,13 @@\n         message = await self._receive()\n \n         if message[\"type\"] == \"websocket.receive\":\n-            return message[\"text\"]\n+            try:\n+                return message[\"text\"]\n+            except KeyError:\n+                try:\n+                    return message[\"bytes\"].decode()\n+                except KeyError:\n+                    raise InvalidUsage(\"Bad ASGI message received\")\n         elif message[\"type\"] == \"websocket.disconnect\":\n             pass\n", "issue": "There is an obvious bug in ASGI WebsocketConnection of Sanic\n### Is there an existing issue for this?\n\n- [X] I have searched the existing issues\n\n### Describe the bug\n\nI started my sanic app with UvicornWorker. The original websocket will become WebsocketConnection. When I call\r\nthe ws.recv function will report an error if bytes data is received at this time.\r\n`KeyError\uff1a\u2018text\u2019`\r\n[https://github.com/sanic-org/sanic/blob/main/sanic/server/websockets/connection.py](url)\r\n`    async def recv(self, *args, **kwargs) -> Optional[str]:\r\n        message = await self._receive()\r\n\r\n        if message[\"type\"] == \"websocket.receive\":\r\n            return message[\"text\"]\r\n        elif message[\"type\"] == \"websocket.disconnect\":\r\n            pass\r\n\r\n        return None`\r\nThere is no data of bytes type processed here.\n\n### Code snippet\n\n_No response_\n\n### Expected Behavior\n\n_No response_\n\n### How do you run Sanic?\n\nASGI\n\n### Operating System\n\nubuntu\n\n### Sanic Version\n\n22.3\n\n### Additional context\n\n_No response_\n", "before_files": [{"content": "from typing import (\n    Any,\n    Awaitable,\n    Callable,\n    Dict,\n    List,\n    MutableMapping,\n    Optional,\n    Union,\n)\n\n\nASIMessage = MutableMapping[str, Any]\n\n\nclass WebSocketConnection:\n    \"\"\"\n    This is for ASGI Connections.\n    It provides an interface similar to WebsocketProtocol, but\n    sends/receives over an ASGI connection.\n    \"\"\"\n\n    # TODO\n    # - Implement ping/pong\n\n    def __init__(\n        self,\n        send: Callable[[ASIMessage], Awaitable[None]],\n        receive: Callable[[], Awaitable[ASIMessage]],\n        subprotocols: Optional[List[str]] = None,\n    ) -> None:\n        self._send = send\n        self._receive = receive\n        self._subprotocols = subprotocols or []\n\n    async def send(self, data: Union[str, bytes], *args, **kwargs) -> None:\n        message: Dict[str, Union[str, bytes]] = {\"type\": \"websocket.send\"}\n\n        if isinstance(data, bytes):\n            message.update({\"bytes\": data})\n        else:\n            message.update({\"text\": str(data)})\n\n        await self._send(message)\n\n    async def recv(self, *args, **kwargs) -> Optional[str]:\n        message = await self._receive()\n\n        if message[\"type\"] == \"websocket.receive\":\n            return message[\"text\"]\n        elif message[\"type\"] == \"websocket.disconnect\":\n            pass\n\n        return None\n\n    receive = recv\n\n    async def accept(self, subprotocols: Optional[List[str]] = None) -> None:\n        subprotocol = None\n        if subprotocols:\n            for subp in subprotocols:\n                if subp in self.subprotocols:\n                    subprotocol = subp\n                    break\n\n        await self._send(\n            {\n                \"type\": \"websocket.accept\",\n                \"subprotocol\": subprotocol,\n            }\n        )\n\n    async def close(self, code: int = 1000, reason: str = \"\") -> None:\n        pass\n\n    @property\n    def subprotocols(self):\n        return self._subprotocols\n\n    @subprotocols.setter\n    def subprotocols(self, subprotocols: Optional[List[str]] = None):\n        self._subprotocols = subprotocols or []\n", "path": "sanic/server/websockets/connection.py"}], "after_files": [{"content": "from typing import (\n    Any,\n    Awaitable,\n    Callable,\n    Dict,\n    List,\n    MutableMapping,\n    Optional,\n    Union,\n)\n\nfrom sanic.exceptions import InvalidUsage\n\n\nASGIMessage = MutableMapping[str, Any]\n\n\nclass WebSocketConnection:\n    \"\"\"\n    This is for ASGI Connections.\n    It provides an interface similar to WebsocketProtocol, but\n    sends/receives over an ASGI connection.\n    \"\"\"\n\n    # TODO\n    # - Implement ping/pong\n\n    def __init__(\n        self,\n        send: Callable[[ASGIMessage], Awaitable[None]],\n        receive: Callable[[], Awaitable[ASGIMessage]],\n        subprotocols: Optional[List[str]] = None,\n    ) -> None:\n        self._send = send\n        self._receive = receive\n        self._subprotocols = subprotocols or []\n\n    async def send(self, data: Union[str, bytes], *args, **kwargs) -> None:\n        message: Dict[str, Union[str, bytes]] = {\"type\": \"websocket.send\"}\n\n        if isinstance(data, bytes):\n            message.update({\"bytes\": data})\n        else:\n            message.update({\"text\": str(data)})\n\n        await self._send(message)\n\n    async def recv(self, *args, **kwargs) -> Optional[str]:\n        message = await self._receive()\n\n        if message[\"type\"] == \"websocket.receive\":\n            try:\n                return message[\"text\"]\n            except KeyError:\n                try:\n                    return message[\"bytes\"].decode()\n                except KeyError:\n                    raise InvalidUsage(\"Bad ASGI message received\")\n        elif message[\"type\"] == \"websocket.disconnect\":\n            pass\n\n        return None\n\n    receive = recv\n\n    async def accept(self, subprotocols: Optional[List[str]] = None) -> None:\n        subprotocol = None\n        if subprotocols:\n            for subp in subprotocols:\n                if subp in self.subprotocols:\n                    subprotocol = subp\n                    break\n\n        await self._send(\n            {\n                \"type\": \"websocket.accept\",\n                \"subprotocol\": subprotocol,\n            }\n        )\n\n    async def close(self, code: int = 1000, reason: str = \"\") -> None:\n        pass\n\n    @property\n    def subprotocols(self):\n        return self._subprotocols\n\n    @subprotocols.setter\n    def subprotocols(self, subprotocols: Optional[List[str]] = None):\n        self._subprotocols = subprotocols or []\n", "path": "sanic/server/websockets/connection.py"}]}