简体   繁体   English

"main.js:95 WebSocket 连接到 'wss:\/\/website' 失败:("

[英]main.js:95 WebSocket connection to 'wss://website' failed :(

I have tried to make a simple video calling app using Django and WebRTC.我尝试使用 Django 和 WebRTC 制作一个简单的视频通话应用程序。 I tried running this on localhost and it works well, but I tried hosting it on a website hosting platform and now it doesn't work.我尝试在 localhost 上运行它,它运行良好,但我尝试将它托管在网站托管平台上,现在它不起作用。 I surfed through many websites to correct this, but failed.我浏览了许多网站来纠正这个问题,但都失败了。 I haven't used Redis server.我没有使用过 Redis 服务器。

Here are some required files:以下是一些必需的文件:

asgi.py asgi.py

import os

from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
import chat.routing

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

application = ProtocolTypeRouter({
    "https": get_asgi_application(),
    # Just HTTP for now. (We can add other protocols later.)
    "websocket": AuthMiddlewareStack(
        URLRouter(
            chat.routing.websocket_urlpatterns
        )
    )
})

settings.py设置.py


import os
import django_heroku

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '****'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['https://myProject.herokuapp.com/']


# Application definition

INSTALLED_APPS = [
    'channels',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'chat',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'myProject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'myProject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = '/home/myProject/static/'


ASGI_APPLICATION = 'myProject.asgi.application'

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [('https://myProject.herokuapp.com/'),
         ('redis://<my_secret_password_given_by_redislabs>@<my_redislabs_endpoint>')],
        },
    },
}
django_heroku.settings(locals())

This is my main.js file that consists code for VideoCalling functionality.这是我的main.js文件,其中包含 VideoCalling 功能的代码。

console.log('in main.js')

var ICE_config = {
  'iceServers': [
    {
      'url': 'stun:stun.l.google.com:19302'
    },
    {
      'url': 'turn:192.158.29.39:3478?transport=udp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    },
    {
      'url': 'turn:192.158.29.39:3478?transport=tcp',
      'credential': 'JZEOEt2V3Qb0y27GRntt2u2PAYA=',
      'username': '28224511:1379330808'
    }
  ]
}

var mapPeers = {};
var usernameInput = document.querySelector('#username');
var btnJoin = document.querySelector('#btn-join');

var username;
var webSocket;

function webSocketOnMessage(event)
{
    var parsedData = JSON.parse(event.data);
    var peerUsername = parsedData['peer'];
    var action = parsedData['action'];

    if(username == peerUsername)
    {
        return;
    }
    var receiver_channel_name = parsedData['message']['receiver_channel_name'];

    if(action == 'new-peer'){
        createOfferer(peerUsername, receiver_channel_name);
        return;
    }

    if(action == 'new-offer'){
        var offer = parsedData['message']['sdp'];

        createAnswerer(offer, peerUsername, receiver_channel_name);
        return;
    }

    if(action == 'new-answer'){
        var answer = parsedData['message']['sdp'];

        var peer = mapPeers[peerUsername][0];

        peer.setRemoteDescription(answer);

        return;
    }

}

btnJoin.addEventListener('click', () =>{
    username= usernameInput.value;

    console.log(username);

    if(username =='')
    {
        return;
    }
    usernameInput.value='';
    usernameInput.disabled=true;
    usernameInput.style.visibility = 'hidden';

    btnJoin.disabled=true;
    btnJoin.style.visibility = 'hidden';

    var labelUsername = document.querySelector('#label-username');
    labelUsername.innerHTML = username;

    var loc = window.location;
    var wsStart = 'ws://';

    if(loc.protocol == 'https:')
    {
        wsStart = 'wss://';
    }

    var endpoint = wsStart + loc.host + loc.pathname;

    console.log(endpoint);

line 95 --> webSocket = new WebSocket(endpoint);

    webSocket.addEventListener('open', (e) =>{
        console.log('Connection opened');

       sendSignal('new-peer',{});
    webSocket.addEventListener('message', webSocketOnMessage);
    webSocket.addEventListener('close', (e) =>{
        console.log('Connection closed');
    });
    webSocket.addEventListener('error', (e) =>{
        console.log('Error occurred');
    });
});
});


var localStream = new MediaStream();

const constraints = {
    'video':true,
    'audio':true
}

const localVideo =  document.querySelector('#local-video');
const btnToggleAudio =  document.querySelector('#btn-toggle-audio');
const btnToggleVideo=  document.querySelector('#btn-toggle-video');

var userMedia = navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
        localStream = stream;
        localVideo.srcObject = localStream;
        localVideo.muted = true;

        var audioTracks = stream.getAudioTracks();
        var videoTracks = stream.getVideoTracks();

        audioTracks[0].enabled = true;
        videoTracks[0].enabled = true;

        btnToggleAudio.addEventListener('click', () =>{
            audioTracks[0].enabled = !audioTracks[0].enabled;

            if(audioTracks[0].enabled){
                btnToggleAudio.innerHTML = '<i class="fas fa-microphone" style="font-size:20px;"></i>';
                return;
            }
            btnToggleAudio.innerHTML = '<i class="fas fa-microphone-slash" style="font-size:20px;"></i>';
        });
        btnToggleVideo.addEventListener('click', () =>{
            videoTracks[0].enabled = !videoTracks[0].enabled;

            if(videoTracks[0].enabled){
                btnToggleVideo.innerHTML = '<i class="fas fa-video" style="font-size:20px;"></i>';
                return;
            }
            btnToggleVideo.innerHTML = '<i class="fas fa-video-slash" style="font-size:20px;"></i>';
        });

    })
    .catch(error =>{
        console.log('Error accessing media devices!', error);
    });
    var btnSendMsg = document.querySelector('#btn-send-msg');
    var messageList = document.querySelector('#message-list');
    var messageInput = document.querySelector('#msg');
    btnSendMsg.addEventListener('click', sendMsgOnClick);

function sendMsgOnClick(){
    var message = messageInput.value;
    var li = document.createElement('li');
    li.appendChild(document.createTextNode('Me: '+ message));
    messageList.append(li);

    var dataChannels = getDataChannels();

    message = username + ': ' + message;

    for(index in dataChannels){
        dataChannels[index].send(message);
    }
    messageInput.value = '';
}

function sendSignal(action, message)
{

     var jsonStr = JSON.stringify({
           'peer': username,
           'action': action,
           'message': message,
         });
     webSocket.send(jsonStr);
}

function createOfferer(peerUsername, receiver_channel_name)
{
    
    var peer = new RTCPeerConnection(ICE_config);
    addLocalTracks(peer);

    var dc = peer.createDataChannel('channel');
    dc.addEventListener('open',() =>{
        console.log('Connection opened!');
    });
    dc.addEventListener('message', dcOnMessage);

    var remoteVideo = createVideo(peerUsername);
    setOnTrack(peer, remoteVideo);

    mapPeers[peerUsername] = [peer,dc];

    peer.addEventListener('iceconnectionstatechange', ()=>{
        var iceConnectionState = peer.iceConnectionState;
        if(iceConnectionState === 'failed'|| iceConnectionState === 'disconnected' || iceConnectionState === 'closed'){
            delete mapPeers[peerUsername];
            if(iceConnectionState != 'closed')
            {
                peer.close();
            }
            removeVideo(remoteVideo);
        }
    });
    peer.addEventListener('icecandidate', (event)=>{
        if(event.candidate){
            console.log('New ice candidate', JSON.stringify(peer.localDescription));
            return;
        }
        sendSignal('new-offer',{
            'sdp' : peer.localDescription,
            'receiver_channel_name': receiver_channel_name

        });

    });
    peer.createOffer()
        .then(o => peer.setLocalDescription(o))
        .then(() =>{
            console.log('Local description set successfully');
        });

}


function addLocalTracks(peer){
    localStream.getTracks().forEach(track => {
        peer.addTrack(track, localStream);
    });
    return;
}


function dcOnMessage(event){
    var message = event.data;

    var li = document.createElement('li');
    li.appendChild(document.createTextNode(message));
    messageList.appendChild(li);
}


function createAnswerer(offer, peerUsername, receiver_channel_name)
{
    var peer = new RTCPeerConnection(ICE_config);
    addLocalTracks(peer);

    var remoteVideo = createVideo(peerUsername);
    setOnTrack(peer, remoteVideo);

    peer.addEventListener('datachannel', e => {
        peer.dc = e.channel;
        peer.dc.addEventListener('open',() => {
            console.log('Connection opened!');
        });
    peer.dc.addEventListener('message', dcOnMessage);
    mapPeers[peerUsername] = [peer,peer.dc];

    });


    peer.addEventListener('iceconnectionstatechange', () => {
        var iceConnectionState = peer.iceConnectionState;
        if(iceConnectionState === 'failed'|| iceConnectionState === 'disconnected' || iceConnectionState === 'closed'){
            delete mapPeers[peerUsername];
            if(iceConnectionState != 'closed')
            {
                peer.close();
            }
            removeVideo(remoteVideo);
        }
    });
    peer.addEventListener('icecandidate', (event) => {
        if(event.candidate){
            console.log('New ice candidate', JSON.stringify(peer.localDescription));
            return;
        }
        sendSignal('new-answer',{
            'sdp' : peer.localDescription,
            'receiver_channel_name': receiver_channel_name

        });

    });
    peer.setRemoteDescription(offer)
        .then(() =>{
            console.log('Remote Description set successfully for %s.', peerUsername);

            return peer.createAnswer();
        })
        .then(a =>{
            console.log('Answer created!');
            peer.setLocalDescription(a);
        });
}


function createVideo(peerUsername){
    var videoContainer = document.querySelector('#video-container');
    var remoteVideo = document.createElement('video');
    remoteVideo.id = peerUsername + '-video';
    remoteVideo.autoplay = true;
    remoteVideo.playsInline = true;

    var videoWrapper = document.createElement('div');
    videoContainer.appendChild(videoWrapper);
    videoWrapper.appendChild(remoteVideo);
    return remoteVideo;
}

function setOnTrack(peer, remoteVideo){
    var remoteStream = new MediaStream()

    remoteVideo.srcObject = remoteStream;
    peer.addEventListener('track', async(event) =>{
        remoteStream.addTrack(event.track, remoteStream);
    });
}

function removeVideo(video){
    var videoWrapper = video.parentNode;
    videoWrapper.parentNode.removeChild(videoWrapper);
}

function getDataChannels(){
    var dataChannels =[];

    for(peerUsername in mapPeers){
        var dataChannel = mapPeers[peerUsername][1];

        dataChannels.push(dataChannel);
    }

    return dataChannels;
}

I'm also attaching main.html for reference:我还附上main.html以供参考:

<!DOCTYPE html>

