Search code examples
elixirphoenix-frameworkplug

How do I make Plug.ErrorHandler and other Plug work at the same time?


I noticed that the response generated by send_resp in the handle_errors callback of Plug.ErrorHandler does not pass through other Plugs.

For example, I build a JSON response in handle_error. But this JSON response won't pass my JSONHeaderPlug and CORSPlug. This has brought a lot of trouble.

Specific symptoms such as the lack of these essential HTTP headers:

access-control-allow-credentials: true
access-control-allow-origin: *
access-control-expose-headers: 
content-type: application/json; charset=utf-8

Is there a way to let the response in handle_error pass through other Plugs in the same order as the normal response?


Solution

  • I don't know why this is the case (I thought all the plugs before the error will be applied, but I did reproduce your situation). Still you can put all the plugs in a module and call it yourself. Remember you should do as little as possible in the handle_errors callback, because one of the plugs might be the reason for the error.

    defmodule ApplySomePlug do
      use Plug.Builder
    
      plug(CORSPlug)
      plug(:put_custom_header)
    
      def put_custom_header(conn, _) do
        Plug.Conn.put_resp_header(conn, "foo", "bar")
      end
    end
    

    and to use it

    def handle_errors(conn, _) do
      opts = ApplySomePlug.init(nil)
      conn = ApplySomePlug.call(conn, opts)
    
      Phoenix.Controller.json(conn, %{error: "something bad happened"})
    end