不久前我在虚拟目录中运行我的应用程序时遇到了同样的问题。
经过大量时间的浪费和挣扎,我能够将所有部分放在一起,让我的应用程序在虚拟目录中运行,其中包括使用 Socket.io 的应用程序
由于没有太多关于这个特定场景的文档和可用的资源,我发现,只部分描述了如何解决这个问题。这是有关如何使所有这些工作的教程。我个人有多个使用此设置实现 REST API 或 Socket.io 的 Node.js Web 服务。
我强烈建议使用下面的 Web.config 模板来完成这项工作。
IISNode Web.config 模板
https://gist.github.com/pbaio/f63918181d8d7f8ee1d2
上面链接中的配置有一些我放在那里的注释以帮助易用性。它配置为使用 app.js 作为主文件,但如果您的文件命名不同,只需切换值以使用该文件。
要使此配置正常工作,如果您尚未安装它,您将需要用于 IIS 的 URL 重写模块。
默认设置
默认情况下,此模板设置为在 IIS 中运行的标准 Web 应用程序中工作,而不是在虚拟目录环境中。但是,通过一些小的调整,您可以使用相同的 Web.config 在虚拟目录中运行 Node.js 应用程序。
获取 Express 以使用您的虚拟目录
IISNode 在您的<appSettings>
环境变量中声明所有键。我们可以利用它来设置我们的虚拟目录路径并将其公开给我们的主文件。在上面的模板中,我们的主文件是app.js
.
获取我们的虚拟目录路径
我们需要在我们的 Web.config 文件中获取我们的应用程序将从中路由的路径。我们通过访问进程对象上的环境变量来做到这一点。将以下行添加到我们的app.js
文件中。
var virtualDirPath = process.env.virtualDirPath || '';
这会从我们的 Web.config 中检索我们的 virtualDirPath,并给它一个空字符串的默认值。
路由页面
然后我们可以将 virtualDirPath 添加到我们的路由中,如果您使用的是 Jade 或 EJS 等视图引擎,我们可以将我们的虚拟目录路径传递给视图:
var app = require('express')();
app.get(virtualDirPath + '/', function(req, res) {
res.render('index', { virtualDirPath: virtualDirPath });
});
静态内容
我们可以很容易地提供如下服务:
app.use(express.static(path.join(virtualDirPath, 'public')));
如果您使用的是 Bower.io,同样的事情:
app.use('/bower_components', express.static(path.join(virtualDirPath,'bower_components')));
使用 Express 和 Socket.io 的虚拟目录
在 Socket.io 中使用虚拟目录时,我们需要更改服务器和客户端的配置。
服务器端
我们需要配置我们的 Socket.io 服务器,这与您通常的做法略有不同。
var app = require('express')();
var virtualDirPath = process.env.virtualDirPath || '';
var server = require('http').Server(app);
var io = require('socket.io')(server, { path: virtualDirPath + '/socket.io' });
// Get the port that we should be listening on
server.listen(process.env.PORT || 8080);
在上面的代码中,我们正在修改我们的 Socket.io 服务器以在我们的 virtualDirpath 上运行,而不是默认路径('/socket.io'
是默认路径)。
Web.config 更改
为了让 IISNode 与 socket.io 正常工作,我们还需要添加一些额外的 url 重写并换出我们的处理程序。在上面的模板配置文件中,我们可以在第 57 行看到 Socket.io 处理程序,它在模板中被注释掉了。
<add name="iisnode-socket.io" path="app.js" verb="*" modules="iisnode" />
然后我们需要为 Socket.io 路径添加我们的 url 重写
<rule name="SocketIO" patternSyntax="ECMAScript">
<match url="socket.io.+" />
<action type="Rewrite" url="app.js"/>
</rule>
客户端
在客户端,我们只需要指定 Socket.io 服务器正在侦听的路径,而不是其默认路径。
var socket = io.connect('http://example.com:port', { path: '/virtualDirPath/socket.io' });
此时一切都应该很好,您的 Socket.io 应用程序在带有 IISNode 的虚拟目录中运行。
环境信息
使用此配置的应用程序是使用 Node.js、Express 4.12.3 构建的,并在安装了 IISNode 的 IIS 7.5 中运行。此外,通过更改配置文件中的处理程序,Socket.io 也可以在虚拟目录中使用。上例中使用的 Socket.io 版本是 1.3.5