--I want to introduce Request and Response Validation in the committee to add API for public release to Rails project. --If you put it as middleware of Rack, it will affect the existing processing.
Add committee to Gemfile and bundle install
.
gem 'committee'
All you have to do now is create a class to use the committee and call it from the Controller.
lib/public_api/committee_validator.rb
module PublicApi
class CommitteeValidator
attr_reader :request_object
def initialize(request_object)
@request_object = request_object
end
def committee_options
{
schema_path: Rails.root.join('schema', 'swagger.yml').to_s,
prefix: '/public_api/v1'
}
end
def validate_request!
unless schema_validator.link_exist?
request = "`#{request_object.request_method} #{request_object.path_info}` undefined in schema."
raise Committee::InvalidRequest.new(request)
end
schema_validator.request_validate(request_object)
end
def validate_response!(status, headers, body)
schema_validator.response_validate(status, headers, [body], true) if validate_response?(status)
end
def validate_response?(status)
Committee::Middleware::ResponseValidation.validate?(status, committee_options.fetch(:validate_success_only, false))
end
def schema
@schema ||= Committee::Middleware::Base.get_schema(committee_options)
end
def router
@router ||= schema.build_router(committee_options)
end
def schema_validator
@schema_validator ||= router.build_schema_validator(request_object)
end
end
end
app/controllers/public_api/v1/base_controller.rb
module PublicApi
module V1
class BaseController < ApplicationController
before_action :validate_request
after_action :validate_response
private
def committee_validator
@committee_validator ||= ::PublicApi::CommitteeValidator.new(request)
end
def validate_request
committee_validator.validate_request!
rescue Committee::InvalidRequest => e
# render_bad_request
end
def validate_response
committee_validator.validate_response!(response.status, response.headers, response.body)
rescue StandardError => e
Rails.logger.error("#{e.class}: #{ex.message}\n#{ex.backtrace.join("\n")}")
end
end
end
After that, rescue it nicely and change the process according to the specifications. With this kind of feeling, you can introduce it while suppressing the influence on the outside of Public Api!