Problem when connecting Django and Flutter websockets

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://http://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

in your ChatScreen file there is URL which is quite unusual because there suppose to be only one protocol either wss or http 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.

What helped me:

  1. I have installed redis using brew - brew install redis
  2. I have started redis, before starting my Django project - redis-server I'm not redis expert, please refer to official redis website
  3. I have installed daphne pip install daphne and added it into my INSTALLED_APPS in settings.py:
    # Application definition
    INSTALLED_APPS = [
        'daphne',
        ...,
    ]
  1. I have added ASGI_APPLICATION in settings.py and configured my asgi.py. In settings.py:
    ASGI_APPLICATION = 'project.asgi.application'
  1. In asgi.py:
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
    
    application = ProtocolTypeRouter({
        "http": get_asgi_application(),
        "websocket": AuthMiddlewareStack(
                URLRouter(
                    websocket_urlpatterns
                ),
            )
        })
  1. I have added CHANNEL_LAYERS like so in settings.py:
    # Configure channel layers
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('localhost', 6379)],
        },
    },
    'ROUTING': 'ws.routing.application',
}

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.

WebSocket HANDSHAKING /ws/chat_app/FxmZiA/ [192.168.0.11:60081]

WebSocket CONNECT /ws/chat_app/FxmZiA/ [192.168.0.11:60081]

Back to Top