Reputation: 2598
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.
Upvotes: 3
Views: 688
Reputation: 111
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
Upvotes: 2