Ошибка рукопожатия Websocket между Node.js и реагировать

#node.js #reactjs #sockets #websocket

#node.js #reactjs #сокеты #websocket

Вопрос:

Я пишу приложение с использованием сокетов, но, похоже, не могу заставить первоначальное рукопожатие работать. Я использую WebSockets React в своем интерфейсе, работающем на ПОРТУ 8080, и Node.js сокет на серверной части, работающий на ПОРТУ 5000. Подтверждение связи во внешнем интерфейсе выполняется через мой компонент следующим образом:

     componentDidMount(){
        this.socket = new WebSocket('ws://localhost:5000', ['json']);
        this.socket.onerror = err => {
            console.log(err)
        }
        this.socket.onmessage = e => {
            let res = JSON.parse(e.data);
            console.log(e, res);
            let copyArr = [...this.state.message]
            copyArr.push(res);

            this.setState({
                message: copyArr
            });
        }
    }
  

На моем узловом сервере я делаю:

 const server = http.createServer();

server.on('upgrade', (req, socket) => {

    if(req.headers['upgrade'] !== "websocket"){
        socket.end('HTTP/1.1 400 Bad Request');
        return;
    }

    const acceptKey = req.headers['sec-websocket-key'];
    const acceptHash = generateValue(acceptKey);

    console.log('accepkey', acceptKey, 'hash', acceptHash);

    const resHeaders = [ 'HTTP/1.1 101 Web Socket Protocol Handshake', 'Upgrade: WebSocket', 'Connection: Upgrade', `Sec-WebSocket-Accept: ${acceptHash}` ];

    console.log(resHeaders);

    let protocols = req.headers['sec-websocket-protocol'];
    protocols = !protocols ? [] : protocols.split(',').map(name => name.trim());

    if(protocols.includes('json')){
        console.log('json here');
        resHeaders.push(`Sec-WebSocket-Protocol: json`);
    }

    socket.write(resHeaders.join('rn')   'rnrn');
})

function generateValue(key){
    return crypto
      .createHash('sha1')
      .update(key   '258EAFA5-E914–47DA-95CA-C5AB0DC85B11', 'binary')
      .digest('base64');
}
  

Когда мой компонент React монтируется, он пытается установить первоначальное подтверждение связи, но не удается с ошибкой: WebSocket connection to 'ws://localhost:5000/' failed: Error during WebSocket handshake: Incorrect 'Sec-WebSocket-Accept' header value . Я проверил с помощью Chrome developer tool и обнаружил это
введите описание изображения здесь
Находясь на серверной части, при регистрации заголовка ключа принятия запроса и заголовков ответа, я увидел это:
введите описание изображения здесь

Итак, если я не ошибаюсь в этих заголовках, кажется, что заголовок запроса и ответа accept-key каким-то образом изменяется при переходе от клиента к серверу, и наоборот. Как это происходит? Или я неправильно понял, что происходит. Почему именно первоначальное подтверждение связи не работает?

Комментарии:

1. На вашем скриншоте вы смотрите не на свой запрос websocket. Посмотрите на URL, это соединение webpack-dev-server с websocket (localhost: 8080), которое было успешным (код состояния 101)

Ответ №1:

В после - есть тире 258EAFA5-E914–47DA-95CA-C5AB0DC85B11 вместо дефиса E914 , поэтому замените его дефисом -

ссылка https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-WebSocket-Accept

Ответ №2:

Я считаю, что generateValue функция неверна, вы передаете binary кодировку inputData, которая является ключевым словом для latin1 в соответствии с документами. Но я считаю, что это UTF-8 строка, а не latin1 , поэтому хэш результата неверен. Поэтому просто попробуйте использовать update(key '258EAFA5-E914–47DA-95CA-C5AB0DC85B11', 'utf8') или даже без второго utf8 аргумента, поскольку он используется по умолчанию.