【问题标题】:Is it possible to set a base URL for NodeJS app?是否可以为 NodeJS 应用程序设置基本 URL?
【发布时间】:2011-05-21 12:08:53
【问题描述】:

我希望能够在同一个域下托管多个 NodeJS 应用程序,而无需使用子域(例如 google.com/reader 而不是 images.google.com)。问题是我总是输入网址的第一部分,例如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

【问题讨论】:

  • 也许你可以更新答案,因为它已经过时了?

标签: node.js connect express


【解决方案1】:

目前还不支持,自己添加也不容易。

整个路由的东西都深埋在服务器代码中,作为奖励,它们自己的路由不会暴露。

我挖掘了源代码并检查了最新版本的 Express 和 Connect 中间件,但仍然不支持此类功能,您应该在 ConnectExpress 本身上打开一个问题。

同时...

自己打补丁,这是一种快速简便的方法,只需更改一行代码。

~/.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

【讨论】:

  • 更新:修复了简单字符串的损坏补丁。
  • 感谢您的全面回答。修补快递的解决方案。但是,将参数传递给 staticProvider 只会设置找到静态文件的根目录,而不是为其提供服务的 url。我猜可以制作一个类似的补丁,从 url 中删除 /myapp。
  • 覆盖第三方库是不明智的,因为每次更新到新版本时,您还需要重新添加代码。
【解决方案2】:

express 路由器从 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);

上一个答案(在 express 4.0 之前):

express-namespace 模块(现在已死)用于解决问题:

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
        });
});

【讨论】:

  • 来自 Google 的注意事项:这是正确的答案,即使它没有被标记。如果可能的话,通常最好避免对维护良好的库进行猴子修补。
  • 进一步说明 - 项目似乎已死 github.com/expressjs/express-namespace/issues/44 在 express 4 中使用路由器 bulkan-evcimen.com/…
  • 这个过程是否会评估重定向?例如resp.redirect('/') 但你真的打算去 /myapp
【解决方案3】:

还有可靠性问题。如果可靠性很重要,一个常见的解决方案是使用前端反向 HTTP 代理,例如 nginx 或 HAProxy。它们都使用单线程事件架构,因此具有很强的可扩展性。

然后您可以为不同的子站点设置不同的节点进程,并且如果一个站点发生故障(未捕获的异常、内存泄漏、程序员错误等),其余的子站点继续工作。

【讨论】:

    【解决方案4】:

    我能够结合使用路由的 express-namespace 和下面的 google group 讨论中的静态资产修复来实现这一点。这个 sn-p 会将对 /foo/javascripts/jquery.js 的请求视为对 /javascripts/jquery.js 的请求:

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

    来源: https://groups.google.com/forum/#!msg/express-js/xlP6_DX6he0/6OTY4hwfV-0J

    【讨论】:

    • 这一定是答案,而不是破解核心。
    【解决方案5】:

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

    //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-resouce 顺利配合。我有几个快速子应用程序,它们使用此解决方案在前缀 /api 下方提供 API,并在 /. 处提供常规网站
    • 只想指出:Error: 'app.router' is deprecated! Please see the 3.x to 4.x migration guide for details on how to update your app.
    • app.router 已弃用
    【解决方案6】:

    只是为了更新线程,现在有了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);
    

    干杯!

    【讨论】:

      【解决方案7】:

      我知道这是一个非常古老的问题,但 Express 已经发生了很大变化,因为大多数这些答案都已发布,所以我想我会分享我的方法。

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

      但是,也可以将整个应用程序挂载到特定路径。举个例子,假设我们的应用程序(我们要在/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

      【讨论】:

      • 优雅的解决方案,可用于模块化不同的应用程序,2021 年仍然有效,耻辱快递已死
      猜你喜欢
      • 2011-12-18
      • 2011-10-30
      • 2019-09-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 2021-06-14
      相关资源
      最近更新 更多