Search code examples
elixirphoenix-framework

handling pattern match exceptions in phoenix elixir


I have multiple controller methods, where I am pattern matching with the coming parameters one of them is

  def index(conn, %{
        "id" => camera_exid,
        "from" => from,
        "to" => to,
        "limit" => "3600",
        "page" => _page
      }) do

when user requests such as http://localhost:4000/v2/cameras/pocri-yweod/recordings/snapshots?limit=3600&page=1

it throws an error, and of course, it supposes to through error, but is there any way to handle such error more gracefully than an exception? without creating another index with fewer values to pattern match?

I tried creating a fallback controller very basic

defmodule EvercamMediaWeb.FallbackController do
  use EvercamMediaWeb, :controller

  def call(conn, what) do
    IO.inspect(what)
    render_error(conn, 400, "error.")
  end
end

but it didn't work.

Is it possible to make it for the whole controller? when the pattern matched parameters doesn't match, it returns 400 while saying which params are missing? I am the only pattern matching those parameters in the head which are definite.


Solution

  • Yes, it's possible to make it for the whole controller, as phoenix injects an action/2 plug in controllers which -by default- calls the function matched from the router, and it can be overridden.

    try this in your controller:

      def action(conn, _) do
        required_fields = %{
          index: ["id", "from", "to", "limit", "page"],
          action2: ["id", "x", "y"]
        }
    
        args = [conn, conn.params]
    
        missing_fields =
          Enum.reject(required_fields[action_name(conn)], fn x -> x in Map.keys(conn.params) end)
    
        case missing_fields do
          [] ->
            apply(__MODULE__, action_name(conn), args)
    
          fields ->
            conn
            |> put_status(:bad_request)
            |> text("missing fields: " <> inspect(fields))
        end
      end
    

    you can render the way you like, in case missing_fields list is not empty.

    ps: returning error 400 is not an exception, it's a well handled error, as stated by Jose here https://github.com/phoenixframework/phoenix/issues/2386#issuecomment-315590839