簡體   English   中英

在Rails中異常后存儲響應HTTP狀態代碼

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM