saa
saa

Reputation: 255

How to override errors in phoenix?

I build restful api (json) on phoenix. And I did not need the support of html.

How to override errors in phoenix? Example errors: - 500 - 404 when no route found and other.

Upvotes: 10

Views: 3696

Answers (4)

Patrick Oscity
Patrick Oscity

Reputation: 54734

You need to customize MyApp.ErrorView. Phoenix generates this file for you in web/views/error_view.ex. The default content of the template can be found on Github.

Also see the docs on custom errors, although they seem to be a bit outdated because they instruct you to use MyApp.ErrorsView (plural), which was replaced with MyApp.ErrorView

Upvotes: 4

Edouard Menayde
Edouard Menayde

Reputation: 307

None of the answer above worked for me. The only way i was able to make phoenix use json only for the api endpoint was to edit the endpoint settings this way :

config :app, App.Endpoint,
       render_errors: [
         view: App.ErrorView,
         accepts: ~w(json html) # json has to be in before html otherwise only html will be used
       ]

The idea being json has to be the first of the world list for html to be rendered, kinda weird but it works.

Then have an ErrorView which looks like this :

defmodule App.ErrorView do
  use App, :view

  def render("400.json", _assigns) do
    %{errors: %{message: "Bad request"}}
  end

  def render("404.json", _assigns) do
    %{errors: %{message: "Not Found"}}
  end

  def render("500.json", _assigns) do
    %{errors: %{message: "Server Error"}}
  end
end

Nothing different from the other answer here, I just added a 400 bad request because I ran into it and you should too : add anything that you might run into.

And finally in my router code:

pipeline :api do
  plug(:accepts, ["json"])
end
pipeline :browser do
  plug(:accepts, ["html"])
  ...
end

Nothing different from the other answer but you have to make sure your pipelines are configured correctly.

Upvotes: 1

S. Alekseenko
S. Alekseenko

Reputation: 109

You can override 400-500 errors with plug :accepts, ["json"] in you router.ex. For example:

# config/config.exs
...
config :app, App.endpoint,
  ...
  render_errors: [accepts: ~w(html json)],
  ...    

# web/views/error_view.ex
defmodule App.ErrorView do
 use App.Web, :view

 def render("404.json", _assigns) do
   %{errors: %{message: "Not Found"}}
 end

 def render("500.json", _assigns) do
   %{errors: %{message: "Server Error"}}
 end
end


# in router.ex
defmodule App.Router do
 use App.Web, :router

 pipeline :api do
   plug :accepts, ["json"]
 end

 pipe_through :api

 # put here your routes
 post '/foo/bar'...

 # or in scope: 
 scope '/foo' do
   pipe_through :api
   get 'bar' ...
 end

It will works.

Upvotes: 0

stephenmuss
stephenmuss

Reputation: 2445

For those who may have the same issues I had, there a couple of steps required to render JSON for 404 and 500 responses.

Firstly add render("404.json", _assigns) and render("500.json", _assigns) to your app's web/views/error_view.ex file.

For example:

defmodule MyApp.ErrorView do
  use MyApp.Web, :view

  def render("404.json", _assigns) do
    %{errors: %{message: "Not Found"}}
  end

  def render("500.json", _assigns) do
    %{errors: %{message: "Server Error"}}
  end
end

Then in your config/config.exs file updated the default_format to "json".

config :my_app, MyApp.Endpoint,
  render_errors: [default_format: "json"]

Note that if your app is purely a REST api this will be fine, but be careful in the event you also render HTML responses as now by default errors will be rendered as json.

Upvotes: 8

Related Questions