【发布时间】:2018-12-31 06:38:25
【问题描述】:
我在 phoenix 上构建了 restful api (json)。而且我不需要html的支持。
如何覆盖 phoenix 中的错误?示例错误: - 500 - 404 找不到路线 和其他。
【问题讨论】:
我在 phoenix 上构建了 restful api (json)。而且我不需要html的支持。
如何覆盖 phoenix 中的错误?示例错误: - 500 - 404 找不到路线 和其他。
【问题讨论】:
对于那些可能遇到与我相同的问题的人,需要几个步骤来为 404 和 500 响应呈现 JSON。
首先将render("404.json", _assigns) 和render("500.json", _assigns) 添加到您应用的web/views/error_view.ex 文件中。
例如:
defmodule MyApp.ErrorView do
use MyApp.Web, :view
def render("404.json", _assigns) do
%{errors: %{message: "Not Found"}}
end
def render("500.json", _assigns) do
%{errors: %{message: "Server Error"}}
end
end
然后在您的config/config.exs 文件中将default_format 更新为"json"。
config :my_app, MyApp.Endpoint,
render_errors: [default_format: "json"]
请注意,如果您的应用程序是纯粹的 REST api,这很好,但如果您还呈现 HTML 响应,则要小心,因为现在默认错误将呈现为 json。
【讨论】:
您需要自定义MyApp.ErrorView。 Phoenix 在 web/views/error_view.ex 中为您生成此文件。模板的默认内容可以在on Github找到。
另请参阅 the docs on custom errors,尽管它们似乎有点过时,因为它们指示您使用 MyApp.ErrorsView(复数),已替换为 MyApp.ErrorView
【讨论】:
plug :accepts, ... 从路由器移动到端点,它可能会起作用。否则请等待新的 Phoenix 版本。
以上答案都不适合我。
我能够让 phoenix 仅将 json 用于 api 端点的唯一方法是以这种方式编辑端点设置:
config :app, App.Endpoint,
render_errors: [
view: App.ErrorView,
accepts: ~w(json html) # json has to be in before html otherwise only html will be used
]
json 的想法必须是要呈现 html 的世界列表中的第一个,这有点奇怪,但它确实有效。
然后有一个看起来像这样的 ErrorView:
defmodule App.ErrorView do
use App, :view
def render("400.json", _assigns) do
%{errors: %{message: "Bad request"}}
end
def render("404.json", _assigns) do
%{errors: %{message: "Not Found"}}
end
def render("500.json", _assigns) do
%{errors: %{message: "Server Error"}}
end
end
与此处的其他答案没有什么不同,我只是添加了一个 400 错误请求,因为我遇到了它,您也应该:添加您可能遇到的任何内容。
最后在我的路由器代码中:
pipeline :api do
plug(:accepts, ["json"])
end
pipeline :browser do
plug(:accepts, ["html"])
...
end
与其他答案没有什么不同,但您必须确保您的管道配置正确。
【讨论】:
您可以用plug :accepts, ["json"] 覆盖router.ex 中的400-500 错误。例如:
# config/config.exs
...
config :app, App.endpoint,
...
render_errors: [accepts: ~w(html json)],
...
# web/views/error_view.ex
defmodule App.ErrorView do
use App.Web, :view
def render("404.json", _assigns) do
%{errors: %{message: "Not Found"}}
end
def render("500.json", _assigns) do
%{errors: %{message: "Server Error"}}
end
end
# in router.ex
defmodule App.Router do
use App.Web, :router
pipeline :api do
plug :accepts, ["json"]
end
pipe_through :api
# put here your routes
post '/foo/bar'...
# or in scope:
scope '/foo' do
pipe_through :api
get 'bar' ...
end
它会起作用的。
【讨论】: