当用户尝试访问不存在的API路由时,会遇到Phoenix的问题。Phoenix似乎希望在默认情况下呈现"404.html“,这会导致调用catch all render函数(该函数返回一个地图),然后导致错误,因为Phoenix试图将JSON呈现为HTML。
** (UndefinedFunctionError) function Phoenix.HTML.Safe.to_iodata/1 is undefined (module Phoenix.HTML.Safe is not available)
Phoenix.HTML.Safe.to_iodata(%{error: %{errors: ["An internal error has occurred. Our team has been notified."], message: "Internal Error"}})
(phoenix) lib/phoenix/controller.ex:729: Phoenix.Controller.__put_render__/5
(phoenix) lib/phoenix/endpoint/render_errors.ex:77: Phoenix.Endpoint.RenderErrors.instrument_render_and_send/5
(phoenix) lib/phoenix/endpoint/render_errors.ex:62: Phoenix.Endpoint.RenderErrors.__catch__/5
(phoenix) lib/phoenix/endpoint/cowboy2_handler.ex:42: Phoenix.Endpoint.Cowboy2Handler.init/4这是最终要调用的默认呈现函数:
def render(code, _assigns) do
Logger.error("Error handler requested #{inspect code}. Please add support for that.")
%{
error: %{
message: "Internal Error",
errors: ["An internal error has occurred. Out team has been notified."]
}
}
end我见过前一个问题中的"set_format“解决方案(这里:https://stackoverflow.com/a/39189452),正如用户所说,这确实感觉有点老生常谈,尽管它看起来确实有效。
我还意识到,我可以只指定一个接受404.html的呈现函数,但这感觉也比我想要的更像是一个创可贴。
我的最终目标是让Phoenix不想呈现404.html,相反,我想随意指定模板,或者至少告诉Phoenix它应该寻找404.json。理想情况下,解决方案应该是应用程序范围的。
发布于 2020-02-26 00:01:24
您的路由器只是一个插头。您可以使用与Plug.Router或任何插件相同的方式处理错误。在下面的示例代码中,可以随意将MyAppWeb替换为您的web模块的名称。
defmodule MyAppWeb.Router do
use MyAppWeb, :router
use Plug.ErrorHandler #<-- Add this line
# and implement the callback handle_errors/2
defp handle_errors(conn, %{reason: %Phoenix.Router.NoRouteError{message: message}}) do
conn |> json(%{error: message}) |> halt()
end
defp handle_errors(conn, _) do
conn |> json(%{error: "unknown"}) |> halt()
end
...
end请注意,您可以调用控制器可用的所有函数,因为Phoenix.Controller是在import MyAppWeb, :router时导入的。您可以在模块MyAppWeb的源代码中看到这一点,请注意宏__using__/1和函数router/0。
发布于 2020-07-10 19:25:47
您应该将您的端点配置为将错误呈现为json:
config :the_app, TheApp.Endpoint,
render_errors: [view: TheApp.ErrorView, accepts: ~w(json), layout: false]https://stackoverflow.com/questions/60385212
复制相似问题