web-dev-qa-db-ja.com

Expressアプリからhttp.serverを取得するにはどうすればよいですか?

Expressを使用してHTTPリクエストを処理するサーバー側のnode.jsアプリケーションを作成しており、websocket(socket.io)サポートを追加しています。ただし、HTTPサーバーを起動するコードにアクセスできません。さまざまなURLを処理するエクスプレスルーターと関数を作成しています。私のコードは次のようになります:

_var express = require('express');
var router = express.Router();
router.post( myURL, myFunction );
_

ルーターを設定するときに、socket.ioを使用してWebSocket接続もリッスンしたいと思います。 expressまたはexpress()require('socket.io')( xxx )に渡すことができません。http.Serverオブジェクトを渡す必要があります。しかし、サーバーを起動しなかったので、どうすれば入手できますか?

14
Graeme Perrow

私の知る限り、Express appオブジェクトはサーバーオブジェクトを認識していません。 Expressでの動作方法では、appオブジェクトはサーバーオブジェクトに与えられ、その逆ではありません。実際、単一のappオブジェクトを複数のサーバーで使用することもできます(httpサーバーとhttpsサーバーで使用されることもあります)。

req.connection.serverを使用すると、リクエストハンドラー内からサーバーオブジェクトにアクセスできますが、サーバーからはリクエストのコンテキストの一部として取得されます。これは、appオブジェクト自体が認識しているものではありません。

そのため、初期化時にsocket.ioで使用するためにサーバーオブジェクトにアクセスする場合は、サーバーオブジェクトを変数が作成される場所にキャプチャする必要があります。

質問に表示するコードはサーバーを作成または起動しません。 Expressで使用するサーバーを起動する通常の2つの方法は次のとおりです。

var express = require('express');
var app = express();
// Express creates a server for you and starts it
var server = app.listen(80);

または、サーバーを自分で作成し、ハンドラとしてExpressに渡します。

var express = require('express');
var app = express();
// you explicitly create the http server
var server = require('http').createServer(app);
server.listen(80);

これらのいずれの場合も、変数にサーバーオブジェクトが含まれ、socket.ioでそれを使用できます。


リクエストハンドラーに渡されるreqまたはresオブジェクトからのリクエストの処理内で、Expressルートハンドラー内からサーバーにアクセスできます。

res.connection.server
req.connection.server
23
jfriend00

app.listen()を呼び出すと、サーバーが返されます。例えば:

const server = app.listen(process.env.NODE_PORT, () => {
  console.log('Listening', server.address());
});
7
Brad

簡単なラッパーを記述して、次のコードをファイルに追加することで、ExpressアプリでSocket IOインスタンスをインスタンス化または取得できます。

//Dependencies
const socketIo = require('socket.io');

//Placeholder for instance
let io;

//Export handler to instantiate or get instance
module.exports = function(server) {
  if (server) {
    io = socketIo(server);
  }
  return io;
};

次に、Expressを設定するときに、通常の方法でこのインスタンスをインスタンス化できます。

const app = require('express')();
const server = require('http').Server(app);
const io = require('./path-to-your-file')(server);

そして、後で別のルートやコードで必要になった場合は、次のようにして取得できます。

const io = require('./path-to-your-file')();

これはもちろん単純な例ですが、必要に応じてロジックを変更できます。

1
Adam Reis

次のコードを使用して同じことを行うこともできます。

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(80);

詳細については、あなたが参照することをお勧めします このリンク

1
chernwen123

Wepack devServerをsocket-ioで使用したときにこの問題が発生し、jfriend00のコメントが役に立ちました。私はこのトリックを使います:

let server;
app.use((req, res, next) => {
    if (!server){
        server = req.connection.server;
        //do fancy staffs with http-server
    }
    next();
})
1
lexa-b

express listen関数の実装方法をご覧ください。

_app.listen = function listen() {
  var server = http.createServer(this);
  return server.listen.apply(server, arguments);
};
_

したがって、httpサーバーインスタンスを明示的に格納するかどうかは基本的に問題になりません。

_var server = require('http').createServer(app);
_

または、express listenの戻り値を参照してください:

_var server = app.listen()
_

あなたは同じことを技術的に参照していますが、これはどうやら混乱しています... app.listen()は基本的にhttp.Server(arguments)

0
Tomas