Deployment of Django Channels App in Google Cloud Platform - django

I am working on my first django channels app and I want to deploy my django channel app in Google Cloud Platform,its working fine in local server,but when I deployed it on Google Cloud Platform,it gives me errors:
WebSocket connection to 'wss://sockets-263709.appspot.com/ws/chat/user2/' failed: Error during WebSocket handshake: Unexpected response code: 400
I have researched but can't figure out how to setup it,here's my below code:
Entry point:
from Frames.wsgi import application
app = application
wsgi.py:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Frames.settings')
application = get_wsgi_application()
Asgi.py
import os
import django
from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Frames.settings')
django.setup()
application = get_default_application()
settings.py:
WSGI_APPLICATION = 'Frames.wsgi.application'
ASGI_APPLICATION = "Frames.routing.application"
CHANNEL_LAYERS={
"default":{
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("sockets-263709.appspot.com", 6379)],
},
},
}
client side:
var wsStart='ws://';
// check if it is secured then assign wss://
if (loc.protocol==='https:'){
wsStart="wss://"
}
var chatSocket = new WebSocket(wsStart +window.location.host +
'/ws/chat/' + roomName + '/');
Requirements.txt
absl-py==0.8.1
aioredis==1.3.1
asgiref==3.2.3
astor==0.8.1
async-timeout==3.0.1
attrs==19.3.0
autobahn==19.11.1
Automat==0.8.0
certifi==2019.11.28
cffi==1.13.2
channels==2.3.1
channels-redis==2.4.1
chardet==3.0.4
constantly==15.1.0
daphne==2.4.0
Django==3.0.1
djangochannelsrestframework==0.0.3
djangorestframework==3.11.0
gast==0.3.2
google-pasta==0.1.8
grpcio==1.25.0
h5py==2.10.0
hiredis==1.0.1
hyperlink==19.0.0
idna==2.8
incremental==17.5.0
Markdown==3.1.1
msgpack==0.6.2
mysqlclient==1.4.6
protobuf==3.11.1
pyasn1==0.4.8
pyasn1-modules==0.2.7
pycparser==2.19
PyHamcrest==1.9.0
PyMySQL==0.9.3
pyOpenSSL==19.1.0
pytz==2019.3
PyYAML==5.2
requests==2.22.0
scipy==1.3.3
service-identity==18.1.0
six==1.13.0
sqlparse==0.3.0
termcolor==1.1.0
tqdm==4.40.2
Twisted==19.10.0
txaio==18.8.1
urllib3==1.25.7
I have a start point from WSGI.py,I have researched and came know about daphne but don't know,can anybody point me how to deploy it properly.The connection is successfully open in locally.
Is the host is correctly mention in config(CHANNEL_LAYERS) in settings.py

Related

Is there a way to enable secure websockets on Django?

I can't use secure websockets on Django with the sll enabled. I use the sslserver package for Django to allow HTTPS on the development server. My goal is to make a secure chat.
Here is the configuration :
INSTALLED_APPS = [
'channels',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'sslserver',
'accounts',
'chat',
]
#WSGI_APPLICATION = 'sendapp.wsgi.application'
ASGI_APPLICATION = 'sendapp.asgi.application'
# LEARN CHANNELS
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer"
},
}
Concerning the asgi file :
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sendapp.settings')
application = ProtocolTypeRouter({
'https': get_asgi_application(),
'websocket': AuthMiddlewareStack(URLRouter(ws_urlpatterns))
})
I start the Django server this way :
python .\manage.py runsslserver --certificate .\sendapp\certif.crt --key .\sendapp\code.key 0.0.0.0:8000
I understand that to use secure websockets, you have to use a Daphne server. So I tried to run it in its basic configuration in the root of manage.py :
daphne sendapp.asgi:application
but i have this error code in the shell :
django.core.exceptions.ImproperlyConfigured: Requested setting INSTALLED_APPS, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
Does anyone have a solution to this error message ?
I found the solution to the previous problem. It seems to come from the asgi file. More precisely from :
from django.core.asgi import get_asgi_application
django_asgi_app = get_asgi_application()
I don't know why but you have to put these two lines at the beginning of the file, they have to be the first lines of code, like this :
import os, django
from django.core.asgi import get_asgi_application
django_asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from chat.routing import ws_urlpatterns
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sendapp.settings')
django.setup()
application = ProtocolTypeRouter({
'https': django_asgi_app,
'websocket': AuthMiddlewareStack(URLRouter(ws_urlpatterns))
})
Then afterwards, in a terminal :
export DJANGO_SETTINGS_MODULE =sendapp.settings
If you use powershell :
$env:DJANGO_SETTINGS_MODULE = 'sendapp.settings'
This should work now.

