Django Channels App Websocket Connection Failing - django

I believe I have a similar issue to the one found here
and here.
The gist is that I'm running a Django app with channels on an Amazon-ec2 instance and the websockets are failing to connect.
Most of my code regarding the websockets comes from the django-channels tutorial here.
Traffic is being directed though secured dns name behind an application load balancer.
I'm running this entirely on Daphne (handling both https and websocket traffic) with pretty minimal configurations:
daphne -b <server_url> -p <port> test_app.asgi:application
I'm also authenticating with openID-connect using the mozilla-django-oidc module. However for the websocket test I'm not expecting authentication. I feel it's worth pointing out if the issue is related to websocket authentication in any way.
In development I'm running a local redis cluster as my channel layer. My dev app (all http:// and ws://) has no issues connecting to websockets. The chat app works as expected. I can connect to my websockets and is confirmed with a
127.0.0.1:60779 - - [07/Apr/2021:12:06:05] "WSCONNECTING /ws/chat/lobby/"
Here is the code in asgi.py
import chat.routing
asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
application = ProtocolTypeRouter(
{
"http": asgi_app,
"websocket": AuthMiddlewareStack(
URLRouter(chat.routing.websocket_urlpatterns)
),
}
)
and the code in chat/routing.py
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
In production I'm using an elasticache redis cluster as my channel layer. I can test this in the django shell and it connects/sends/receives.
However in the production chat I am unable to reach the room or see the above WSCONNECTING message. It never upgrades the connection to a websocket.
The next log after that is
2021-04-07 16:15:15,279 WARNING Not Found: /ws/chat/lobby/
Like its trying to resolve that route as http and not as a websocket.
After doing some additional reading I tried to use the host/port that is running on Daphne like
wss://<my host ip>:<port>/ws/chat/lobby
Which did not cause an immediate failure but ultimately never connected.
(index):46 Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
Here's the error in chrome
I feel like it's something to do with that public-facing host name that is being used as the host name in the websocket url. All inbound traffic is allowed. I'm not sure how this relates to the issue at hand.
I'm still trying to learn my way around all this. Any advice would certainly be appreciated.
Thanks!

I was just running thru that same tutorial, and I got the same error. I decided to look at the methods imported here:
from channels.routing import ProtocolTypeRouter, URLRouter
and I couldn't find them. So I uninstalled django-channels and installed channels
python3 -m pip uninstall django-channels && python3 -m pip install channels
and stuff worked.

Related

OperationalError, Error 111 connecting to 127.0.0.1:6379. Connection refused. After deploying in heroku

I am getting the below error after I deployed my website on heroku.
Error 111 connecting to 127.0.0.1:6379. Connection refused.
Request Method: POST
Request URL: https://website.herokuapp.com/account/register
Django Version: 3.2.8
Exception Type: OperationalError
Exception Value:
Error 111 connecting to 127.0.0.1:6379. Connection refused.
Exception Location: /app/.heroku/python/lib/python3.8/site-packages/kombu/connection.py, line 451, in _reraise_as_library_errors
Python Executable: /app/.heroku/python/bin/python
Python Version: 3.8.12
Python Path:
['/app',
'/app/.heroku/python/bin',
'/app',
'/app/.heroku/python/lib/python38.zip',
'/app/.heroku/python/lib/python3.8',
'/app/.heroku/python/lib/python3.8/lib-dynload',
'/app/.heroku/python/lib/python3.8/site-packages']
Server time: Sat, 11 Dec 2021 21:17:12 +0530
So basically my website has to send email regarding otp, after registration and also some contract related emails. These email are neccessary to be sent hence can't be avoided. I posted a question earlier here regardig how to minimize the time that sending emails takes so that the user doesn't have to wait the entire time. I was suggested to use asynchronous code for this. So i decided to use celery for this. I followed the youtube video that taught how to use it.
Now after I pushed the code in the website I am getting this error. I am beginner andd have no idea how to rectify it. Please suggest me what shoul I do. Below are the details and configurations.
settings.py
CELERY_BROKER_URL = 'redis://127.0.0.1:6379'
CELERY_RESULT_BACKEND = 'redis://127.0.0.1:6379'
CELERY_ACCEPT_CONTENT =['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SELERLIZER = 'json'
requirements.txt
amqp==5.0.6
asgiref==3.4.1
billiard==3.6.4.0
celery==5.2.1
click==8.0.3
click-didyoumean==0.3.0
click-plugins==1.1.1
click-repl==0.2.0
colorama==0.4.4
Deprecated==1.2.13
dj-database-url==0.5.0
Django==3.2.8
django-ckeditor==6.1.0
django-filter==21.1
django-js-asset==1.2.2
django-multiselectfield==0.1.12
dnspython==2.1.0
As I mentioned I am beginer, please suggest me a detailed ans as to how I can recctify this error.
Here's the problem:
CELERY_BROKER_URL = 'redis://127.0.0.1:6379'
Redis won't be running on your local dyno. You'll have to run it somewhere else and configure your code to connect to it. A common choice is to run Redis via an addon:
Once you’ve chosen a broker, create your Heroku app and attach the add-on to it. In the examples we’ll use Heroku Redis as the Redis provider but there are plenty of other Redis providers in the Heroku Elements Marketplace.
If you choose to use Heroku Redis, you'll be able to get the connection string to your instance via the REDIS_URL environment variable:
Heroku add-ons provide your application with environment variables which can be passed to your Celery app. For example:
import os
app.conf.update(BROKER_URL=os.environ['REDIS_URL'],
CELERY_RESULT_BACKEND=os.environ['REDIS_URL'])
Your Celery app now knows to use your chosen broker and result store for all of the tasks you define in it.
Other addons will provide similar configuration mechanisms.
All quoted documentation here, and most links, come from Heroku's Using Celery on Heroku article. I suggest you read the entire document for more information.

WebSocket connection to 'ws:/' failed: Error during WebSocket handshake: Unexpected response code: 200

I am using Django-channels to connect to the server, but it always show the error like this:
reconnectwebsockets.js WebSocket connection to 'ws:xxx' failed:
Error during WebSocket handshake: Unexpected response code: 200
Also, I am using docker, this may be a issue of docker container configuration?
Any ideas what could be possibly wrong?
Question details
Hello, did you try to use channels library? It will give you same powerful as Django-channels one. Here you can find necessary documentation for it.
I recommend you use it because it is give you more flexibility then Django-channels one.
Channels library
Quick start
You can read how to work with it at Tutorial.
Errors and solutions
Unexpected response code: 200 (or other code XXX) (solved):
Be sure you include your application and channels via settings (mysite.settings) and use asgi application:
INSTALLED_APPS = [
'channels',
'chat',
...
]
...
ASGI_APPLICATION = "mysite.asgi.application"
Be sure you use channel layers (mysite.settings).
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer',
},
}
According Documentation you should use database for production, but for local environment you may use channels.layers.InMemoryChannelLayer.
Be sure you run asgi server (not wsgi) because you need asynchronous behaviour. Also, for deployment you should use daphne instead of gunicorn. daphne is included in channels library by default, so you don't need to install it manually.
Basic run server will look like (Terminal):
daphne -b 0.0.0.0 -p $PORT mysite.asgi:application
where $PORT is specific port (for UNIX system is 5000). (That format used for heroku application, you can change it manually).
Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR and same errors with using https connection (solved):
Difference between ws and wss?
You may think about to use your server via wss protocol:
replace ws://... with wss://... or use following template in your html (chat/templates/chat/room.html):
(window.location.protocol === 'https:' ? 'wss' : 'ws') + '://'
Hope this answer is useful for channels with Django.

How to run wsgi along the side of the daphne ASGI for django channels

i am using django channels in my project using using official django channels v2, my simple channels app is completed and working fine if run python manage.py runserver
but
i want to run django channels in different port so i am now using daphne
using daphne my_project.asgi:application --port 8001 it working fine in 8001 port
INFO Starting server at tcp:port=8001:interface=127.0.0.1
INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras)
and i also run python manage.py runserver in another terminal parallely working fine. now my both channels in 8001 and django in 8000 port working correctly but my runserver command running ASGI/Channels instead of wsgi development server,
Starting ASGI/Channels version 2.2.0 development server at http://127.0.0.1:8000/
instead of
Starting development server at http://127.0.0.1:8000/
settings.py
ASGI_APPLICATION = 'my_project.routing.application'
WSGI_APPLICATION = 'my_project.wsgi.application'
if i debug any function in views.py request, it is ASGI request instead of django wsgi request
asgi.py
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my_project.settings")
django.setup()
application = get_default_application()
my question is:
how to get django request instead of ASGI request in our normal function view request(like def index(request)) or if we install django channels every request become ASGI request?
what is the use of the python mange.py runworker command
Like you can read here: https://asgi.readthedocs.io/en/latest/
ASGI (Asynchronous Server Gateway Interface) is a spiritual successor
to WSGI, intended to provide a standard interface between
async-capable Python web servers, frameworks, and applications.
Where WSGI provided a standard for synchronous Python apps, ASGI
provides one for both asynchronous and synchronous apps, with a WSGI
backwards-compatibility implementation and multiple servers and
application frameworks.
so answer for your question nr 1 is: Yes, all requests will be ASGI.
Question nr 2 - it's a command to run multiple workers to process your channel requests in asynchronous way https://channels.readthedocs.io/en/1.x/deploying.html#run-worker-servers

Django wsgi server bjoern multithreaded

i would like to use bjoern wsgi server, currently this is working fine but i want to get it multithreaded so that i can access my application localy on multiple ports not only on port 8080 but also und 8081, 8082 etc...
currently i do the following at my run.py file which starts the django app:
import bjoern
from app.wsgi import application
bjoern.run(application, 'localhost', 8080, reuse_port=True)
how can i spawn multiple processes of run.py on diffrent ports?
Or in general how can i use multithreading at this point?
The documentation seems quite complicated to me or at least i dont know where to start, https://docs.python.org/3/library/threading.html.
Thanks in advance

django-websocket-redis development server not working

I'm working on a Django app that's using the django-websocket-redis app to publish events from the server side.
I've successfully configured a test server using nginx and uWSGI to route both HTTP and WS requests correctly to my Django app, but on my local development environment I cannot get this working.
According to the django-websocket-redis documentation, it's enough to start the Django development server and everything should work fine, but it seems like this is far away from reality.
Here is what I've checked:
redis is running on localhost:6379 and is responding to PING requests
tried to run the server on different ports (80, 8080, 8000) to check if the django-websocket-redis makes any assumption about the development server's port, but nothing changed
searched for solution online, but there is nothing about this topic
On my local environment on the client side I see a 404 error when my app tries to connect to the local WebSocket. My settings.py sets the WEBSOCKET_URL to the correct URL (on test server it's working, but locally isn't).
Anyone has an idea what am I doing wrong? Thanks!
I've found a workaround to this.
I've modified my wsgi.py to this and it works now:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
# This application object is used by any WSGI server configured to use this
# file. This includes Django's development server, if the WSGI_APPLICATION
# setting points here.
from django.core.wsgi import get_wsgi_application
from django.conf import settings
from ws4redis.django_runserver import WebsocketRunServer
if settings.DEBUG:
_django_app = get_wsgi_application()
_websocket_app = WebsocketRunServer()
def application(environ, start_response):
if environ.get('PATH_INFO').startswith(settings.WEBSOCKET_URL):
return _websocket_app(environ, start_response)
return _django_app(environ, start_response)
else:
application = get_wsgi_application()
UPDATE: it's not needed to create a custom management command as I mentioned previously, so I've deleted that part of the answer.