我在Rails应用程序中有一个普通的HTML前端和一个JSON API。现在,如果有人调用/api/not_existent_method.json
它,它将返回默认的HTML 404页面。有什么办法可以将其更改为类似的内容,{"error": "not_found"}
同时保留HTML前端的原始404页面?
Answers:
一位朋友向我指出了一种优雅的解决方案,该解决方案不仅可以处理404错误,还可以处理500个错误。实际上,它可以处理所有错误。关键在于,每个错误都会生成一个异常,该异常会向上传播到整个机架中间件,直到它们中的一个被处理为止。如果您想了解更多信息,可以观看此出色的截屏视频。Rails拥有自己的异常处理程序,但是您可以通过较少记录的exceptions_app
config选项覆盖它们。现在,您可以编写自己的中间件,也可以将错误路由回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
我喜欢创建一个单独的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
api/non_existant_route
?
rescue_from ActiveRecord::RecordNotFound, with: not_found
必须是,with: :not_found
但只能是一个字符编辑:P
当然,它将看起来像这样:
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版本和所需的确切行为而异。用Google搜索很容易找到。
rescue_from
文档。