How to cchange the default error when parsing request body failed

56 views
Skip to first unread message

stefan....@securitytrails.com

unread,
Jan 17, 2018, 11:12:58 PM1/17/18
to phoenix-talk
Greetings. I really enjoyed learning and working in Phoenix framework so far. It's proven to be a great tool with amazing code patterns and code readability.
Anyway, regarding my problem. I have an issue regarding default responses. So when JSON body parsing fails, in development, a message is returned with text "Malformed JSON body", however, in production,
only 400 is returned from the server. I'd like to be able to customize this behaviour, and return a custom json. Let's say a json like this: %{message: "Some message when parsing failed"}

I was partially able to achieve this by making a custom Plug, but the actual plug seems very hackish, because in order for it to work I had to disable it in the testing environment.


Here's what I did:

# File /plugs/prepare_parse.ex
defmodule
ApplicationApi.Plug.PrepareParse do
 
@moduledoc """
  A Plug used to 'prepareParse'. Phoenix doesn't send a nice error message when the body json
  has invalid attributes. This plug solves just that, if the request body is malformed,
  a more well-formatted message is returned from the server
  """

 
import Plug.Conn
 
@env Application.get_env(:application_api, :env)

 
@doc """
  Overrides the Plug.init/1 method
  """

 
def init(opts) do
    opts
 
end

 
@doc """
  Overrides the Plug.call/2 method
  """

 
def call(conn, opts) do
   
%{method: method} = conn
   
# TODO: check for PUT aswell
   
if method in ["POST"] and not(@env in [:test]) do
      decoder
= Keyword.get(opts, :json_decoder)
     
{:ok, body, _conn} = Plug.Conn.read_body(conn)
     
case decoder.decode(body) do
       
{:ok, _result} -> conn
       
{:error, _reason} ->
          error
= %{message: "Malformed JSON in the body"}
          conn
         
|> put_resp_header("content-type", "application/json; charset=utf-8")
         
|> send_resp(400, Poison.encode!(error))
         
|> halt
     
end
   
else
      conn
   
end
 
end
end

# ...
# File endpoint.ex
 
# HACK: This plug is used to send out a nice error message
 
# when a json body contains syntax errors
 
# !!IMPORTANT This is NOT BEING tested in the :test environment!
  plug
SecuritytrailsApiWeb.Plug.PrepareParse, json_decoder: Poison
# ....


Could there be a better way to achieve something like this that I'm not seeing?
Thanks in advance, happy codding!

OvermindDL1

unread,
Jan 18, 2018, 10:08:57 AM1/18/18
to phoenix-talk
This mailing list is deprecated (I think?), so it's best to ask at https://elixirforum.com/ overall.  :-)

However, as I recall I 'think' the spec says it should return some kind of formatted error on 400, but you can of course override it to return json instead by returning, well, whatever you want from your 400 error handler in the error_view.ex file.  :-)

Do note that in development the system hooks errors like that to return debuggable errors, but that is disableable on certain routes as well, it's documented someone on the above elixir forum.  :-)
Reply all
Reply to author
Forward
0 new messages