ExpressJS服务器 - 如何处理多个域

jAn*_*ndy 21 javascript node.js express

我在使用Express搞错了,我想知道,"最正确"的方法是处理链接到同一服务器的多个域.

让我们假设我们有

  • foo.com
  • bar.net
  • baz.com

这一切都指向了111.222.333.444.该机器正在使用Express运行NodeJS.我目前的解决方案如下:

var express = require( 'express' ),
    app     = module.exports = express.createServer(),
// ... more lines ...
app.get( '/', routes.index.bind( app ) );
Run Code Online (Sandbox Code Playgroud)

到目前为止,这非常简单.到目前为止唯一的例外是我的app.configure电话,我没有打电话.use( express.static() ).那是因为这个.routes.index()方法现在看起来像这样:

var fs    = require( 'fs' ),
// ... more lines ...

exports.index = function( req, res ) {
    var host = /(\w+\.)?(.*)\.\w+/.exec( req.header( 'host' ) ),
        app  = this;

    switch( host[ 2 ] ) {
        case 'foo':
            app.use( express.static( '/var/www/foo' ) );
            fs.readFile( '/var/www/foo/index.html', 'utf8', fileReadFoo );
            break;
        case 'bar':
            app.use( express.static( '/var/www/bar' ) );
            fs.readFile( '/var/www/bar/index.html', 'utf8', fileReadBar );
            break;
        case 'baz':
            // ... lines ...
            res.render( 'index', { title: 'Baz Title example' } );
            break;
        default:
            res.send('Sorry, I do not know how to handle that domain.');
    }

    function fileReadFoo( err, text ) {
        res.send( text );
    }

    function fileReadBar( err, text ) {
        res.send( text );
    }
};
Run Code Online (Sandbox Code Playgroud)

这里发生的是,我分析req.headerhost条目并解析域名.基于此,我调用了.static()方法,因此Express可以提供正确的静态资源等,而且,我只是简单地读取并发送index.html文件的内容.我试图使用Jade来提供普通的HTML文件,但Jade中include指令只接受相对的修改.

然而,这确实有效,但我不确定这是否是一个好习惯.

任何建议/帮助欢迎.


更新

我想我需要更清楚地说明这一点.无论如何我不是初学者.我非常清楚ES是如何工作的以及NGINX等其他服务器.我正在寻找有关NodeJS/Express正确用途的合格答案.如果使用Node/Express没有任何意义,请详细说明.如果有更好的方法使用Node/Express执行此操作,请解释.

谢谢 :-)

Jon*_*ski 28

瓦迪姆几乎是正确的想法.您可以配置如何使用vhost中间件响应每个域:

// `baz.com`
var app = express.createServer();
app.get( '/', routes.index );

// ...

express.createServer()
    .use( express.vhost( 'foo.com', express.static( '/var/www/foo' ) ) )
    .use( express.vhost( 'bar.net', express.static( '/var/www/bar' ) ) )
    .use( express.vhost( 'baz.com', app ) )
    .use( function( req, res ) {
        res.send('Sorry, I do not know how to handle that domain.');
    })
    .listen( ... );
Run Code Online (Sandbox Code Playgroud)

routes.index然后可以简化为仅处理baz.com请求:

exports.index = function( req, res ) {
    // ... lines ...
    res.render( 'index', { title: 'Baz Title example' } );
};
Run Code Online (Sandbox Code Playgroud)

编辑

至于比较:

switch首先有效地完成,并将确定如何处理所有基于以下的请求host- 类似于:

express.createServer().use(function( req, res, next ) {
    switch( req.host ) {
        case 'foo.com': express.static( '/var/www/foo' )( req, res, next ); break;
        case 'bar.net': express.static( '/var/www/bar' )( req, res, next ); break;
        case 'baz.com': app.handle( req, res, next ); break;
        default: res.send( ... );
    }
}).listen( ... );
Run Code Online (Sandbox Code Playgroud)

它允许您在启动时设置堆栈,以便立即获得任何中间件:

server.stack = [
    express.vhost( 'foo.com', ... ),
    express.vhost( 'bar.net', ... ),
    express.vhost( 'baz.com', ... ),
    [Function]
];
Run Code Online (Sandbox Code Playgroud)

这些也反映了您可能遇到的两个可能的问题来源:

相同堆栈没有过滤器

每个Application只有1个中间件堆栈,您正在使用的所有中间件都直接添加到app.use(...).尽管添加了一些条件,你仍然得到:

app.stack = [
    // ...,
    app.router,
    express.static( '/var/www/foo' ),
    express.static( '/var/www/bar' )
];
Run Code Online (Sandbox Code Playgroud)

而且条件不会改变如何static中间件回应-这是req.path不是req.host-只有当他们在堆开始响应.

堆栈的状态

而且,如果static中间件直到另一个请求发出后才添加,那么我认为它们不会立即可用:

// GET http://foo.com/file 404
app.stack = [ app.router ]

// GET http://foo.com/ 200
app.stack = [ app.router, express.static( '/var/www/foo' ) ]

// GET http://foo.com/file 200
app.stack = [ app.router, express.static( '/var/www/foo' ) ]
Run Code Online (Sandbox Code Playgroud)

这也可能意味着static可以多次将相同的中间件添加到堆栈中:

// 3x GET http://foo.com/
app.stack = [
    app.router,
    express.static( '/var/www/foo' ),
    express.static( '/var/www/foo' ),
    express.static( '/var/www/foo' )
]
Run Code Online (Sandbox Code Playgroud)

增加依赖于其他请求也表明可能的竞争条件:

// was `foo.com` or `bar.net` first?
app.stack = [
    app.router,
    express.static( ? ),
    express.static( ? )
]
Run Code Online (Sandbox Code Playgroud)


Bin*_*los 12

我喜欢使用bouncy作为前端反向代理 - 这可以让你运行完全不同的快速堆栈作为不同的服务器进程(每个具有不同的功能并且分离以获得健壮性)...

然后,您可以决定如何路由到不同的端口,它可以与WebSockets一起使用.

var bouncy = require('bouncy');

bouncy(function (req, bounce) {
    if (req.headers.host === 'bouncy.example.com') {
        bounce(8000);
    }
    else if (req.headers.host === 'trampoline.example.com') {
        bounce(8001)
    }
}).listen(80);
Run Code Online (Sandbox Code Playgroud)