首页 > 解决方案 > REST API 自定义 MatchError 处理优雅

问题描述

我正在 Elixir 中开发一个 REST API。我正在尝试设计一个系统,该系统允许我与要返回给客户端的自定义消息进行模式匹配失败。我正在使用插件。

假设我有一个用于在我的数据库中创建用户的端点,如果帐户已经存在,我可能会使以下语句失败:
0 = DbAdapter.select("SELECT * FROM users WHERE email = 'email@example.com';)

这失败了,MatchError并且 plugInternal server error向客户端返回了一个泛型。

我想做的是定义一些结构,如下所示:

0 = DbAdapter.select("...") << %{code: 1113, reason: "account already exists"}

基本上,如果断言0 = DbAdapter.select("...")失败,我想返回%{code: 1113, reason: "account already exists"}给客户端。我的目标是非常简单的语法,就像上面的语法(可能是运算符重载之类的)。

我的理解是 plug 处理错误的方法如下:

def handle_errors(conn, ree = %{kind: _kind, reason: _reason, stack: _stack}) do
    IO.inspect ree
    send_resp(conn, conn.status, "Internal error: The resource you're looking for might not exist on the server.")
end

如何在断言失败时获取自定义错误元组,并在 handle_errors 中将其返回给客户端?有没有一种干净的方法可以做到这一点?

标签: restapielixir

解决方案


handle_errors用于处理您的请求可能发生的错误,而不是根据操作结果返回的特殊状态。

您需要创建您的应用程序以返回有效数据或有意义的错误代码,它将从中为客户端生成适当的响应:

case DbAdapter.select("...") do
  0 -> create!
  _ -> %{code: 1113, reason: "account already exists"}
end

在其他地方,也许在另一个插件中:

case data do
  %{code: 1113, reason: reason} -> send_resp(conn, 418, reason)
  %{code: 200, data: data} -> send_resp(conn, 200, data)
end

推荐阅读