Web Sockets failing connection / Django Channels

The problem is, it Used to work.. And then i decided to change my frontend css framework, and then it stopped working. even though the code is the exact same.
my asgi.py file
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import apps.conversation.routing as conversation_routing
import apps.twikkerprofile.routing as core_routing
import apps.feed.routing as feed_routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'twikker.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
conversation_routing.websocket_urlpatterns +
core_routing.websocket_urlpatterns +
feed_routing.websocket_urlpatterns
)
)
})
My routing.py files all follow this pattern:
from django.urls import path
from apps.feed import consumers
websocket_urlpatterns = [
path('ws/tweek/', consumers.TweekConsumer.as_asgi()),
path('ws/like/', consumers.LikeConsumer.as_asgi()),
]
The websockets declaration in the frontend:
const tweekSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/'
+ 'tweek/'
);
const likeSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/'
+ 'like/'
);
And the errors I get in the console:
Edit:
When I start the server, this is what I get
System check identified no issues (0 silenced).
October 24, 2022 - 11:37:50
Django version 4.1.2, using settings 'twikker.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
But I guess it should be Starting ASGI/Channels, doesnt it?
Ok so I followed a youtube tutorial, where I only did "pip install channels", and added "channels" to INSTALLED_APPS in settings.py,
But after reading the channels docs, I saw i should actualy "pip install -U channels["daphne"]" and add "daphne" to INSTALLED_APPS,
then it worked

Django daphne asgi: Django can only handle ASGI/HTTP connections, not websocket

This is really frustrating, I did set everything up according to the documentation, but daphne keeps throwing an error when I try to run it independently, it does work correctly when I use python manage.py run server. this is very frustrating and I can't seem to find similar error anywhere else
2020-01-25 09:57:17,627 INFO Starting server at tcp:port=8000:interface=127.0.0.1
2020-01-25 09:57:17,628 INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2020-01-25 09:57:17,628 INFO Configuring endpoint tcp:port=8000:interface=127.0.0.1
2020-01-25 09:57:17,629 INFO Listening on TCP address 127.0.0.1:8000
127.0.0.1:44516 - - [25/Jan/2020:09:57:27] "WSCONNECTING /ws/score/" - -
2020-01-25 09:57:28,637 ERROR Exception inside application: Django can only handle ASGI/HTTP connections, not websocket.
File "/home/sofdeath/.local/lib/python3.7/site-packages/daphne/cli.py", line 30, in asgi
await self.app(scope, receive, send)
File "/home/sofdeath/.local/lib/python3.7/site-packages/django/core/handlers/asgi.py", line 146, in __call__
% scope['type']
Django can only handle ASGI/HTTP connections, not websocket.
127.0.0.1:44516 - - [25/Jan/2020:09:57:28] "WSDISCONNECT /ws/score/" - -
^C2020-01-25 09:57:39,126 INFO Killed 0 pending application instances
here is my asgi.py
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tabulator.settings')
application = get_asgi_application()
my routing.py:
from django.urls import re_path
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator
import judge.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
judge.routing.websocket_urlpatterns
)
)
),
})
and in my settings.py:
INSTALLED_APPS = [
...
'channels',
]
...
WSGI_APPLICATION = 'tabulator.wsgi.application'
ASGI_APPLICATION = "tabulator.routing.application"
...
CHANNEL_LAYERS = {
"default": {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
change your asgi.py to this:
import os
import django
from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tabulator.settings')
django.setup()
application = get_default_application()
You need to change your asgi.py according to this
# mysite/asgi.py
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import chat.routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
chat.routing.websocket_urlpatterns
)
),
})
change your asgi.py as #ahmad says and edit your settings.py to this:
CHANNEL_LAYERS = {
"default": {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [("redis", 6379)],
},
},
}
and be sure that DEBUG = False. That is because you are not running your project on local server it it will throw an error if you use "127.0.0.1" or "localhost".

Django now working channels with ASGI + WSGI in Heroku

I am trying to setup a Django + Heroku app with Channels (V.2).
I tried to follow all the tutorial but most of them are not updated.
App must use WSGI for HTTP request and ASGI for websockets requests.
So far I found that it is almost working, the last missing piece is for the websockets endpoints to be visible for web app.
At this point whenever I try to create a new websocket:
Error during WebSocket handshake: Unexpected response code: 404
Here is the Settings:
ASGI_APPLICATION = 'app_xxx.routing.application'
ASGI_THREADS = 5
WSGI_APPLICATION = 'app_xxx.wsgi.application'
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
'hosts': [os.environ.get('REDIS_URL')],
},
},
}
Here is the Procfile:
web: gunicorn app_xxx.wsgi --log-file -
web2: daphne app_xxx.asgi:channel_layer --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channel_layer -v2
Here is the asgi:
import os
from channels.layers import get_channel_layer
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app_xxx.settings")
channel_layer = get_channel_layer()
Here is the routing:
from channels.routing import ProtocolTypeRouter, URLRouter, ChannelNameRouter
from django.urls import path
from apps.booking.consumers import BookingConsumer
application = ProtocolTypeRouter({
"websocket": URLRouter([
path('ws/booking_review/<room_name>', BookingConsumer),
]),
})
You're supposed to run the ASGI application, not channel layer. Your ASGI_APPLICATION setting should point to routing.py or you can move its contents to asgi.py and point to it. With your current configuration, your Procfile should look like this:
web: gunicorn app_xxx.wsgi --log-file -
web2: daphne app_xxx.routing:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channel_layer -v2
Check the docs deployment page for more details

Django ASGI New Relic getting a CORS Error Heroku

I am running a Django Application using Django channels and a daphne server (ASGI) instead of the typical gunicorn (WSGI) server. So I had to modify my application to this:
# asgi.py
import os
import django
from channels.routing import get_default_application
from asgiref.wsgi import WsgiToAsgi
from django.core.wsgi import get_wsgi_application
from newrelic import agent
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "server.settings")
django.setup()
application = agent.WSGIApplicationWrapper(get_wsgi_application())
application = WsgiToAsgi(application)
To my surprise this actually works. When I access my django api from a browser or postman it works properly and the data shows up in New Relic. However, I also have a client-side Angular web app which makes REST API calls to the django server and I am getting CORS errors.
Please note that this is not a regular CORS issue as when I remove the new relic wrapper I am able to access my API properly from Angular.
Failed to load https://my-app.herokuapp.com/api/: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin https://frontend.com is therefore not allowed access.
Change your asgi.py file something like this
from django.core.asgi import get_asgi_application
import newrelic.agent #import newrelic agent
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "server.settings")
django_asgi_app = get_asgi_application()
from django.conf import settings
newrelic_config_file = settings.BASE_DIR + "/newrelic.ini" #location of your newrelic.ini file
newrelic.agent.initialize(newrelic_config_file) #initialise agent
application = newrelic.agent.ASGIApplicationWrapper(django_asgi_app)