{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TClone</title>
    <link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css">
</head>
<body>

        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                  <ul class="navbar-nav mr-auto">
                    <li>
                        <div style="float:right;" class="nav-link">
                            <button class="bg-dark" id="btn-toggle-audio"><i class="fas fa-microphone" style="font-size:20px;"></i></button>
                            <button class="bg-dark" id="btn-toggle-video"><i class="fas fa-video" style="font-size:20px;"></i></button>
                            <button class="bg-dark" id="main" onclick="openNav()"><i class="far fa-comments" style="font-size:20px;"></i></button>
                        </div>
                    </li>
                  </ul>

                </div>
        </nav>
<h3 id="label-username">USERNAME</h3>
<div>
    <input id="username"><button id="btn-join" class="bg-dark">Join Room</button>
</div>
<div>
    <div id="video-container">

        <div>
            <video id="local-video" style="float:left;" poster="{% static 'images/profile.png' %}" controls  width="590px" height="480px" autoplay playsinline></video>
        </div>

    </div>
        <div class="sidenav bg-dark" id="mySidebar">
            <h3 style="color:white">CHAT</h3>
             <button class="closebtn bg-dark"">×</button>

            <div id="messages">
                <ul id="message-list" class="navbar-nav mr-auto"></ul>
            </div>
            <div>
                <input id="msg"><button id="btn-send-msg" class="bg-dark">Send Message</button>
            </div>
            <button id="btn-share-screen" class="bg-dark">Share screen</button>
        </div>
</div>

<script src="{% static 'js/main.js' %}"></script>
</body>
</html>

EDIT:编辑:

consumers.py消费者.py

import json
from channels.generic.websocket import AsyncJsonWebsocketConsumer


class ChatConsumer(AsyncJsonWebsocketConsumer):

    async def connect(self):
        self.room_group_name = 'Test-Room'

        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, code):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

        print('Disconnected')

    async def receive(self, text_data):
        receive_dict = json.loads(text_data)
        message = receive_dict['message']
        action = receive_dict['action']

        if (action == 'new-offer') or (action == 'new-answer'):
            receiver_channel_name = receive_dict['message']['receiver_channel_name']
            receive_dict['message']['receiver_channel_name'] = self.channel_name
            await self.channel_layer.send(
                receiver_channel_name,
                {
                    'type': 'send.sdp',
                    'receive_dict': receive_dict
                }
            )
            return

        receive_dict['message']['receiver_channel_name'] = self.channel_name

        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'send.sdp',
                'receive_dict': receive_dict
            }
        )

    async def send_sdp(self, event):
        receive_dict = event['receive_dict']

        await self.send(text_data=json.dumps(receive_dict))

Also adding Procfile .还添加Procfile

web: gunicorn myProject.wsgi:application --log-file - --log-level debug
python manage.py collectstatic --noinput
python manage.py migrate
worker: python manage.py runworker channel_layer
web: python myProject/manage.py runserver 0.0.0.0:$PORT

requirements.txt要求.txt

django

django-channels

gunicorn

django_heroku

And when I run this app, I get this error:当我运行这个应用程序时,我得到了这个错误:

in main.js line 95:WebSocket connection to 'wss://(name of website).com/' failed:在 main.js 第 95 行:WebSocket 连接到“wss://(网站名称).com/”失败:

I tried checking the security of the website hosting service, and it is https.我尝试检查网站托管服务的安全性,它是 https。 Now I am really NOT able to identify where my error is and I really need help in correcting this.现在我真的无法确定我的错误在哪里,我真的需要帮助来纠正这个问题。 Thanks in advance!提前致谢!

The problem lies in your Procfile .问题在于您的Procfile Gunicorn is a WSGI HTTP Server. Gunicorn是一个 WSGI HTTP 服务器。 It doesn't support ASGI.它不支持 ASGI。 This is what you have to do.这是你必须做的。

But first things first, in requirements.txt that's not how you're supposed to add packages.但首先,在requirements.txt ,这不是您添加包的方式。 Create a virtual environment(if you haven't already) with either by pipenv , virtualenv or if you don't want to download additional packages, then you can use venv .通过pipenvvirtualenv创建虚拟环境(如果您还没有),或者如果您不想下载其他软件包,则可以使用venv ( Note: There is no major difference among the three mentioned packages. ). 注意:上面提到的三个包之间没有太大区别。 )。

In your working directory, run this on the root level of your django-channels project: python -m venv venv .在您的工作目录中,在django-channels项目的根级别运行此命令: python -m venv venv Then activate the venv :然后激活venv

venv\\Scripts\\activate - if you are on Windows venv\\Scripts\\activate - 如果您使用的是 Windows

source venv/bin/activate - if you are on Mac or Linux. source venv/bin/activate - 如果您使用的是 Mac 或 Linux。

Then install django , channels , channels_redis with pip .然后使用pip安装djangochannelschannels_redis

Now run: pip freeze > requirements.txt .现在运行: pip freeze > requirements.txt This will add all the required packages correctly.这将正确添加所有必需的包。

Now, in your Procfile delete everything and add these lines:现在,在您的Procfile删除所有内容并添加以下行:

web: daphne <your_project>.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels --settings=<your_project>.settings -v2

