Socket.IO с Express / Apache2 / SSL - PullRequest
0 голосов
/ 04 июня 2019

Хорошо, я искал почти каждый вопрос / ответ, который я могу найти об этом в SO и других местах в Интернете, но безрезультатно. Итак, я решил опубликовать это, чтобы увидеть, есть ли у кого направление, чтобы указать мне.

Настройка

У меня есть приложение React и Node / Express API на отдельных поддоменах. Приложение React находится на сайте www.domain.com, а API - на сайте api.domain.com. Приложение React использует конечные точки, предоставляемые приложением Express (api.domain.com/endpoint и т. Д.).

Кроме того, Express API использует Socket.io для некоторых коммуникаций в реальном времени и предоставляется на том же порту, что и сам API.

Все это обслуживает Apache2.

Соответствующие образцы кода

Мой корневой файл Express (index.js):

const app = require('express', '4.16.4')();
const bodyParser = require('body-parser');
const cors = require('cors');
const http = require('http').createServer(app);
const io = require('socket.io')(http);
require('./sockets/chat')(io);

const db = require('./services/db.service');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cors({
  credentials: true,
}));

const projects = require('./routes/projects');
const assets = require('./routes/assets');

app.use('/projects', projects);
app.use('/assets', assets);

// Test API endpoint
app.get('/test', (req, res) => {
  res.send('You got me');
});

db.connect();

http.listen(4002, () => {
  console.log('API is ready on 4002');
});

/sockets/chat, который импортируется в вышеуказанный файл:

const Message = require('../models/message.model');

module.exports = (io) => {
  io.on('connection', (socket) => {
    socket.on('message', async ({ asset, from, body }) => {
      const msg = new Message({
        asset,
        from,
        body,
      });
      const message = await msg.save();
      io.emit('message', message);
    });
  });
};

Компонент React Chat, который обрабатывает интерфейс с Socket.io:

import React, { Component } from 'react';
import ChatMessage from '../ChatMessage';
import { Auth0Lock } from '../Auth';
import socketIOClient from 'socket.io-client';
import MessageService from '../../services/message.service';
import { apiUrl, loginCallback } from '../../config';

require('./styles.scss');

class Chat extends Component {
  constructor(props) {
    super(props);
    this.state = {
      messages: [],
    }
  }

  componentDidMount() {
    MessageService.getAssetMessages(this.props.assetId)
      .then((messages) => {
        this.setState({ messages })
      })
      .catch((e) => console.log(e));

    this.socket = socketIOClient(apiUrl, {transports: ['websocket']}); 
    this.socket.on('message', (message) => {
      this.setState({
        messages: [
          ...this.state.messages,
          message,
        ],
      });
    });
    this.socket.on('connect_error', (err) => {
      console.log('SocketIO connection error:', err);
    });
  }

И конфиг Apache2, который находится перед API (на поддомене):

# Added to mitigate CVE-2017-8295 vulnerability
UseCanonicalName On
<VirtualHost *:80>
        ServerName api.reviewcycle.io

        RewriteCond %{SERVER_NAME} =api.reviewcycle.io
        RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=301]

        ErrorLog ${APACHE_LOG_DIR}/error-reviewcycle-api.log
</VirtualHost>

<VirtualHost *:443>
        ServerName api.reviewcycle.io

        <Proxy *>
                Order allow,deny
                Allow from all
        </Proxy>

        RewriteEngine On
        RewriteCond %{REQUEST_URI}      ^/socket.io/            [NC]
        RewriteCond %{QUERY_STRING}     transport=websocket     [NC]
        RewriteRule /(.*)               wss://localhost:4002/$1 [P,L]

        SSLEngine On
        SSLCertificateFile /etc/cloudflare/reviewcycle.io.pem
        SSLCertificateKeyFile /etc/cloudflare/reviewcycle.io.key

        ProxyPass / http://localhost:4002/
        ProxyPassReverse / http://localhost:4002/
</VirtualHost>

Проблема

Когда приложение загружается и модуль пытается установить соединение с Socket.io, происходит сбой следующим образом:

enter image description here

Что касается детализации запроса сети:

enter image description here

Я перепробовал почти все, что только мог придумать, включая кучу изменений в конфигурации Apache. Я чувствую, что где-то в пути, Apache не передает запрос на Express правильно, но я не уверен.

Если кто-нибудь увидит здесь что-нибудь неладное, я был бы очень благодарен за помощь! Также будем рады предоставить любую другую информацию, которая может понадобиться для отслеживания этой информации!

ТИА!

1 Ответ

0 голосов
/ 05 июня 2019

Оказывается, ответ на этот вопрос был довольно простым.

Эта строка в конфигурации Apache: RewriteRule /(.*) wss://localhost:4002/$1 [P,L], требуется другой протокол. Поскольку внутреннее соединение с API не осуществляется через SSL, изменение этого значения на ws:// привело к исправлению ситуации.

Если кто-то еще наткнется на это, надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...