I’m trying to establish a connection with my Django backend and Flutter code using WebSockets
, but unfortunately I’m unable to do so, went through many articles and videos and everyone is basically doing the same without receiving an error.. Please give a little push to, I’m kinda new into this.
First of all I created a new django app called ‘chat_app’ (added it into settings.py), where I created a new model of my Messages
:
class Message(models.Model):
room = models.ForeignKey(Room, on_delete=models.CASCADE)
sender = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.content
Then I made my consumers.py
(here I’m a little bit confused, isn’t it better to refer to my room unique_id
instead of name, since the ID is unique and not the name in my case? Decided to stick with the tutorial.)
class ChatConsumer(WebsocketConsumer):
def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
self.accept()
def disconnect(self, close_code):
# Leave room group
self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
Done the routing.py
# The WebSocket URL pattern for chat rooms is defined by this code
websocket_urlpatterns = [
re_path(r'ws/chat_app/(?P<room_name>w+)/$', ChatConsumer.as_asgi()),
]
Then added it into my project URLs:
urlpatterns = [
path('admin/', admin.site.urls),
...,
path('ws/', include(websocket_urlpatterns)),
]
And this is how I’m trying to establish a connection in Flutter, basically it is a new page, where I’m passing room data through the Navigator
from the previous page:
class ChatScreen extends StatefulWidget {
const ChatScreen({
Key? key,
required this.room,
}) : super(key: key);
final RoomModelResponse room;
@override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final TextEditingController _controller = TextEditingController();
final List<String> _messages = [];
late WebSocketChannel _channel;
@override
void initState() {
super.initState();
_channel = IOWebSocketChannel.connect(
'wss://192.168.0.11:8000/ws/chat_app/${widget.room.roomName}/'); // Update the WebSocket URL with your Django server address and room name
_channel.stream.listen((message) {
setState(() {
_messages.add(message);
});
});
}
Outputs:
In the flutter terminal I get the following message:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: WebSocketChannelException: WebSocketChannelException: WebSocketException: Connection to 'http://192.168.0.11:8000/ws/chat_app/3wVCio/#' was not upgraded to websocket
#0 new IOWebSocketChannel._withoutSocket.<anonymous closure> (package:web_socket_channel/io.dart:119:24)
#1 Stream.handleError.<anonymous closure> (dart:async/stream.dart:931:16)
#2 _HandleErrorStream._handleError (dart:async/stream_pipe.dart:269:17)
#3 _ForwardingStreamSubscription._handleError (dart:async/stream_pipe.dart:157:13)
#4 _RootZone.runBinaryGuarded (dart:async/zone.dart:1606:10)
#5 _BufferingStreamSubscription._sendError.sendError (dart:async/stream_impl.dart:358:15)
#6 _BufferingStreamSubscription._sendError (dart:async/stream_impl.dart:376:7)
#7 _BufferingStreamSubscription._addError (dart:async/stream_impl.dart:280:7)
#8 _SyncStreamControllerDispatch._sendError (dart:async/stream_controller.dart:788:19)
#9 <…>
Django:
Not Found: /ws/chat_app/3wVCio/
[15/Feb/2024 16:46:19] "GET /ws/chat_app/3wVCio/ HTTP/1.1" 404 4379
Where the "3wVCio" is the unique_id
of my room.
I will provide additional information if need
Update:
The latest think I’ve tried is allowing all origin CORS
in my project:
INSTALLED_APPS = [
# other installed apps
'corsheaders',
]
CORS_ALLOW_ALL_ORIGINS = True
Unfortunately, no success..
Made my ALLOWED_HOST
in Django settings to be equal to ['*']
and configured my asgi.py
file as follows:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(), # Django HTTP ASGI application
"websocket": OriginValidator(
AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
),
['*']
)
), # Django Channels WebSocket ASGI application
})
I tried to handshake with the WebSocket using postman, here is the output:
Error: Unexpected server response: 404
Handshake Details
Request URL: http://192.168.0.11:8000/ws/chat_app/3wVCio/
Request Method: GET
Status Code: 404 Not Found
Request Headers
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: GW/3ZvtVDOXDlKNkIwg2zw==
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Host: 192.168.0.11:8000
Response Headers
Date: Fri, 16 Feb 2024 15:28:45 GMT
Server: WSGIServer/0.2 CPython/3.12.1
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY
Content-Length: 4379
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin
2
Answers
What helped me:
brew
-brew install redis
redis-server
I'm not redis expert, please refer to official redis websitedaphne
pip install daphne
and added it into myINSTALLED_APPS
in settings.py:ASGI_APPLICATION
insettings.py
and configured myasgi.py
. Insettings.py
:asgi.py
:CHANNEL_LAYERS
like so insettings.py
:And with that, I have finally managed to connect "HANDSHAKE" and "CONNECT" with the WebSocket. I'm sorry, that I cannot give explanation why all of these worked. I just wanted to show, what worked for me.
in your
ChatScreen
file there is URL which is quite unusual because there suppose to be only one protocol eitherwss
orhttp
but you are using both so that might be the issue.if you want to use web socket then protocol suppose to be only
wss or ws
.