I’m trying to build a REST API using Phoenix for the first time, and I just want to customize the error view to make them all render a JSON in the browser.
By default, the ErrorView
module has a template_not_found
callback which returns the status message.I followed the example from elixir-phoenix-realworld-example-app, and here is my error_view.ex
:
defmodule DictletWeb.ErrorView do
use DictletWeb, :view
def render("404.json", _assigns) do
%{
"error" => %{
"code" => 404,
"msg" => "Page Not Found"
}
}
end
def render("500.json", _assigns) do
%{
"error" => %{
"code" => 500,
"msg" => "Internal Error"
}
}
end
def template_not_found(_template, assigns) do
render("404.json", assigns)
end
end
I have set debug_errors: false
in the config, but when I visit non-existent route in the browser, I get errors below:
[info] GET /random_path
[debug] Converted error Phoenix.Router.NoRouteError to 404 response
[error] #PID<0.758.0> running DictletWeb.Endpoint (connection #PID<0.735.0>, stream id 2) terminated
Server: localhost:4000 (http)
Request: GET /random_path
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Phoenix.HTML.Safe not implemented for %{"error" => %{"code" => 404, "msg" => "Page Not Found"}} of type Map. This protocol is implemented for the following type(s): Phoenix.LiveView.Comprehension, Phoenix.LiveView.Component, Phoenix.LiveView.Rendered, Phoenix.LiveComponent.CID, Float, Date, Time, NaiveDateTime, Tuple, List, Phoenix.HTML.Form, BitString, DateTime, Integer, Atom
(phoenix_html 2.14.3) lib/phoenix_html/safe.ex:1: Phoenix.HTML.Safe.impl_for!/1
(phoenix_html 2.14.3) lib/phoenix_html/safe.ex:15: Phoenix.HTML.Safe.to_iodata/1
(phoenix 1.5.12) lib/phoenix/controller.ex:777: Phoenix.Controller.render_and_send/4
(phoenix 1.5.12) lib/phoenix/endpoint/render_errors.ex:78: Phoenix.Endpoint.RenderErrors.instrument_render_and_send/5
(phoenix 1.5.12) lib/phoenix/endpoint/render_errors.ex:64: Phoenix.Endpoint.RenderErrors.__catch__/5
(phoenix 1.5.12) lib/phoenix/endpoint/cowboy2_handler.ex:65: Phoenix.Endpoint.Cowboy2Handler.init/4
(cowboy 2.9.0) /home/tunkshif/Documents/Project/dictlet/deps/cowboy/src/cowboy_handler.erl:37: :cowboy_handler.execute/2
(cowboy 2.9.0) /home/tunkshif/Documents/Project/dictlet/deps/cowboy/src/cowboy_stream_h.erl:306: :cowboy_stream_h.execute/3
(cowboy 2.9.0) /home/tunkshif/Documents/Project/dictlet/deps/cowboy/src/cowboy_stream_h.erl:295: :cowboy_stream_h.request_process/3
(stdlib 3.15) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
It seems that the map returned from render("404.json", _assigns)
was treated as HTML, but I want it to be rendered as JSON in the browser. So how can I fix this?