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

发布于 2024-10-06 06:24:47 字数 670 浏览 8 评论 0原文

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

I want to be able to host multiple NodeJS apps under the same domain, without using sub-domains (like google.com/reader instead of images.google.com). The problem is that I'm always typing the first part of the url e.g. "/reader" in Express/NodeJS.

How can I set up an Express app so that the base URL is something.com/myapp?

So instead of:

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

I can do:

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

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

I'd also like to configure Connect's staticProvider to behave the same way (right now it defaults to serving static files to something.com/js or something.com/css instead of something.com/myapp/js)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

‖放下 2024-10-13 06:24:47

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/express-namespace。 com/visionmedia/express-namespace

require('express-namespace');

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

The express router can handle this since 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);

Previous answer (before express 4.0) :

The express-namespace module (dead now) used to do the trick :

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
        });
});
把人绕傻吧 2024-10-13 06:24:47

目前尚不支持此功能,并且您自己添加它并不容易。

整个路由内容都深埋在服务器代码中,而且作为奖励,它们本身的路由不会暴露。

我深入研究了源代码,还检查了最新版本的 Express 和 Connect 中间件,但仍然不支持此类功能,您应该在 ConnectExpress 本身。

同时...

自己修补,这是一种快速而简单的方法,只需更改一行代码。

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

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

This should be around line 357 code>,将其替换为:

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

现在只需添加设置:

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

这适用于纯字符串的路径,对于正则表达式支持,您必须自己在路由器中间件中进行修改,在这种情况下最好提出问题。

至于静态提供程序,只需在设置时添加 /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

At the moment this is not supported, and it's not easy to add it on your own.

The whole routing stuff is buried deep inside the server code, and as a bonus there's no exposure of the routes them selfs.

I dug through the source and also checked out the latest version of Express and the Connect middleware, but there's still no support for such functionality, you should open a issue either on Connect or Express itself.

Meanwhile...

Patch the thing yourself, here's a quick and easy way with only one line of code changed.

In ~/.local/lib/node/.npm/express/1.0.0/package/lib/express/servers.js, search for:

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

This should be around line 357, replace that with:

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

Now just add the setting:

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

This works fine with paths that are plain strings, for RegEx support you will have to hack around in the router middleware yourself, better file an issue in that case.

As far as the static provider goes, just add in /mypapp when setting it up.

Update

Made it work with RegExp too:

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

I only tested this with a handful of expressions, so this isn't 100% tested but in theory it should work.

Update 2

Filed an issue with the patch:
https://github.com/visionmedia/express/issues/issue/478

九命猫 2024-10-13 06:24:47

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

干杯!

Just to update the thread, now with Express.js v4 you can do it without using 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);

Cheers!

贪恋 2024-10-13 06:24:47

我能够使用路由的express-namespace和下面的谷歌小组讨论中的静态资产修复的组合来实现这一点。此代码片段会将对 /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

I was able to achieve this using a combination of express-namespace for the routes and a fix from the below google group discussion for the static assets. This snippet will treat a request to /foo/javascripts/jquery.js like a request to /javascripts/jquery.js:

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

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

究竟谁懂我的在乎 2024-10-13 06:24:47

我知道这是一个非常古老的问题,但自从大多数答案发布以来,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

I know this is a very old question but Express has changed a lot since most these answers were posted so I thought I'd share my approach.

You can, of course, use Routers with Express 4 to group together related functionality behind a particular path. This is well documented and has already been covered by other answers.

However, it is also possible to mount an entire application at a particular path. As an example, let's assume our application (the one we want to host at /myapp) looks like this, in a file called 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;

In our main js file we could then mount this whole application at the path /myapp:

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

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

app.listen(3000);

Note that we've created two applications here, one mounted on the other. The main application could have further sub-apps mounted at different paths as required.

The code in myapp.js is completely independent of where it was mounted. It's similar to the structure used by the express-generator in that regard.

Some documentation about sub-apps can be found here:

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

無處可尋 2024-10-13 06:24:47

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

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

There are also reliability issues. If reliability is important, a common solution is to use a front-end reverse HTTP proxy such as nginx or HAProxy. They both use single-thread evented architecture and are thus very scalable.

Then you can have different node processes for different subsites, and if one site fails (uncaught exception, memory leak, programmer error, whatever) the rest of sub-sites continue to work.

心房敞 2024-10-13 06:24:47

我一直在寻找这个功能,但是是为了 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”

I was looking for this feature but for API routes, not for static files. What I did was that when I initialized the router, I added the mount path. So my configuration looks like this

//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, {});
    });
});

Notice the '/api' when calling the router

时光暖心i 2024-10-13 06:24:47

这对我有用

const app = express();
const router = express.Router()
app.get("/books", function(){
  //your code
})
app.use("/api", router)

This worked for me

const app = express();
const router = express.Router()
app.get("/books", function(){
  //your code
})
app.use("/api", router)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文