如何从快递应用程序获取http.server?

时间:2016-06-27 20:30:50

标签: javascript node.js express socket.io

我正在编写一个服务器端node.js应用程序,它使用express来处理HTTP请求,我正在添加websockets(socket.io)支持。但是,我无权访问启动HTTP服务器的代码。我正在编写一个快速路由器和函数来处理各种URL。我的代码如下:

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

在设置路由器时,我想使用socket.io来监听websocket连接。我无法将expressexpress()传递给require('socket.io')( xxx ),我需要传递http.Server对象。但由于我没有启动服务器,我怎么能得到它?

6 个答案:

答案 0 :(得分:14)

据我所知,Express app对象不知道服务器对象。在Express中工作的方式,app对象被赋予服务器对象,而不是相反。

您可以从req.connection.server的请求处理程序中访问服务器对象,但是它来自服务器作为请求的上下文的一部分,这不是app对象本身知道的事情

因此,如果要在初始化时访问服务器对象以与socket.io一起使用,则必须将服务器对象捕获到创建它的变量中。

您在问题中显示的代码不会创建或启动服务器。启动服务器以使用Express的常用两种方法是:

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一起使用。

在处理来自传递给请求处理程序的reqres对象的请求时,您可以从Express路由处理程序内部访问服务器。

res.connection.server
req.connection.server

答案 1 :(得分:4)

致电app.listen()时会返回服务器。例如:

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

答案 2 :(得分:1)

您还可以使用以下代码完成同样的事情。

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

server.listen(80);

有关详细信息,我建议您参考this link

答案 3 :(得分:1)

您可以编写一个简单的包装器,通过将以下内容放在某个文件中来实例化或获取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')();

这当然是一个简化的示例,但您可以修改逻辑以满足您的需求。

答案 4 :(得分:1)

当我将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();
})

答案 5 :(得分:0)

看看如何实现表达listen的功能:

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

因此,基本上,是否显式存储http服务器实例并不重要:

var server = require('http').createServer(app);

或参考快递listen的返回值:

var server = app.listen()

从技术上讲,您指的是同一件事,这在某种程度上使IMHO感到困惑...也许最好明确地要求开发人员将express app作为http服务器构造函数参数传递,因为app.listen()基本上是{的包装{1}}