🦔

特定パス以下のActionController::RoutingErrorでJSONを返却する

2020/09/24に公開約1,600字

環境

Ruby 2.5.7
Rails 5.2 (ActionPack 5.2)

コード

module YourNameSpace::Middleware
  class RoutingErrorResponseJson
    RESPONSE_JSON_PATHS = %w[/api/v1]

    def initialize(app)
      @app = app
    end

    def call(env)
      request = ActionDispatch::Request.new(env)
      status, headers, response = @app.call(env)
      # NOTE: ActionController::RoutingError時に設定されるパラメータ
      # See https://github.com/rails/rails/blob/5-2-stable/actionpack/lib/action_dispatch/journey/router.rb#L64
      if enable?(request) && status == 404 && headers['X-Cascade'] == 'pass'
        status, headers, response = pass_response(status)
      end 

      [status, headers, response]
    rescue Exception => exception # rubocop:disable Lint/RescueException
      raise exception
    end

    private

    def pass_response(status)
      [
        status,
        { "Content-Type" => "application/json" },
        [
          JSON.generate(
            {
              title: 'Routing Error',
              detail: 'No route matches',
              invalid_params: []
            }
          )
        ]
      ]
    end

    def enable?(request)
      RESPONSE_JSON_PATHS.any? { |path| request.path.to_s.start_with?(path) }
    end
  end
end
require_relative "../../lib/middleware/routing_error_response_json"
::Rails.application.config.middleware.use YourNameSpace::Middleware::RoutingErrorResponseJson

実現できる事

↑の例であれば /api/v1 以下へのリクエストでRoutingErrorとなった場合にJSONを返却する事ができる。
WebとApiが同居しているアプリケーションなどで利用価値があるかもしれない。

Discussion

ログインするとコメントできます