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 Redirecting to Google Groups 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
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
How to handle excepions in elixir?
Suppose i have A, B, C ,D, E modules. and each module has get() function.
A.get() method will call t...
New
The Elixir Typespec docs show the following syntax for keyword lists in typespecs:
# ...
| [key: type] # keyword lists...
New
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
In Ruby, I can go:
User.find_by(email: "foobar@email.com").update(email: "hello@email.com")
How can I do something similar in Elixir?
...
New
In templates/appointment/index.html.eex:
<%= for appointment <- @appointments do %>
<tr>
<td><%= appoi...
New
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Credo is smart enough to check for (something like) this:
assert length(the_list) == 0
with this response:
Checking if an enum is empt...
New
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this:
...
New
Other popular topics
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition)
It’s been a while since we first asked this, I...
New
I have an umbrella app.
Some of the apps inside depend on other apps in the umbrella, unsurprisingly.
I’m writing a test for one of the...
New
I would like to know what is the best IDE for elixir development?
New
Hi everyone!
I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help.
Where are they similar?
Where do they differ the m...
New
Hello!
tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability.
After spen...
New
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
New
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