Deploy again with these settings.使用这些设置再次部署。

EDIT:编辑:

Change your Procfile to this:将您的Procfile更改为:

release: python manage.py migrate
web: daphne <your_project>.asgi:application --port $PORT --bind 0.0.0.0 -v2
worker: python manage.py runworker channels --settings=<your_project>.settings -v2

And I see that you have changed your Redis configuration to this:我看到您已将 Redis 配置更改为:

"CONFIG": {
            "hosts": [('https://myProject.herokuapp.com/'), // <--- I don't think this line is necessary, so change it back to what it was
         ('redis://<my_secret_password_given_by_redislabs>@<my_redislabs_endpoint>')],
        },

You have to use daphne.你必须使用达芙妮。

https://github.com/django/daphne https://github.com/django/daphne

I will try to show you the minimum configuration.我将尝试向您展示最低配置。

app
├── app
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── db.sqlite3
├── main
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   ├── models.py
│   ├── routing.py
│   ├── consumers.py
│   ├── tests.py
│   ├── urls.py
│   ├── views.py
│   └── templates
│       │
│       └── chat
│            └── room.html
├── manage.py

asgi.py asgi.py

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'app.settings')
import django
django.setup()

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import main.routing

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            main.routing.websocket_urlpatterns
        )
    ),
})

routing.py路由.py

from django.urls import re_path
import main.consumers
websocket_urlpatterns = [
    re_path(r"ws/chat/(?P<root_name>\w+)/$", main.consumers.ChatConsumer.as_asgi()),
]

consumers.py消费者.py

from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
class ChatConsumer(AsyncWebsocketConsumer): 
    async def connect(self):
        self.room_name  = self.scope["url_route"]["kwargs"]["room_name"]
        self.room_group_name = "chat_%s" % self.room_name
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )
        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        print("receive")

settings.py设置.py

ASGI_APPLICATION = 'main.asgi.application'
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

views.py视图.py

def room(request, room_name):
    return render(request, "chat/room.html", {"room_name": room_name})

room.html房间.html

{{ room_name|json_script:"roomName" }}
roomName = JSON.parse(document.getElementById("roomName").textContent);
    chatSocket = new WebSocket(
        "ws://"
        + window.location.host
        + "/ws/chat/"
        + roomName
        + "/"
    );

Run

~/app$ daphne app.asgi:application

Open打开

http://127.0.0.1:8000/room_1/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 wss上的WebSocket连接失败 - WebSocket connection on wss failed twilio.min.js:77 WebSocket 连接到'wss://chunderw-vpc-gll.twilio.com/signal'连接失败: - twilio.min.js:77 WebSocket connection to 'wss://chunderw-vpc-gll.twilio.com/signal' failed: Error in connection establishment: Vitejs:WebSocket 由于 HMR 而无法连接到“wss://host:port/” - Vitejs: WebSocket connection to 'wss://host:port/' failed due to HMR WebSocket 连接到“wss://localhost:8000/game”失败(Symfony,棘轮) - WebSocket connection to 'wss://localhost:8000/game' failed ( Symfony, Ratchet ) WebSocket 连接到“wss://ip:8080/”失败:连接建立错误:net::ERR_CONNECTION_REFUSED - WebSocket connection to 'wss://ip:8080/' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED 与&#39;wss:// localhost:44300 / Home / websocketcon&#39;的WebSocket连接失败:WebSocket握手期间出错:意外响应代码:404 - WebSocket connection to 'wss://localhost:44300/Home/websocketcon' failed: Error during WebSocket handshake: Unexpected response code: 404 RequireJS:多个main.js? - RequireJS: Multiple main.js? Django 通道使用安全的 WebSocket 连接 - WSS:// - Django channels using secured WebSocket connection - WSS:// ./app/main.js 模块构建失败:语法错误:意外令牌 (10:18) - ERROR in ./app/main.js Module build failed: SyntaxError: Unexpected token (10:18) 本机脚本:无法创建应用程序…无法加载模块:…app / main.js - Nativescript: unable to create application… Failed to load module: …app/main.js
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM