prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Websocket not working at non-root path
  ### Please confirm the following
  
  - [X] I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).
  - [X] I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.
  - [X] I understand that AWX is open source software provided for free and that I might not receive a timely response.
  
  ### Summary
  
  Changes from #11342 and #652 are not full
  
  ### AWX version
  
  21.0.0
  
  ### Select the relevant components
  
  - [X] UI
  - [ ] API
  - [ ] Docs
  
  ### Installation method
  
  kubernetes
  
  ### Modifications
  
  no
  
  ### Ansible version
  
  _No response_
  
  ### Operating system
  
  _No response_
  
  ### Web browser
  
  _No response_
  
  ### Steps to reproduce
  
  Deploy AWX with custom `ingress_path: /awx`
  
  ### Expected results
  
  websocket should work
  
  ### Actual results
  
  `2022-05-17 08:46:41,031 ERROR    [-] daphne.ws_protocol [Failure instance: Traceback: <class 'ValueError'>: No route found for path 'awx/websocket/'.
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/autobahn/websocket/protocol.py:2841:processHandshake
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/txaio/tx.py:366:as_future
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/ws_protocol.py:72:onConnect
  --- <exception caught here> ---
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/server.py:201:create_application
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:54:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:47:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:145:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:169:__init__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/middleware.py:31:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:150:__call__
  ]
  2022-05-17 08:46:41,031 ERROR    [Failure instance: Traceback: <class 'ValueError'>: No route found for path 'awx/websocket/'.
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/autobahn/websocket/protocol.py:2841:processHandshake
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/txaio/tx.py:366:as_future
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/ws_protocol.py:72:onConnect
  --- <exception caught here> ---
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/server.py:201:create_application
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:54:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:47:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:145:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:169:__init__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/middleware.py:31:__call__
  /var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:150:__call__`
  
  ### Additional information
  
  It seems that issue is in  https://github.com/ansible/awx/blob/48b016802c517ff04d1cff4c43e64f17bb77a7a8/awx/main/routing.py
  
  ```
  websocket_urlpatterns = [
      re_path(r'websocket/$', consumers.EventConsumer),
      re_path(r'websocket/broadcast/$', consumers.BroadcastConsumer),
  ]
  ```
  From https://docs.djangoproject.com/en/4.0/ref/urls/:
  
  When a route ends with $ the whole requested URL, matching against path_info, must match the regular expression pattern (re.fullmatch() is used).
  
  Replacing with
  
  ```
  websocket_urlpatterns = [
      re_path(r'websocket/', consumers.EventConsumer),
      re_path(r'websocket/broadcast/', consumers.BroadcastConsumer),
  ]
  ```
  
  solves the issue
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `awx/main/routing.py`
  Content:
  ```
  1 import redis
  2 import logging
  3 
  4 from django.conf import settings
  5 from django.urls import re_path
  6 
  7 from channels.auth import AuthMiddlewareStack
  8 from channels.routing import ProtocolTypeRouter, URLRouter
  9 
  10 from . import consumers
  11 
  12 
  13 logger = logging.getLogger('awx.main.routing')
  14 
  15 
  16 class AWXProtocolTypeRouter(ProtocolTypeRouter):
  17     def __init__(self, *args, **kwargs):
  18         try:
  19             r = redis.Redis.from_url(settings.BROKER_URL)
  20             for k in r.scan_iter('asgi:*', 500):
  21                 logger.debug(f"cleaning up Redis key {k}")
  22                 r.delete(k)
  23         except redis.exceptions.RedisError as e:
  24             logger.warning("encountered an error communicating with redis.")
  25             raise e
  26         super().__init__(*args, **kwargs)
  27 
  28 
  29 websocket_urlpatterns = [
  30     re_path(r'websocket/', consumers.EventConsumer.as_asgi()),
  31     re_path(r'websocket/broadcast/', consumers.BroadcastConsumer.as_asgi()),
  32 ]
  33 
  34 application = AWXProtocolTypeRouter(
  35     {
  36         'websocket': AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),
  37     }
  38 )
  39
  ```
  --- 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/awx/main/routing.py b/awx/main/routing.py
  --- a/awx/main/routing.py
  +++ b/awx/main/routing.py
  @@ -27,8 +27,8 @@
   
   
   websocket_urlpatterns = [
  -    re_path(r'websocket/', consumers.EventConsumer.as_asgi()),
  -    re_path(r'websocket/broadcast/', consumers.BroadcastConsumer.as_asgi()),
  +    re_path(r'websocket/$', consumers.EventConsumer.as_asgi()),
  +    re_path(r'websocket/broadcast/$', consumers.BroadcastConsumer.as_asgi()),
   ]
   
   application = AWXProtocolTypeRouter(
  
verification_info: {"golden_diff": "diff --git a/awx/main/routing.py b/awx/main/routing.py\n--- a/awx/main/routing.py\n+++ b/awx/main/routing.py\n@@ -27,8 +27,8 @@\n \n \n websocket_urlpatterns = [\n-    re_path(r'websocket/', consumers.EventConsumer.as_asgi()),\n-    re_path(r'websocket/broadcast/', consumers.BroadcastConsumer.as_asgi()),\n+    re_path(r'websocket/$', consumers.EventConsumer.as_asgi()),\n+    re_path(r'websocket/broadcast/$', consumers.BroadcastConsumer.as_asgi()),\n ]\n \n application = AWXProtocolTypeRouter(\n", "issue": "Websocket not working at non-root path\n### Please confirm the following\n\n- [X] I agree to follow this project's [code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html).\n- [X] I have checked the [current issues](https://github.com/ansible/awx/issues) for duplicates.\n- [X] I understand that AWX is open source software provided for free and that I might not receive a timely response.\n\n### Summary\n\nChanges from #11342 and #652 are not full\n\n### AWX version\n\n21.0.0\n\n### Select the relevant components\n\n- [X] UI\n- [ ] API\n- [ ] Docs\n\n### Installation method\n\nkubernetes\n\n### Modifications\n\nno\n\n### Ansible version\n\n_No response_\n\n### Operating system\n\n_No response_\n\n### Web browser\n\n_No response_\n\n### Steps to reproduce\n\nDeploy AWX with custom `ingress_path: /awx`\n\n### Expected results\n\nwebsocket should work\n\n### Actual results\n\n`2022-05-17 08:46:41,031 ERROR    [-] daphne.ws_protocol [Failure instance: Traceback: <class 'ValueError'>: No route found for path 'awx/websocket/'.\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/autobahn/websocket/protocol.py:2841:processHandshake\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/txaio/tx.py:366:as_future\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/ws_protocol.py:72:onConnect\r\n--- <exception caught here> ---\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/server.py:201:create_application\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:54:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:47:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:145:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:169:__init__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/middleware.py:31:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:150:__call__\r\n]\r\n2022-05-17 08:46:41,031 ERROR    [Failure instance: Traceback: <class 'ValueError'>: No route found for path 'awx/websocket/'.\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/autobahn/websocket/protocol.py:2841:processHandshake\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/txaio/tx.py:366:as_future\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/ws_protocol.py:72:onConnect\r\n--- <exception caught here> ---\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/twisted/internet/defer.py:151:maybeDeferred\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/daphne/server.py:201:create_application\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:54:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:47:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:145:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/sessions.py:169:__init__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/middleware.py:31:__call__\r\n/var/lib/awx/venv/awx/lib64/python3.9/site-packages/channels/routing.py:150:__call__`\n\n### Additional information\n\nIt seems that issue is in  https://github.com/ansible/awx/blob/48b016802c517ff04d1cff4c43e64f17bb77a7a8/awx/main/routing.py\r\n\r\n```\r\nwebsocket_urlpatterns = [\r\n    re_path(r'websocket/$', consumers.EventConsumer),\r\n    re_path(r'websocket/broadcast/$', consumers.BroadcastConsumer),\r\n]\r\n```\r\nFrom https://docs.djangoproject.com/en/4.0/ref/urls/:\r\n\r\nWhen a route ends with $ the whole requested URL, matching against path_info, must match the regular expression pattern (re.fullmatch() is used).\r\n\r\nReplacing with\r\n\r\n```\r\nwebsocket_urlpatterns = [\r\n    re_path(r'websocket/', consumers.EventConsumer),\r\n    re_path(r'websocket/broadcast/', consumers.BroadcastConsumer),\r\n]\r\n```\r\n\r\nsolves the issue\n", "before_files": [{"content": "import redis\nimport logging\n\nfrom django.conf import settings\nfrom django.urls import re_path\n\nfrom channels.auth import AuthMiddlewareStack\nfrom channels.routing import ProtocolTypeRouter, URLRouter\n\nfrom . import consumers\n\n\nlogger = logging.getLogger('awx.main.routing')\n\n\nclass AWXProtocolTypeRouter(ProtocolTypeRouter):\n    def __init__(self, *args, **kwargs):\n        try:\n            r = redis.Redis.from_url(settings.BROKER_URL)\n            for k in r.scan_iter('asgi:*', 500):\n                logger.debug(f\"cleaning up Redis key {k}\")\n                r.delete(k)\n        except redis.exceptions.RedisError as e:\n            logger.warning(\"encountered an error communicating with redis.\")\n            raise e\n        super().__init__(*args, **kwargs)\n\n\nwebsocket_urlpatterns = [\n    re_path(r'websocket/', consumers.EventConsumer.as_asgi()),\n    re_path(r'websocket/broadcast/', consumers.BroadcastConsumer.as_asgi()),\n]\n\napplication = AWXProtocolTypeRouter(\n    {\n        'websocket': AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),\n    }\n)\n", "path": "awx/main/routing.py"}], "after_files": [{"content": "import redis\nimport logging\n\nfrom django.conf import settings\nfrom django.urls import re_path\n\nfrom channels.auth import AuthMiddlewareStack\nfrom channels.routing import ProtocolTypeRouter, URLRouter\n\nfrom . import consumers\n\n\nlogger = logging.getLogger('awx.main.routing')\n\n\nclass AWXProtocolTypeRouter(ProtocolTypeRouter):\n    def __init__(self, *args, **kwargs):\n        try:\n            r = redis.Redis.from_url(settings.BROKER_URL)\n            for k in r.scan_iter('asgi:*', 500):\n                logger.debug(f\"cleaning up Redis key {k}\")\n                r.delete(k)\n        except redis.exceptions.RedisError as e:\n            logger.warning(\"encountered an error communicating with redis.\")\n            raise e\n        super().__init__(*args, **kwargs)\n\n\nwebsocket_urlpatterns = [\n    re_path(r'websocket/$', consumers.EventConsumer.as_asgi()),\n    re_path(r'websocket/broadcast/$', consumers.BroadcastConsumer.as_asgi()),\n]\n\napplication = AWXProtocolTypeRouter(\n    {\n        'websocket': AuthMiddlewareStack(URLRouter(websocket_urlpatterns)),\n    }\n)\n", "path": "awx/main/routing.py"}]}