web-dev-qa-db-ja.com

NodeJSアプリのベースURLを設定することはできますか?

サブドメイン(images.google.comの代わりにgoogle.com/readerなど)を使用せずに、同じドメインで複数のNodeJSアプリをホストできるようにします。問題は、URLの最初の部分を常に入力していることです。 Express/NodeJSの「/ reader」。

ベースURLがsomething.com/myappになるようにExpressアプリを設定するにはどうすればよいですか?

代わりに:

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に静的ファイルを提供します)

58
David Tang

現時点ではこれはサポートされておらず、自分で追加するのは簡単ではありません。

ルーティングに関するものはすべてサーバーコードの奥深くに埋められており、おまけとして、それらが自分自身のルートを公開することはありません。

ソースを掘り下げ、ExpressとConnectミドルウェアの最新バージョンもチェックアウトしましたが、そのような機能はまだサポートされていません。 Connect または Express 自体。

その間...

自分でパッチを適用してください。ここでは、1行のコードを変更するだけで、すばやく簡単な方法があります。

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

16
Ivo Wetzel

エクスプレスルーターは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-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
        });
});
128
Remi Mélisson

スレッドを更新するために、今すぐExpress.jsv4を使用して、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);

乾杯!

8
danilodeveloper

ルートのエクスプレス名前空間と、以下の静的アセットの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

7
Ben Zittlau

信頼性の問題もあります。信頼性が重要な場合、一般的なソリューションは、nginxやHAProxyなどのフロントエンドリバースHTTPプロキシを使用することです。どちらもシングルスレッドイベントアーキテクチャを使用するため、非常にスケーラブルです。

その後、サブサイトごとに異なるノードプロセスを使用できます。1つのサイトが失敗した場合(キャッチされない例外、メモリリーク、プログラマエラーなど)、残りのサブサイトは引き続き機能します。

3
nponeccop

この機能を探していましたが、静的ファイルではなく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」に注意してください

2
Xerri

これは非常に古い質問ですが、これらの回答のほとんどが投稿されて以来、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);

ここでは2つのアプリケーションを作成し、一方が他方にマウントされていることに注意してください。メインアプリケーションには、必要に応じて別のパスに追加のサブアプリをマウントできます。

myapp.jsのコードは、マウントされた場所とは完全に独立しています。その点でexpress-generatorによって使用される構造に似ています。

サブアプリに関するドキュメントはこちらにあります。

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

1
skirtle