[英]Store response HTTP status code after exception in Rails
我正在Ruby on Rails中開發REST Web服務。
在每個請求之后,即使存在某些異常,我也希望將響應HTTP狀態代碼存儲在數據庫中。 我怎樣才能做到這一點?
我做了兩次嘗試都沒有成功:
應用程序控制器中的after_filter
class Api::ApiController < ActionController::Base before_action :set_current_rest_request after_filter :finalize_current_rest_request private def set_current_rest_request @current_rest_request = RestRequest.new @current_rest_request.request_at = DateTime.now @current_rest_request.save end def finalize_current_rest_request @current_rest_request.answer_at = DateTime.now @current_rest_request.http_status_code = response.status @current_rest_request.save end end
不起作用,因為在發生異常的情況下不會調用finalize_current_rest_request
應用控制器中的rescue_from
class Api::ApiController < ActionController::Base before_action :set_current_rest_request after_filter :finalize_current_rest_request rescue_from Exception, :with => :handle_exception private def set_current_rest_request @current_rest_request = RestRequest.new @current_rest_request.request_at = DateTime.now @current_rest_request.save end def finalize_current_rest_request @current_rest_request.answer_at = DateTime.now @current_rest_request.http_status_code = response.status @current_rest_request.save end def handle_exception(exception) finalize_current_rest_request raise exception end end
不起作用,因為在引發異常之前,我在handle_exception中調用finalize_current_rest_request時response.status仍為200
您需要使用begin搶救塊包裝控制器的每個動作。 就像是:
begin
respond_to do |format|
format.json { redirect_to foos_path, notice: 'Foo was successfully destroyed.' }
rescue
@current_rest_request.http_status_code = response.status
end
end
通常,這種行為取決於日志,但是我認為您確實有這樣做的充分理由。
如果您確實希望如前所述干燥,則可以放入應用程序控制器:
rescue_from Exception, :with => :store_request
def store_request
current_rest_request = RestRequest.new
current_rest_request.request_at = DateTime.now
current_rest_request.http_status_code = response.status
current_rest_request.save
end
注意:在應用程序控制器中進行搶救通常被認為是不好的做法。 我認為實際處理此問題的最佳方法是實施全面的日志記錄方案。
我終於解決了添加中間件的問題( 這里提供了一些關於Rails中間件如何工作的數據)。 詳細地,在config / application.rb中,我添加了:
config.middleware.insert_before "Rails::Rack::Logger","StoreStatus"
api控制器是
class Api::ApiController < ActionController::Base
before_action :set_current_rest_request
private
def set_current_rest_request
@current_rest_request = RestRequest.new
request.env[:current_rest_request] = @current_rest_request
end
end
我用以下代碼添加了文件lib / store_status.rb:
class StoreStatus
def initialize(app)
@app = app
end
def call(env)
data = @app.call(env)
if (env[:current_rest_request])
rest_request = env[:current_rest_request]
rest_request.http_status_code = data[0]
rest_request.save
end
data
end
end
請注意,可能會出現一些語法錯誤,因為已獲得該代碼的重構代碼,該代碼包含此問題的其他無用的復雜性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.