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.
It wonât work. Optional parameters should not be matched in the head. You should handle them in the body. Name the second parameter and use âMap.getâ in the body, with a default value.
A general rule of thumb is that if something does not match the head of a function, it should fail fast. It is not something you expect, so donât handle it.
Why not just make a catch-all index function without pattern-matching and log its parameters? It seems some of your externally arriving data are unexpected.
I havenât said âfallbackâ, you did, and you have been told, it does not what you want, it can only be used to âfixâ return values that are not proper conns.
Therefore I am not sure what you are asking forâŠ
I would switch all your def to only pattern match on the absolute required values, which in this case is probably just def index(conn, params). But then inside the body of each function I would call a helper function that will describe the required parameters and pattern match on them, if that match fails, then the helper function can return a 400 error that describes the missing parameters.
IMO this is a huge smell that this is the wrong place for this logic - itâs in a common path for all actions in the controller, but needs specific behavior for each action.
What about extracting the internals of that to a plug and specifically inserting it for each action?
plug :required_fields, ["id", "from", "to", "etc"] when action == :index
plug :required_fields, ["something", "else"] when action == :action2