I'm writing a Plug Parser that among other things decodes JSON using Poison (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).
I'm using 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
if there was an error during the parsing. However ParseError
expects an exception
struct. I don't have one of those, I only have the tuple returned from Poison.decode/2
.
As a workaround, I can use use Poison.decode!/2
and rescue
the raised error, re-raising it as a ParseError
, but that seems weird when the non-raising decode/2
is available.
So my questions are, in increasing abstractness:
ParseError
from a parser without a source exception?ParseError
, or it it better to raise my own exception?(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).
...
- Is there a better way altogether, allowing me to verify the signature without re-implementing the JSON parsing?
Letting Plug.Parsers.JSON
do that is in fact the best option. Since version 1.5.1 it's possible to provide a custom body reader to the parser that can cache the body for later use. This is a much more generic solution than re-implementing a JSON-parser plug.
Here is my custom 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