如何在node-http-proxy旁边使用vhost?

时间:2012-02-20 21:38:59

标签: apache node.js proxy vhosts express

我正在运行Nodejs和Apache。

node-http-proxy正在侦听端口80,然后将请求转发到Apache(:9000)或Express(:8000)。

我在Apache上的虚拟主机看起来像:

<VirtualHost 127.0.0.1>
    DocumentRoot "/localhost/myVhost"
    ServerName myVhost
</VirtualHost>

我的问题是,在Express / Nodejs端具有类似vhost功能的“正确”方法是什么?我宁愿不必将每个Nodejs应用程序放在它自己的端口上,如下所示:

https://github.com/nodejitsu/node-http-proxy (标题为“使用'仅主机名'代理请求的代理请求”部分)

我注意到Connect(根据我的理解,捆绑在Express中)有一些vhosts功能。我应该使用它吗?如果是这样,在node-http-proxy旁边运行它的正确方法是什么?

http://www.senchalabs.org/connect/middleware-vhost.html

我还注意到这个名为“Cluster”的其他模块,似乎是相关的,但我不确定如何:

http://learnboost.github.com/cluster/

虽然不想压倒,但我也遇到了一个名为“Haibu”的东西,似乎是相关的,但我不确定它是否会成为使用虚拟主机的全部替代品:

https://github.com/nodejitsu/haibu

注意:我是前端人员,所以我对很多服务器术语不是很熟悉

4 个答案:

答案 0 :(得分:11)

我从未想过海布或群集。但我确实找到了解决我问题的好方法。令我惊讶的是,它实际上非常简单。但是,我对服务器知之甚少,所以虽然这有效,但它可能不是最佳的。

