【问题标题】:Running NodeJS in a Apache server在 Apache 服务器中运行 NodeJS
【发布时间】:2017-10-21 23:56:59
【问题描述】:

我正在尝试使用 Socket.IO 和 Express 制作一个浏览器多人游戏,尽管我不太清楚为什么需要 Express。我的服务器中有该应用程序,位于名为 /game 的文件夹中,因此要访问该应用程序,用户应键入 http://www.example.com/game 而不是 http://www.example.com:3000,这就是教程的操作方式。我知道这更多是 Apache 2 VirtualHost 配置文件问题,但我不知道在哪里发布。 这是我的实际 .conf 文件

# /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>

ServerAdmin admin@example.com
DocumentRoot /var/www/example.com/public_html
ServerName example.com
ServerAlias www.example.com
ProxyPreserveHost On
ProxyPass /game http://www.example.com:3000
ProxyPassReverse /game http://www.example.com:3000


ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

实际上,当用户通过输入带有端口 (http://www.example.com:3000) 的 url 进入时,服务器会返回一条日志消息,例如“用户已连接”,但是当我通过输入我想要的 url (http://www.example.com/game) 输入时,然后它不返回任何让我发疯的消息... index.js 代码:

var app = require('express')();
 var http = require('http').Server(app);
 var io = require('socket.io')(http);

 app.get('/', function(req, res){
   res.sendFile(__dirname + '/index.html');
 });

 io.on('connection', function(socket){
   console.log('a user connected');
   socket.on('disconnect', function(){
     console.log('user disconnected');
 });
 socket.on('chat message', function(msg){
    onsole.log('message: ' + msg);
 });
 });

 http.listen(3000, function(){
   console.log('listening on *:3000');
 });

index.html 代码:

<!doctype html>
<html>
  <head>
    <title>Socket.IO App</title>
    <style>
     * { 
       margin: 0;
       padding: 0; 
       box-sizing: border-box; 
     }
     body { 
       font: 13px Helvetica, Arial; 
     }
     form { 
       background: #000; 
       padding: 3px; 
       position: fixed;
       bottom: 0; 
       width: 100%; 
     }
     form input { 
       border: 0; 
       padding: 10px; 
       width: 90%; 
       margin-right: .5%; 
     }
     form button { 
       width: 9%; 
       background: rgb(130, 224, 255); 
       border: none; 
       padding: 10px; 
      }
    #messages { 
       list-style-type: none; 
       margin: 0; padding: 0; 
    }
    #messages li { 
       padding: 5px 10px; 
    }
    #messages li:nth-child(odd) { 
       background: #eee; 
    }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>
    </form>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://code.jquery.com/jquery-1.11.1.js"></script>
    <script>
    $(function () {
      var socket = io();
      $('form').submit(function(){
        socket.emit('chat message', $('#m').val());
        $('#m').val('');
        return false;
      });
    });
    </script>
  </body>
</html>

提前致谢。

edit:另外,我在通过 example.com/game 访问时检查了浏览器控制台,它说未找到 socket.io.js 文件,但是当以其他方式输入时正确加载文件...

【问题讨论】:

  • 嗨@MirzaSisic 感谢您的回答!它实际上帮助了我,但我已经看过那篇文章,它并没有解决我的问题。现在我可以运行我的应用程序并通过 example.com:3000 访问它,但我希望能够通过 example.com/game 访问它。实际上,他们都将我返回到正确的页面,但是当通过 example.com/game 进入时,它不会加载 socket.io 脚本(404)并且服务器不会返回任何消息作为“用户已连接”。再次感谢!
  • 找不到socket.io时,它记录的url是什么?并确认这是否是您的套接字文件的正确 url
  • 我之前使用的是 CDN url。现在我已将其更改为 src="socket.io/socket.io.js",现在在请求 example.com/game 时我没有收到有关 js 文件加载的任何错误,但我收到 404“polling-xhr.js”。 js:264 GET example.com/socket.io/… 404(未找到)"

标签: javascript node.js apache socket.io reverse-proxy


【解决方案1】:

在客户端,指定socket.io客户端的path字段:

var socket = io('http://www.example.com', {
  'path': '/game/socket.io'
});

或:

var socket = io(window.location.origin, {
  'path': window.location.pathname + '/socket.io'
});

在您的 apache 配置中,还添加 ws 重写规则来路由 websocket 流量,您将需要 proxyproxy_httpproxy_wstunnelrewrite 模块:

RewriteEngine On
RewriteCond %{HTTP:Connection} Upgrade [NC]
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteRule /game/(.*) ws://www.example.com:3000/$1 [P,L]

ProxyPass        /game  http://www.example.com:3000
ProxyPassReverse /game  http://www.example.com:3000

您可以找到here 使用 docker 来重现您的配置的示例项目(节点应用程序 + apache 反向代理)

【讨论】:

  • 您好,感谢您的回答!我会试试这个并返回结果
  • 好吧,我尝试了很多不同的方法,但都没有奏效。实际上,当我输入 example.com:3000 时,它会正确加载页面并在服务器中记录一条消息。但是当我输入 example.com/game 时,它​​不仅不记录消息,而且不加载 socket.io 文件以及我拥有的一些脚本......我不知道我是否也在解释自己不好,但这让我发疯了
  • 你应该查看你的浏览器开发控制台和 apache 日志来调试你的问题
  • 我现在正在做,这实际上是我在上一条评论中所说的,如果需要我可以附上图片,我得到的唯一错误是来自浏览器开发控制台,说明当通过example.com/game 它无法加载 socket.io 文件,也无法从我的 HTML 文件中的 body 元素执行 onload 事件中的方法。我不知道如何检查/测试我的 .conf 文件是否设置正确,因为如果我输入 example.com/game 它实际上加载的是 HTML 文件而不是 JS (index.js)
  • 在客户端用/game/socket.io/socket.io.js替换/socket.io/socket.io.js
猜你喜欢
  • 1970-01-01
  • 2013-09-16
  • 2018-10-08
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 2021-01-30
  • 2019-11-10
  • 1970-01-01
相关资源
最近更新 更多