我的 Rails 应用程序中有一个普通的 HTML 前端和一个 JSON API。现在,如果有人调用/api/not_existent_method.json
它,它将返回默认的 HTML 404 页面。有什么方法可以将其更改为类似的内容{"error": "not_found"}
,同时保留 HTML 前端的原始 404 页面?
问问题
48983 次
4 回答
117
一位朋友向我指出了一个优雅的解决方案,它不仅可以处理 404 错误,还可以处理 500 个错误。事实上,它处理每一个错误。关键是,每个错误都会产生一个异常,该异常会通过机架中间件堆栈向上传播,直到由其中一个处理。如果您有兴趣了解更多信息,可以观看此出色的截屏视频。Rails 有自己的异常处理程序,但您可以通过较少记录的exceptions_app
配置选项覆盖它们。现在,您可以编写自己的中间件,也可以将错误路由回 Rails,如下所示:
# In your config/application.rb
config.exceptions_app = self.routes
然后你只需要在你的匹配这些路线config/routes.rb
:
get "/404" => "errors#not_found"
get "/500" => "errors#exception"
然后你只需创建一个控制器来处理它。
class ErrorsController < ActionController::Base
def not_found
if env["REQUEST_PATH"] =~ /^\/api/
render :json => {:error => "not-found"}.to_json, :status => 404
else
render :text => "404 Not found", :status => 404 # You can render your own template here
end
end
def exception
if env["REQUEST_PATH"] =~ /^\/api/
render :json => {:error => "internal-server-error"}.to_json, :status => 500
else
render :text => "500 Internal Server Error", :status => 500 # You can render your own template here
end
end
end
最后要补充一点:在开发环境中,rails 通常不会渲染 404 或 500 页,而是打印回溯。如果您想ErrorsController
在开发模式下查看您的实际操作,请禁用config/enviroments/development.rb
文件中的回溯内容。
config.consider_all_requests_local = false
于 2012-04-21T08:37:07.517 回答
17
我喜欢创建一个单独的 API 控制器来设置格式(json)和特定于 api 的方法:
class ApiController < ApplicationController
respond_to :json
rescue_from ActiveRecord::RecordNotFound, with: :not_found
# Use Mongoid::Errors::DocumentNotFound with mongoid
def not_found
respond_with '{"error": "not_found"}', status: :not_found
end
end
RSpec 测试:
it 'should return 404' do
get "/api/route/specific/to/your/app/", format: :json
expect(response.status).to eq(404)
end
于 2014-06-27T11:53:26.230 回答
11
当然,它看起来像这样:
class ApplicationController < ActionController::Base
rescue_from NotFoundException, :with => :not_found
...
def not_found
respond_to do |format|
format.html { render :file => File.join(Rails.root, 'public', '404.html') }
format.json { render :text => '{"error": "not_found"}' }
end
end
end
NotFoundException
不是真名的例外。它会因 Rails 版本和您想要的确切行为而异。用谷歌搜索很容易找到。
于 2012-04-20T21:32:27.123 回答
6
尝试放在你的末尾routes.rb
:
match '*foo', :format => true, :constraints => {:format => :json}, :to => lambda {|env| [404, {}, ['{"error": "not_found"}']] }
于 2012-04-20T21:48:33.633 回答