我在Apache上设置了正常的虚拟主机 (http://httpd.apache.org/docs/2.0/vhosts/examples.html)

我在Node上安装了以下内容

  • Express(http://expressjs.com/)
  • node-http-proxy(https://github.com/nodejitsu/node-http-proxy)

然后,作为个人风格,我将所有虚拟主机放在一个公共目录(/ localhost)

然后我切换Apache以侦听端口80以外的端口。我恰好选择端口9000,因为我已经看到在某处使用过。 (在httpd.conf中,将“Listen 80”改为“Listen 9000”)。我还必须确保在extra / httpd-vhosts.conf中定义的所有虚拟主机都设置为基于IP的nameVirtualHost(127.0.0.1),而不是使用端口(*:80)。

在节点方面,我创建了我的应用程序/服务器(也称为节点虚拟主机),它在端口8000上进行了监听(有点随意选择端口号)请参阅此链接,了解如何使用快速创建服务器:http://expressjs.com/guide.html

在我的/ localhost目录中,我创建了一个名为“nodeHttpProxy.js”的文件

在nodeHttpProxy.js中使用node-http-proxy然后我创建了一个侦听端口80的代理服务器。使用express,包装连接(http://www.senchalabs.org/connect/)我创建了我的虚拟主机。

nodeHttpProxy.js文件如下所示:

// Module dependancies
var httpProxy = require('/usr/local/lib/node_modules/http-proxy/lib/node-http-proxy')
, express = require('/usr/local/lib/node_modules/express/lib/express');

// Http proxy-server
httpProxy.createServer(function (req, res, proxy) {

    // Array of node host names
    var nodeVhosts = [
        'vhost1'
        , 'vhost2'
    ]
    , host = req.header('host')
    , port = nodeVhosts.indexOf(host) > -1
        ? 8000
        : 9000;

    // Now proxy the request
    proxy.proxyRequest(req, res, {
        host: host
        , port: port
    });
})
.listen(80);

// Vhosts server
express.createServer()
.use(express.vhost('vhost1', require('./vhost1/app')))
.use(express.vhost('vhost2', require('./vhost2/app')))
.app.listen(8000);

如您所见,每次创建新的Node虚拟主机时,我都要做两件事:

  1. 将虚拟主机名添加到“nodeVhosts”数组
  2. 使用.set方法
  3. 定义新的快速虚拟主机

    当然,我还必须在my / localhost目录中创建实际的主机路径/文件。

    完成所有这些后,我只需要运行nodeHttpProxy.js:

    node nodeHttpProxy.js
    

    您可能会遇到一些奇怪的“EACCESS”错误,在这种情况下,只需运行sudo。

    它将侦听端口80,如果主机与nodeVhosts数组中的某个名称匹配,它将在端口8000上将请求转发给该主机,否则它会将请求转发到端口9000上的该主机上。 / p>

答案 1 :(得分:6)

我最近一直在考虑这个问题,因为我在个人测试环境中解决了同样的问题。您无法绕过每个节点应用程序在其自己的端口上运行,但您可以抽象出该过程的痛苦。以下是我现在正在使用的内容,但我希望在此基础上构建一个npm包,以简化将来的工作。

我的每个node.js应用程序都有一个映射文件,其中包含应用程序正在侦听的端口以及一个映射,该映射指示应用程序所在的预期路径。该文件的内容如下所示:

{"path": "domain.com/path", "port": 3001}

当我启动我的应用程序时,它将从map.json文件读取端口并侦听指定的端口。

var map = fs.readFileSync('map.json', 'ascii');
app.listen(map.port);

然后在我的代理设置中,我遍历每个node.js应用程序目录,并检查map.json文件,该文件指示应该将端口80流量代理到此应用程序。

我使用几乎完全相同的方法来为我们的apache托管应用程序设置代理。我们在我们服务的PHP网站上使用基于文件夹的约定,它使用以下配置:

VirtualDocumentRoot /var/www/%-2.0.%-1/%-3+/
VirtualScriptAlias /var/www/%-2.0.%-1/%-3+/cgi-bin/

这实质上允许我们使用以下结构将域映射到文件夹。

http://sub.domain.com/ = /var/www/domain.com/sub/

添加或删除网站不需要其他配置。这与我目前用于代理apache和节点站点的内容非常接近。我可以在不修改此代理应用程序的情况下添加新节点和新的apache站点。

<强>的proxy.js

var fs = require('fs');
var httpProxy = require('http-proxy');

var proxyTable = [];

// Map apache proxies
fs.readdirSync('/var/www/').forEach(function(domain) {
    fs.readdirSync('/var/www/' + domain).forEach(function(path) {
        var fqd = domain + '/' + path;
        var port = fs.readFileSync('port', 'ascii');
        proxyTable[fqd] = fqd + ':' + 8080;
    });
});    

// Map node proxies
fs.readdirSync('/var/www-node/').forEach(function(domain) {
        var map = fs.readFileSync('map.json', 'ascii');
        proxyTable.[map.path] = '127.0.0.1:' + map.port;
});

var options = {
    router: proxyTable
};

var proxyServer = httpProxy.createServer(options);
proxyServer.listen(80);

将来,我可能会将路径与应用程序正在侦听的端口分离,但是这种配置允许我自动构建代理映射,只需要很少的工作。希望这会有所帮助。

答案 2 :(得分:0)

我从@uglymunky那里获得了一些灵感,并在Ubuntu上写了一个厨师脚本。

使用此脚本,您可以在从github下载我的chef项目后使用1行在单个服务器上安装带有vhost支持的express和apache

https://github.com/toranb/ubuntu-web-server

如果您安装了git并将其拉下来,可以这样开启......

sudo ./install.sh configuration.json

这需要Ubuntu 12.04或更高版本,因为我在重新启动计算机时利用了一个upstart脚本来启动节点

当脚本完成后,您将拥有一个工作的ubuntu Web服务器,使用express来运行您配置的任何节点应用程序,沿着apache运行您配置的任何wsgi应用程序

答案 3 :(得分:0)

我正在开发一个极其简单的点库,它可以与您的项目完全隔离。基本上,这个想法将在您的服务器上独立运行,并且不必担心必须在项目中将其捆绑到连接方式。

看看config.json文件,看看它实际上是多么简单。

我一直在寻找这个,但我找到了一些东西,但他们并没有支持我需要的一切,特别是HTTPS,WS和WSS!

现在我写的库只适用于HTTP。但在接下来的几天里,我希望能够完成并为HTTPS,WS和WSS工作。