是否可以为 NodeJS 应用程序设置一个基本 URL?

我希望能够在同一个域名下托管多个 NodeJS 应用程序,而不需要使用子域名(比如 google.com/reader 而不是 images.google.com )。问题在于,我总是在输入 url 的第一部分,例如 Express/NodeJS 中的“/reader”。

如何设置 Express 应用程序,使基本 URL 为 something.com/myapp

所以不是:

app.get("/myapp", function (req, res) {
// can be accessed from something.com/myapp
});

我可以做到:

// Some set-up
app.base = "/myapp"


app.get("/", function (req, res) {
// can still be accessed from something.com/myapp
});

我还想将 Connect 的 staticProvider 配置为以相同的方式工作(现在它默认将静态文件提供给 something.com/jssomething.com/css而不是 something.com/myapp/js)

108110 次浏览

目前还不支持这个功能,而且要自己添加它也不容易。

所有的路由信息都深藏在服务器代码中,而且作为一个额外的好处,它们自己的路由信息不会暴露。

我深入研究了这个源代码,还检查了 Express 的最新版本和 Connect 中间件,但是仍然没有对这些功能的支持,您应该在 连接特快本身上打开一个问题。

与此同时。

自己修补这个东西,这里有一个快速简单的方法,只需要修改一行代码。

~/.local/lib/node/.npm/express/1.0.0/package/lib/express/servers.js中,搜索:

// Generate the route
this.routes[method](path, fn);

这应该在 357行左右,替换为:

// Generate the route
this.routes[method](((self.settings.base || '') + path), fn);

现在只需添加设置:

app.set('base', '/myapp');

对于普通字符串路径来说,这样做效果很好,对于 RegEx 的支持,您必须自己在路由器中间件中进行修改,在这种情况下,最好提交一个问题文件。

至于静态提供程序,只需在设置时添加 /mypapp即可。

更新

也可以使用 RegExp:

// replace
this.routes[method](baseRoute(self.settings.base || '', path), fn);


// helper
function baseRoute(base, path) {
if (path instanceof RegExp) {
var exp = RegExp(path).toString().slice(1, -1);
return new RegExp(exp[0] === '^' ? '^' + base + exp.substring(1) : base + exp);


} else {
return (base || '') + path;
}
}

我只用少数几个表达式测试了它,所以这并不是100% 测试,但理论上它应该可以工作。

更新2

修补程序出现了问题:
Https://github.com/visionmedia/express/issues/issue/478

自4.0以来,快速路由器可以处理这个问题

Http://expressjs.com/en/api.html#router

Http://bulkan-evcimen.com/using_express_router_instead_of_express_namespace.html

var express = require('express');
var app = express();
var router = express.Router();


// simple logger for this router's requests
// all requests to this router will first hit this middleware
router.use(function(req, res, next) {
console.log('%s %s %s', req.method, req.url, req.path);
next();
});


// this will only be invoked if the path ends in /bar
router.use('/bar', function(req, res, next) {
// ... maybe some additional /bar logging ...
next();
});


// always invoked
router.use(function(req, res, next) {
res.send('Hello World');
});


app.use('/foo', router);


app.listen(3000);

上次回答(特快4.0之前) :

Express 命名空间模块(现在已经死了)用来完成这个任务:

Https://github.com/visionmedia/express-namespace

require('express-namespace');


app.namespace('/myapp', function() {
app.get('/', function (req, res) {
// can be accessed from something.com/myapp
});
});

此外,还存在可靠性问题。如果可靠性很重要,通常的解决方案是使用前端反向 HTTP 代理,如 nginx 或 HAProxy。它们都使用单线程事件架构,因此具有很强的可伸缩性。

然后,您可以为不同的子站点使用不同的节点进程,如果一个站点失败(未捕获的异常、内存泄漏、程序员错误等等) ,其余的子站点将继续工作。

我能够实现这一点,使用快速命名空间的路由和修复从下面的谷歌小组讨论的静态资产的组合。这个代码片段将处理/foo/javascript/jquery.js 的请求,就像处理/javascript/jquery.js 的请求一样:

app.use('/foo', express.static(__dirname + '/public'));

来源: Https://groups.google.com/forum/#!msg/express-js/xlp6_dx6he0/6oty4hwfv-0j

我正在寻找这个功能,但 API 路由,而不是静态文件。我所做的是,当我初始化路由器时,我添加了 mount 路径。我的配置是这样的

//Default configuration
app.configure(function(){
app.use(express.compress());
app.use(express.logger('dev'));
app.set('json spaces',0);
app.use(express.limit('2mb'));
app.use(express.bodyParser());


app.use('/api', app.router);        // <---


app.use(function(err, req, res, callback){
res.json(err.code, {});
});
});

在调用路由器时注意’/api’

只是为了更新线程,现在使用 Express.js V4你可以不使用 express-namespace:

var express = require('express'),
forumRouter = express.Router(),
threadRouter = express.Router(),
app = express();


forumRouter.get('/:id)', function(req, res){
res.send('GET forum ' + req.params.id);
});


forumRouter.get('/:id/edit', function(req, res){
res.send('GET forum ' + req.params.id + ' edit page');
});




forumRouter.delete('/:id', function(req, res){
res.send('DELETE forum ' + req.params.id);
});


app.use('/forum', forumRouter);


threadRouter.get('/:id/thread/:tid', function(req, res){
res.send('GET forum ' + req.params.id + ' thread ' + req.params.tid);
});


forumRouter.use('/', threadRouter);


app.listen(app.get("port") || 3000);

干杯!

我知道这是一个非常古老的问题,但是自从大多数这些答案被发布以来,Express 已经改变了很多,所以我想我应该分享我的方法。

当然,您可以使用 Express4路由器将特定路径后面的相关功能组合在一起。这是有据可查的,并且已经被其他答案所涵盖。

但是,也可以在特定的路径上挂载整个应用程序。例如,假设我们的应用程序(我们希望在 /myapp托管的应用程序)在一个名为 myapp.js的文件中如下所示:

var express = require('express'),
path = require('path'),
app = express();


app.use(express.static(path.join(__dirname, 'public')));


app.get('/hello', function(req, res) {
res.send('Hello');
});


// Lots of other stuff here


exports.app = app;

在我们的主 js 文件中,我们可以将整个应用程序挂载到路径 /myapp:

var express = require('express'),
app = express(),
myApp = require('./myapp').app;


app.use('/myapp', myApp);


app.listen(3000);

注意,我们在这里创建了两个应用程序,一个挂载在另一个上。根据需要,主应用程序可以在不同的路径上安装更多的子应用程序。

myapp.js中的代码完全独立于其安装位置。在这方面,它与 express-generator使用的结构类似。

关于子应用程序的一些文档可以在这里找到:

Https://expressjs.com/en/4x/api.html#app.mountpath Https://expressjs.com/en/4x/api.html#app.onmount