【问题标题】:Socket.IO with Express/Apache2/SSL带有 Express/Apache2/SSL 的 Socket.IO
【发布时间】:2019-06-04 18:51:09
【问题描述】:

好的,我已经搜索了我在 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);
    });
  });
};

处理 Socket.io 接口的 React Chat 组件:

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);
    });
  }

以及位于 API 前面的 Apache2 配置(在子域上):

# 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 建立连接,失败如下:

关于网络请求的详细信息:

我几乎尝试了所有我能想到的方法,包括对 Apache 配置的大量更改。我觉得在此过程中的某个地方,Apache 没有正确地将请求代理到 Express,但我不确定。

如果有人在这里看到任何看起来有问题的地方,我将非常感谢您的帮助!也很高兴提供任何其他可能需要的信息来追踪这一点!

TIA!

【问题讨论】:

    标签: reactjs apache express socket.io


    【解决方案1】:

    事实证明,这个问题的答案非常简单。

    Apache 配置中的这一行:RewriteRule /(.*) wss://localhost:4002/$1 [P,L],需要使用不同的协议。因为与 API 的内部连接不是通过 SSL,所以将其更改为 ws:// 最终解决了问题。

    如果其他人偶然发现此问题,希望对您有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-29
      • 2017-04-23
      • 2016-10-20
      • 2016-06-06
      • 2018-05-06
      • 2017-07-27
      • 2017-07-23
      • 1970-01-01
      相关资源
      最近更新 更多