tanweerdev
Write Malformed JSON in the body Plug
I am trying to write a plug which will generate a custom error if the request has malformed JSON which is quite often the case in our scenarios(as we use variables in postman. eg sometimes there is no quote outside the value and it results in malformed JSON). The only help I got is https://groups.google.com/forum/#!topic/phoenix-talk/8F6upFh_lhc which isnt working of course.
defmodule PogioApi.Plug.PrepareParse do
import Plug.Conn
@env Application.get_env(:application_api, :env)
def init(opts) do
opts
end
def call(conn, opts) do
%{method: method} = conn
# TODO: check for PUT aswell
if method in ["POST"] and not(@env in [:test]) do
{:ok, body, _conn} = Plug.Conn.read_body(conn)
case Jason.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, Jason.encode!(error))
|> halt
end
else
conn
end
end
end
Marked As Solved
tanweerdev
in endpoint.ex file add a custom body reader and your custom plug in below order
plug Api.Plug.PrepareParse # should be called before Plug.Parsers
plug Plug.Parsers,
parsers: [:urlencoded, :multipart, :json],
pass: ["*/*"],
body_reader: {CacheBodyReader, :read_body, []}, # CacheBodyReader option is also needed
json_decoder: Phoenix.json_library()
Define a custom body reader
defmodule CacheBodyReader do
def read_body(conn, _opts) do
# Actual implementation
# {:ok, body, conn} = Plug.Conn.read_body(conn, opts)
# conn = update_in(conn.assigns[:raw_body], &[body | (&1 || [])])
# {:ok, body, conn}
{:ok, conn.assigns.raw_body, conn}
end
end
Then your custom parse prepare
defmodule Api.Plug.PrepareParse do
import Plug.Conn
@env Application.get_env(:application_api, :env)
@methods ~w(POST PUT PATCH)
def init(opts) do
opts
end
def call(conn, opts) do
%{method: method} = conn
if method in @methods and not (@env in [:test]) do
case Plug.Conn.read_body(conn, opts) do
{:error, :timeout} ->
raise Plug.TimeoutError
{:error, _} ->
raise Plug.BadRequestError
{:more, _, conn} ->
# raise Plug.PayloadTooLargeError, conn: conn, router: __MODULE__
error = %{message: "Payload too large error"}
render_error(conn, error)
{:ok, "" = body, conn} ->
update_in(conn.assigns[:raw_body], &[body | &1 || []])
{:ok, body, conn} ->
case Jason.decode(body) do
{:ok, _result} ->
update_in(conn.assigns[:raw_body], &[body | &1 || []])
{:error, _reason} ->
error = %{message: "Malformed JSON in the body"}
render_error(conn, error)
end
end
else
conn
end
end
def render_error(conn, error) do
conn
|> put_resp_header("content-type", "application/json; charset=utf-8")
|> send_resp(400, Jason.encode!(error))
|> halt
end
end
1
Also Liked
NobbZ
That will read the body, if it hasn’t been read before, eg by Plug.Parsers.
After you have read the body, you should put the parsed data somewhere in the conn, or it will be lost.
1
Popular in Questions
i’m a new one to elixir
which editor can i use
vs code? or atom?
Thanks! :smiley:
New
What is the idiomatic way of matching for not nil in Elixir?
E.g.,
First way:
defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Hi there,
I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
Hello!
Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”:
14:57:30.512 [warn] ...
New
Hello,
I am trying to convert my lists to string without losing brackets.For start i have 3 map. They look like these
buyer = %{
id: ...
New
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this
"1000"
What is the ...
New
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
Hi all,
I've just started learning Elixir and Phoenix Framework, so please pardon my n00bness at this stage.
I'm trying to use Postg...
New
Hey all,
I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
Other popular topics
Hi,
I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set?
Thanks.
New
Here are few pieces of (common) Linux knowledge that we use for reasonably small one server apps. We use Ubuntu but this should work for ...
New
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
I have a User schema with a :from_id field set to type :string:
defmodule TweetBot.Repo.Migrations.CreateUsers do
use Ecto.Migration
...
New
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Hi,
I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Hi guys, i’m new in the Elixir world, and i have to say, that i love it!
i’m having some problem to understand anonymous functions with ...
New
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including.
What is Phoenix LiveV...
New
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New







