Socket.io与Apache代理的结合使用

11

我正在尝试使用apache设置代理,以便在我的nodejs应用程序中使用socket.io。但是客户端显示以下错误信息:

WebSocket connection to 'wss://example.com/tools/socket.io/?EIO=3&transport=websocket&sid=eOGwJSC14TTWhHRMAAAR' failed: Error during WebSocket handshake: Unexpected response code: 400

这是我的Apache配置:

     <VirtualHost *:443>
            ServerName example.com
            ServerAlias example.com
            #SSLRequireSSL
            SSLProtocol all -SSLv2  -SSLv3
            SSLCompression off
            SSLHonorCipherOrder on
            SSLEngine on
            SSLCertificateFile /etc/ssl/main.pem
            SSLCertificateKeyFile /etc/ssl/dec_ssl.key
            SSLCertificateChainFile /etc/ssl/sub.class1.server.ca.pem
            SSLCACertificateFile /etc/ssl/main.pem
            SSLProxyEngine On

            ProxyPreserveHost On
            ProxyRequests off
    </VirtualHost>

    <Location /tools/>
            ProxyPass http://localhost:8181/
            ProxyPassReverse http://localhost:8181/
    </Location>

这里是客户端代码:

socket = io.connect("https://example.com",{path:'/tools/socket.io'});
socket.on("connect", function () {
    console.log("socketio Connected to server!");
});

我需要添加什么内容到Apache配置中才能消除这个错误?

编辑:我的Apache版本:服务器版本:Apache/2.4.6(CentOS)


你确定你的socket.io服务器正在监听8181端口吗?你能直接访问它吗? - M.Babcock
你有检查过你的Apache错误日志吗? - jcaron
@M.Babcock,是的,服务器正在运行8181端口。我可以从以下网址获取socket.io.js:https://example.com/tools/socket.io/socket.io.js - hs2d
在不使用Apache的情况下,我使用nginx + nodejs时得到了精确的错误消息。 - Scott Stensland
2个回答

5

我已经成功地在Apache 2.4.16上使用了这个,旧版本可能无法正常工作。

<VirtualHost *:443>
        ServerName example.com
        ServerAlias example.com
        #SSLRequireSSL
        SSLProtocol all -SSLv2  -SSLv3
        SSLCompression off
        SSLHonorCipherOrder on
        SSLEngine on
        SSLCertificateFile /etc/ssl/main.pem
        SSLCertificateKeyFile /etc/ssl/dec_ssl.key
        SSLCertificateChainFile /etc/ssl/sub.class1.server.ca.pem
        SSLCACertificateFile /etc/ssl/main.pem
        SSLProxyEngine On

        ProxyPreserveHost On
        ProxyRequests off
</VirtualHost>

<Location /tools/>
        RewriteEngine On
        RewriteCond %{REQUEST_URI}  ^/tools/socket.io            [NC]
        RewriteCond %{QUERY_STRING} transport=websocket    [NC]
        RewriteRule "^/tools/socket.io"           "ws://localhost:8181/socket.io/" [P,L]

        ProxyPass http://localhost:8181/
        ProxyPassReverse http://localhost:8181/
</Location>

ProxyPass无法处理websocket升级。因此,你需要将这些请求重定向到ws://。

我认为通常情况下不应该使用Location来处理这个问题,但是这个配置对你应该起作用。


你能指出我应该把这些行放在我的Apache配置文件中的哪里吗?如果我使用/tools/而不是你的/会怎样? - hs2d
根据您的配置进行了更新。请阅读Apache文档中关于Location的部分,这可能不是您配置的最佳方式,但是在没有更多信息的情况下,我无法确定。 - Gary
1
这对我没有任何改变。仍然出现与原帖相同的错误。 - hs2d
你正在运行哪个版本的Apache? - Gary
我还将/tools添加到条件中,请查看最新更新。您可能需要打开重写日志记录,以便查看您所看到的具体错误。 - Gary
显示剩余2条评论

3
我已根据 @Gary 的建议添加了以下内容:
    <Location /tools/>

    RewriteEngine On
    RewriteCond %{REQUEST_URI}  ^/tools/socket.io            [NC]
    RewriteCond %{QUERY_STRING} transport=websocket    [NC]
    RewriteRule "/(.*)"        "ws://localhost:8181/socket.io/" [P,L]

    ProxyPass http://localhost:8181/
    ProxyPassReverse http://localhost:8181/
   </Location>

在客户端使用路径属性连接套接字。
 discussionSocket = io("https://localhost.in", {
  path:'/tools/socket.io',
  secure: true,
  reconnection: true,
  reconnectionDelay: 1000,
  reconnectionDelayMax: 5000,
  reconnectionAttempts: 99999
});

但是为了实现这一点,我们需要从套接字服务器创建代码中删除SSL配置:-
var http = require('http').Server(app);

我更新了我的答案,并且还修复了 WebSocket 的 400 错误。 - Prashant Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接