skip to Main Content

I am trying to use web sockets to connect to Django Server/Channels. The HTTP views are working but the "ws" ( WebSocket ) connection is being rejected but ONLY on The REACT NATIVE APP. It’s working perfectly on React Web App

App.js For React Native Mobile App

  var ws = React.useRef(
new WebSocket('ws://192.168.10.14:8000/ws/chat/Hello/'),
).current;
ws.onopen = () => {
    setServerState('Connected to the server');
  };
  ws.onclose = e => {
    setServerState('Disconnected. Check internet or server.');
  };
  ws.onerror = e => {
    console.error(e);
    setServerState(e.message);
  };
  ws.onmessage = e => {
    serverMessagesList.push(e.data);
    setServerMessages([...serverMessagesList]);
  };
  const submitMessage = () => {
    ws.send(messageText);
    setMessageText('');
    setInputFieldEmpty(true);
  };

And I get this error
ERROR {"isTrusted": false, "message": "Expected HTTP 101 response but was ‘403 Access denied’"}

But on Web

App.js For React Web App

  let W3CWebSocket = require("websocket").w3cwebsocket;
  var client = new W3CWebSocket("ws://192.168.10.14:8000/ws/chat/Hello/");
  client.onerror = function (e) {
    console.log("Connection Error: " + JSON.stringify(e));
    console.log("Connection Error");
  };

  client.onopen = function () {
    console.log("WebSocket Client Connected");
    let data = JSON.stringify({ message: "Hello Socket!" }); 
    client.send(data);
  };

  client.onclose = function () {
    console.log("echo-protocol Client Closed");
  };

  client.onmessage = function (e) {
    if (typeof e.data === "string") {
      console.log("Received: '" + e.data + "'");
    }
  };

This Code is Working Perfectly

Now For the BackEnd
url.py

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>w+)/$', consumer.ChatConsumer.as_asgi()),
]

Consumer.py

from asgiref.sync import async_to_sync
import json
# WebsocketConsumer is a class that we can inherit from to create a consumer
# A consumer is a class that handles WebSocket connections
# so that we can send and receive messages over the WebSocket
from channels.generic.websocket import WebsocketConsumer


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
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        print(close_code)
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message
            }
        )

    # Receive message from room group
    def chat_message(self, event):
        message = event['message']

        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'message': message
        }))

Settings.py

ASGI_APPLICATION = "xyz.asgi.application"


CHANNEL_LAYERS = {
    'default': {
        'BACKEND': "channels.layers.InMemoryChannelLayer",
        'hosts': [('localhost')],
    }
}

asgi.py

"""
ASGI config for XYZ project.

"""

import Appointments
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'XYZ.settings')

django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
    "http": django_asgi_app,
    
    "websocket": AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(
                Appointments.urls.websocket_urlpatterns
            )
        )
    ),
})

NOTE: The Same backEnd is working perfectly for React.js but giving the above-mentioned error for react native

2

Answers


  1. Chosen as BEST ANSWER

    1- React Native now has built-in support for WebSockets so no need to download any external library.

    2-Removing the useRef will make It work

    FROM

     var ws = React.useRef(new WebSocket('ws://192.168.10.14:8000/ws/chat/Hello/'),
    

    TO

     var ws = new WebSocket('ws://192.168.10.14:8000/ws/chat/Hello/'),
    

  2. It is a strange error that I have encountered once before

    what worked for me was creating a different channels route for the mobile app

    websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>w+)/$', consumer.ChatConsumer.as_asgi()),
    re_path(r'ws/mobile-chat/(?P<room_name>[^/]+)/$', 
    consumer.ChatConsumer.as_asgi())
    ]
    

    I don’t know why or how it worked as there is obviously no reason for the error nor the solution, but I hope that it works for you too!

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search