在使用 Koa 进行 Web 开发时,我们经常会使用 bodyParser 中间件来解析请求体。但是有时候我们会遇到这样一个问题:使用 bodyParser 后无法正常读取请求体的数据。
问题的本质
首先我们来看看这个问题的本质:Koa 使用了 Node.js 的 http.IncomingMessage
类来处理请求,并将请求体存储在一个叫做 ctx.req
的变量中。但是 bodyParser 会在请求结束后通过 ctx.request.body
来访问请求体,而 ctx.request
实际上并没有被赋值。
这就导致了一个非常重要的问题:如果在 bodyParser 之前的中间件中有任何一个中间件修改了 ctx.req
,那么 bodyParser 就不能正确地获取请求体的数据了。
解决方案
为了解决这个问题,最简单的方法就是让 bodyParser 是第一个中间件。这样它就不会受到其他中间件的干扰了。但是如果我们需要在其它中间件中处理请求体,该如何解决呢?
一种解决方案是将 ctx.req
的数据存储到一个新的变量中,然后在之后的中间件中使用这个新的变量。我们可以使用一个名字叫做 rawBody
的新变量来存储请求体的数据:
-- -------------------- ---- ------- ----- --- - --------------- ----- ---------- - -------------------------- ----- --- - --- ------ ------------- ----- ----- -- - ----------- - ----- --- ----------------- ------- -- - --- --- - --- ---------------------------- ------------------ ------- -- - --- -- ------ --- ----------------- -- -- - ------------- --- ------------------- -------- --- ----- ------- --- ---------------------- ------------- ----- -- - ------------------------------ -- -------- ---
在上面的例子中,我们首先定义了一个新的中间件来处理请求。这个中间件会将请求体的数据读取到 ctx.rawBody
变量中。接着我们调用 next()
来将控制权转移到下一个中间件。在 bodyParser 中间件中,我们再次读取请求体的数据,并通过 ctx.request.body
来访问这个数据。
进一步优化
上面的方案已经可以解决问题了,但是它有一个显著的缺点:如果请求体太大,或者数据流过来的太慢,我们就需要等待整个请求体都被读取完毕才能处理它。这会导致响应时间变长,影响性能。
为了进一步优化,我们可以使用一个叫做 koa-body
的中间件,它可以将请求体读取到内存中,并且支持处理大文件。我们只需要在之后的中间件中通过 ctx.request.body
来访问请求体的数据即可。
-- -------------------- ---- ------- ----- --- - --------------- ----- ---- - -------------------- ----- --- - --- ------ ---------------- ------------- ----- -- - ------------------------------ -- -------- ---
总结
在使用 Koa 进行 Web 开发时,我们通常会使用 bodyParser 中间件来解析请求体的数据。但是有时候 bodyParser 无法正常读取请求体的数据,这是因为 Koa 使用了 http.IncomingMessage
类来处理请求,而 bodyParser 依赖于 ctx.request.body
来读取请求体的数据。
为了解决这个问题,我们可以将 bodyParser 放在第一个中间件,或者使用一个新的变量来存储请求体的数据。如果需要处理大文件,我们可以使用 koa-body
中间件来进一步优化。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/647b523e968c7c53b06d094b