Можно ли установить базовый URL для приложения NodeJS?
Я хочу иметь возможность размещать несколько приложений NodeJS в одном домене, не используя поддомены (например, google.com/reader вместо images.google.com). Проблема в том, что я всегда печатаю первую часть URL-адреса, например. "/reader" в Express/NodeJS.
Как настроить приложение 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/js
или something.com/css
вместо something.com/myapp/js
)
Ответы
Ответ 1
В настоящий момент это не поддерживается, и это не легко добавить его самостоятельно.
Вся информация о маршрутизации похоронена глубоко внутри кода сервера, и в качестве бонуса нет воздействия на маршруты, которые они сами себе.
Я вырыл источник, а также проверил последнюю версию Express и промежуточного программного обеспечения Connect, но до сих пор нет поддержки для таких функций, вы должны открыть проблему либо на Connect или Express.
В то же время...
Исправьте это сами, здесь быстрый и простой способ с изменением только одной строки кода.
В ~/.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
Ответ 2
Экспресс-маршрутизатор может справиться с этим с 4.0
http://expressjs.com/api#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 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):
Модуль экспресс-пространства имен (теперь мертвый) используется для выполнения трюка:
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
});
});
Ответ 3
Я смог достичь этого, используя комбинацию пространства выраженных имен для маршрутов и исправление из нижеперечисленного обсуждения группы google для статических активов. Этот фрагмент будет обрабатывать запрос /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
Ответ 4
Просто обновить поток, теперь с помощью 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);
Ура!
Ответ 5
Существуют также проблемы с безопасностью. Если важна надежность, общим решением является использование обратного HTTP-прокси-сервера, такого как nginx или HAProxy. Они оба используют однопоточную evented архитектуру и, следовательно, очень масштабируемы.
Затем у вас могут быть разные процессы node для разных подсайтов, и если один сайт выходит из строя (неотображенное исключение, утечка памяти, ошибка программиста, независимо от того), остальные подсайты продолжают работать.
Ответ 6
Я искал эту функцию, но для маршрутов 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" при вызове маршрутизатора
Ответ 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