如何从 express 应用程序中获取 http.server?

Posted

技术标签:

【中文标题】如何从 express 应用程序中获取 http.server?【英文标题】:How do I get the http.server from the express app? 【发布时间】:2016-10-29 23:35:22 【问题描述】:

我正在编写一个使用 express 来处理 HTTP 请求的服务器端 node.js 应用程序,并且我正在添加 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 对象。但是由于我没有启动服务器,那怎么弄呢?

【问题讨论】:

尝试从 myFunction ***.com/questions/20548921/… 中的 req 访问服务器 启动服务器的代码在哪里?您显示的代码根本不会启动服务器。你的代码中应该有一个xxx.listen()。据我所知,您无法从 Express app 对象中获取服务器对象。它不知道服务器。但是您的 xxx.listen() 代码将知道服务器,因此您需要从那里获取它。 【参考方案1】:

据我所知,Express app 对象不知道服务器对象。在 Express 中的工作方式是,app 对象被提供给服务器对象,而不是相反。事实上,单个app 对象甚至可以与多个服务器一起使用(有时用于 http 和 https 服务器)。

您可以使用 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

【讨论】:

是的,这是我的观点。启动服务器的代码在其他地方,我的代码所做的只是添加一个路由器。我无法访问调用listen() 或调用createServer 的代码,所以我希望有一种方法可以从express 或其他地方获取它。第一条评论中链接的答案有帮助。 @GraemePerrow - 好吧,您可以在处理请求的过程中从 req 或 res 对象获取服务器,但这不是您所要求的。【参考方案2】:

调用app.listen() 时返回服务器。例如:

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

【讨论】:

【参考方案3】:

您可以编写一个简单的包装器来实例化或获取您的 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】:

你也可以使用下面的代码来完成同样的事情。

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

server.listen(80);

更多信息,我建议你参考this link

【讨论】:

我该如何做https?我的语法与您使用的相同,但 var server = require('https').Server(app);似乎没有办法。 首先,正如网络论坛和事实实践中的许多建议一样,从 Node 内置工具通过 HTTPS 加密通信并不是一个好主意,因为存在安全漏洞,因此将其投入生产。而是使用 nginx 之类的代理选项。您可以在许多帖子中了解更多信息。【参考方案5】:

我在使用带有 socket-io 的 wepack devServer 时遇到了这个问题,jfriend00 的评论帮助了我。我使用这个技巧:

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

【讨论】:

【参考方案6】:

看看expresslisten函数是如何实现的:

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

所以基本上你是否明确存储http服务器实例并不重要:

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

或者参考expresslisten的返回值:

var server = app.listen()

从技术上讲,您指的是同一件事,这在某种程度上令人困惑恕我直言...也许明确期望开发人员将 express 应用程序作为 http 服务器构造函数参数传递会更好,因为 app.listen() 基本上可以作为 http.Server(arguments) 的包装器

【讨论】:

以上是关于如何从 express 应用程序中获取 http.server?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 SQL Express 2012 获取数据更改通知?

express 无法从 url 获取查询参数 [重复]

如何在 express/node js 中发送错误 http 响应?

如何使用 Express 和 Apollo-Server 获取 HTTP 授权标头

使用 express-graphql 和 HTTP 客户端从 graphql 获取数据

如何在 MEAN 应用程序中的同一 HTTP 请求中调用多个方法