插件解析器:引发 ParseError

Plug Parser: raising ParseError

我正在编写一个插件解析器,除其他外,它使用 Poison 解码 JSON(我更愿意让 Plug.Parsers.JSON 这样做,但我需要阅读原始请求正文以验证它反对签名,所以这是不可能的。

如果解析过程中出现错误,我将使用 Poison.decode/2 to decode the json. This returns an {:error, ...} tuple on error. As a Plug parser, I think I am expected to raise Plug.Parsers.ParseError。但是 ParseError 需要一个 exception 结构。我没有其中之一,我只有从 Poison.decode/2.

返回的元组

作为解决方法,我可以使用 Poison.decode!/2rescue 引发的错误,将其重新引发为 ParseError,但是当不引发 decode/2可用。

所以我的问题是,越来越抽象:

  1. 如何在没有源异常的情况下从解析器中引发 ParseError
  2. 我需要提出 ParseError,还是提出我自己的异常更好?
  3. 是否有更好的方法,让我无需重新实现 JSON 解析即可验证签名?

How do I raise a ParseError from a parser without a source exception?

您需要自己创建 Plug.Parsers.ParseError

raise %Plug.Parsers.ParseError{exception: %MyException{message: "Failed to parse"}}

Do I need to raise the ParseError, or it it better to raise my own exception?

你可以提出你想要的任何东西,但因为它确实是 ParseError 我看不出有任何理由提出不同的东西。

Is there a better way altogether [...]

这个太自以为是了。 JSON 解析好像没问题

(I'd prefer to let Plug.Parsers.JSON do that, but I need to read the raw request body to verify it against a signature, so that's not possible).

...

  1. Is there a better way altogether, allowing me to verify the signature without re-implementing the JSON parsing?

Plug.Parsers.JSON这样做实际上是最好的选择。从版本 1.5.1 开始,可以为解析器提供一个 custom body reader 来缓存正文供以后使用。这是一个比重新实现 JSON-解析器插件更通用的解决方案。

这是我的习惯 reader:

def read_body(conn, opts) do
  case Plug.Conn.read_body(conn, opts) do
    {res, body, conn} when res in [:ok, :more] ->
      {res, body, update_in(conn.assigns[:raw_body], &((&1 || "") <> body))}

    unknown ->
      unknown
  end
end