我正在实施API端点。在我的控制器操作中,我想使用防护来验证param类型,如下所示:
def get_object(conn, %{"objectId" => object_id}) when is_binary(object_id) do
当客户端使用" objectId"来调用此端点时不是二元的,或没有" objectId"完全,凤凰提出Phoenix.ActionClauseError
。我想拯救此类异常,并返回自定义响应正文(例如{"message": "Invalid request body"}
)。我怎样才能做到这一点?我尝试使用Plug.ErrorHandler
,但它正在重新引发错误(如文档中所述)。
编辑:我发现了类似的问题(https://github.com/phoenixframework/phoenix/issues/2386),但我不想为每个控制器操作创建def get_object(conn, _params), do: :params_mismatch
,因为会有很多
答案 0 :(得分:1)
您为每个操作实现默认子句所发现的是最好的方法,无论它是否存在于所有操作中 - 它是明确的,易于推理,并且正如您所指出的那样,每个动作基本上只有一行代码。
您可以使用宏来删除样板,它可能类似于:
defaction get_object(conn, %{"objectId" => object_id}) do
...
end
这样的宏的实现不是我推荐的,但是对于有趣和游戏,一个简单的实现可能是这样的:
defmacro defaction(signature, do: body) do
{name, argc} =
case signature do
{:when, _, [{name, _, args} | _]} ->
{name, length(args)}
{name, _, args} ->
{name, length(args)}
end
argv = Enum.map(1..argc, fn _ -> quote do _ end end)
quote location: :keep do
def unquote(signature) do
unquote(body)
end
def unquote(name)(unquote_splicing(argv)) do
:params_mismatch
end
end
end
然后您可以定义如下操作:
defaction get_object(conn, %{"objectId" => object_id}) do
...
end
或:
defaction get_object(conn, %{"objectId" => object_id}) when is_binary(object_id) do
...
end
我想提醒您不要使用这种方法,因为它会掩盖错误处理,这可以通过查看宏定义来看到,但也可以使代码的局部推理更加困难。