4

我正在努力解决一个问题,即在 Plug.Parsers.JSON 将其放入管道之前,某些东西正在读取 http 请求的正文。正因为如此,json 插件中的 read_body 超时——你不能两次读取正文。

我们在管道的早期插件中有一个 HMAC 实现,在某些情况下它会读取主体。是否有关于如何使用主体在 Plug 中表现的模式?我的意思是,如果我们只能读取一次,并且必须在 Plug.Parsers.JSON 中对其进行解码,那么......它不会工作。

关注问题。生成 HMAC 哈希时是否需要包含请求正文?我的意思是,我觉得我们必须这样做,但我认为自己在这一点上是一个圆圈。

谢谢!

4

1 回答 1

3

您可以将自定义:body_reader选项传递Plug.Parsers给以缓存正文以供以后使用。

您不希望在解析器之前读取正文,而是缓存正文以便稍后从您想要散列它的插件中读取。

选项

:body_reader- 一个可选的替换(或包装器), Plug.Conn.read_body/2 用于提供一个函数,在解析和丢弃之前访问原始主体。它采用{Module, :function, [args]}(MFA) 的标准格式,默认为 {Plug.Conn, :read_body, []}.

示例

有时您可能想要自定义解析器如何从连接中读取正文。例如,您可能希望缓存正文以稍后执行验证,例如 HTTP 签名验证。这可以通过自定义正文阅读器来实现,该阅读器将读取正文并将其存储在连接中,例如:

defmodule CacheBodyReader do
  def read_body(conn, opts) do
    {:ok, body, conn} = Plug.Conn.read_body(conn, opts)
    conn = update_in(conn.assigns[:raw_body], &[body | (&1 || [])])
    {:ok, body, conn}
  end
end

然后可以将其设置为:

plug Plug.Parsers,
  parsers: [:urlencoded, :json],
  pass: ["text/*"],
  body_reader: {CacheBodyReader, :read_body, []},
  json_decoder: Jason

它是在Plug v1.5.1中添加的。

于 2018-07-30T05:46:06.127 回答