How to render errors/exceptions raised in router plugs based on the request's content-type

I’m learning Phoenix and developing a small app that serves both HTML and JSON content. I’m able to render the controller response based on the request. Everything works well except for any exceptions raised in router plugs, such as Phoenix.Router.NoRouteError or Plug.CSRFProtection.InvalidCSRFTokenError, which always return an HTML response.

I found out that I can use Plug.ErrorHandler in Router to solve my problem:

defmodule AppWeb.Router do
  use AppWeb, :router
  use Plug.ErrorHandler


@impl Plug.ErrorHandler
  def handle_errors(conn, %{kind: _kind, reason: _reason, stack: _stack}) do
    headers = Enum.into(conn.req_headers, %{})
    if headers["content-type"] == "application/json" do
      body = AppWeb.Error.ErrorJSON.render("#{conn.status}.json", %{})
      json(conn, body)
    else
      body = AppWeb.Error.ErrorHTML.render("#{conn.status}.html", %{})
      html(conn, body)
    end
end

Since I’m new to Phoenix, I’m not confident this is the only or best way to solve the the problem. Hence, my question is: How can I render errors/exceptions in router plugs based on the request’s content type?

Thanks,

Oops, my bad. Turns out my client was sending Accept: */* in the request header. After correcting the header, everything works without the need for Plug.ErrorHandler

1 Like