【问题标题】:node.js body on http request object vs body on express request objecthttp请求对象上的node.js主体与快速请求对象上的主体
【发布时间】:2014-01-25 13:18:20
【问题描述】:

我正在尝试构建一个可以与 express 服务器一起使用的 http 模块。

在阅读 http 模块 api 时,我看到它没有将正文保存在请求对象中。 所以我的问题是:

  1. 如果我想构建一个与官方http模块一起使用的express服务器,我应该如何获取body?
  2. 我考虑通过以下方式实现http module:监听socket,如果我得到content-length header,监听socket流的其余部分直到我得到所有的body,把它保存为一个成员http 请求,然后才将请求对象发送到快速服务器处理程序。

我上面的建议与让快递服务器通过 request.on('data',callback(data))“监听”请求正文的优缺点是什么

我的意思是,为什么我不应该像保留标题一样将正文保留在“请求”对象中?

【问题讨论】:

  • 请求正文 - 您的意思是 POST 数据吗?
  • 是的,例如。是的
  • 要获取body数据,需要自己解析请求body。你的做法是合理的,但是为什么不直接使用 express 提供的解析器呢?是什么阻止你这样做?

标签: node.js sockets http express


【解决方案1】:

你可以做到,这很简单。 bodyParser 中间件就是这样做的,例如 (https://github.com/expressjs/body-parser/blob/master/index.js#L27)。问题是,请求正文可能非常大(例如文件上传),因此您通常不希望将其放入内存中。相反,您可以将其流式传输到磁盘或 s3 或诸如此类。

【讨论】:

    【解决方案2】:

    如果不确切知道您想要做什么,就很难回答您的问题。但是我可以给你一些关于 Node/Express 如何处理请求正文的细节,希望你能从那里得到一些东西。

    在处理请求时(直接通过 Node 的请求处理程序,或通过 Express 的请求处理程序),不会自动接收请求的主体:您必须打开 HTTP 流才能接收它。

    body内容的类型应该由Content-Type请求头决定。两种最常见的身体类型是application/x-www-form-urlencodedmultipart/form-data。但是,您可以使用任何您想要的内容类型,这通常在 API 中更常见(例如,使用 application/json 在 REST API 中变得越来越普遍)。

    application/x-www-form-urlencoded 非常简单; name=value 对是 URL 编码的(例如,使用 JavaScript 的内置 encodeURIComponent),然后与与号 (&) 组合。它们通常采用 UTF-8 编码,但也可以在 Content-Type 中指定。

    multipart/form-data 更复杂,通常也可以很大,正如 vkurchatkin 的回答所指出的那样(这意味着您可能不想将其记入内存)。

    Express 提供了一些中间件来自动处理各种类型的正文解析。通常,人们只使用bodyParser,尽管你必须小心那个中间件。它实际上只是一个方便的中间件,结合了jsonurlencodedmultipart。但是,multipart 已被弃用。 Express 仍在捆绑 Connect 2.12,其中仍包括 multipart。但是,当 Express 更新其依赖项时,情况就会发生变化。

    在我撰写本文时,bodyParserjsonurlencodedmultipart 都已从 Connect 中删除。除了multipart 之外的所有内容都已移入模块body-parser (https://github.com/expressjs/body-parser)。如果您需要多部分支持,我推荐 Busboy (https://npmjs.org/package/busboy),它非常强大。在某个时候,Express 会更新它对 Connect 的依赖,并且很可能会向 body-parser 添加一个依赖,因为它已从 Connect 中删除。

    因此,由于 bodyParser 捆绑了不推荐使用的代码 (multipart),我建议仅显式链接 jsonurlencoded(如果您不接受任何 JSON 编码,您甚至可以省略 json机构):

    app.use(express.json());
    app.use(express.urlencoded());
    

    如果您正在编写中间件,您可能不想自动链接jsonurlencoded(更不用说 Busboy);这将打破 Express 的模块化特性。但是,您应该在文档中指定您的中间件需要 req.body 对象可用(如果不可用则正常失败):您可以继续说 jsonurlencoded 和 Busboy 都提供req.body 对象,具体取决于您需要接受的内容类型。

    如果您深入研究urlencodedjson 的源代码,您会发现它们依赖于另一个Node 模块raw-body,它只是打开请求流并检索正文内容。如果您确实需要了解从请求中检索正文的详细信息,您可以在该模块的源代码 (https://github.com/stream-utils/raw-body/blob/master/index.js) 中找到所需的一切。

    我知道这是很多细节,但它们是重要的细节!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-17
      • 2019-09-15
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多