我在 phoenix 上构建了 restful api (json)。而且我不需要html的支持。
如何覆盖凤凰中的错误?示例错误: - 500 - 404 未找到路由等。
我在 phoenix 上构建了 restful api (json)。而且我不需要html的支持。
如何覆盖凤凰中的错误?示例错误: - 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 中为您生成此文件。模板的默认内容可以在 Github上找到。
另请参阅有关自定义错误的文档,尽管它们似乎有点过时,因为它们指示您使用MyApp.ErrorsView
(复数),已替换为MyApp.ErrorView
上面的答案都不适合我。我能够让 phoenixjson
仅用于 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"]
您可以使用in覆盖 400-500 错误router.ex
。例如:
# 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
它会起作用。