diff --git a/lib/rack/filter_param.rb b/lib/rack/filter_param.rb index c6f9180..0828705 100644 --- a/lib/rack/filter_param.rb +++ b/lib/rack/filter_param.rb @@ -1,86 +1,14 @@ -require "rack/filter_param/version" +require 'rack/filter_param/version' +require 'rack/filter_param/middleware' +require 'rack/filter_param/filter' +require 'rack/filter_param/apply_filter' module Rack - class FilterParam + module FilterParam ACTION_DISPATCH_KEY = 'action_dispatch.request.request_parameters'.freeze FILTERED_PARAMS_KEY = 'rack.filtered_params'.freeze - def initialize(app, *params) - @app = app - @params = params.flatten - end - - def call(env) - @request = Rack::Request.new(env) - @params.each { |param| process_param(param) } - - @app.call(env) - end - - private - - attr_reader :request - - def process_param(param) - return unless path_matches?(param) - return unless param_exists?(param) - return unless affirmative_conditional?(param) - - param = param[:param] if param.is_a?(Hash) - - if delete_from_action_dispatch(param) || delete_from_request(param) - filtered_params << [ param.to_s, nil ] - end - end - - def path_matches?(param) - return true unless param.is_a?(Hash) - - path = param[:path] - return true unless path = param[:path] - - return request.env['PATH_INFO'] == path if path.is_a?(String) - return request.env['PATH_INFO'] =~ path if path.is_a?(Regexp) - - false - end - - def param_exists?(param) - param = param.is_a?(Hash) ? param[:param] : param - params.has_key?(param.to_s) - end - - def params - action_dispatch_parsed? ? action_dispatch_params : request.params - end - - def affirmative_conditional?(param) - return true unless param.is_a?(Hash) - - callable, param = param[:if], param[:param] - return true if callable.nil? - - callable.call(params[param.to_s]) - end - - def delete_from_action_dispatch(param) - action_dispatch_parsed? && !!action_dispatch_params.delete(param.to_s) - end - - def delete_from_request(param) - !!request.delete_param(param.to_s) - end - - def action_dispatch_params - request.env[ACTION_DISPATCH_KEY] - end - - def action_dispatch_parsed? - !action_dispatch_params.nil? - end - - def filtered_params - request.env[FILTERED_PARAMS_KEY] ||= [] - end + extend SingleForwardable + def_delegators :'Rack::FilterParam::Middleware', :new end end diff --git a/lib/rack/filter_param/apply_filter.rb b/lib/rack/filter_param/apply_filter.rb new file mode 100644 index 0000000..0d3f34b --- /dev/null +++ b/lib/rack/filter_param/apply_filter.rb @@ -0,0 +1,73 @@ +module Rack + class ApplyFilter + extend Forwardable + + def initialize(filter, request) + @filter = filter + @request = request + end + + def call + return unless param_exists? + return unless path_matches? + return unless if_proc_affirmative? + + if delete_from_action_dispatch || delete_from_request + filtered_params << [ param, nil ] + end + end + + private + attr_reader :filter, :request + + def_delegators :@filter, :param, :path, :if_proc + def_delegators :@request, :env + + def params + action_dispatch_parsed? ? action_dispatch_params : request.params + end + + def param_exists? + params.has_key?(param) + end + + def param_value + params[param] + end + + def action_dispatch_params + env[FilterParam::ACTION_DISPATCH_KEY] + end + + def action_dispatch_parsed? + !action_dispatch_params.nil? + end + + def path_matches? + return true if path.nil? + + return env['PATH_INFO'] == path if path.is_a?(String) + return env['PATH_INFO'] =~ path if path.is_a?(Regexp) + + false + end + + def if_proc_affirmative? + return true if if_proc.nil? + + if_proc.call(param_value) + end + + def delete_from_action_dispatch + action_dispatch_parsed? && !!action_dispatch_params.delete(param) + end + + def delete_from_request + !!request.delete_param(param) + end + + def filtered_params + env[FilterParam::FILTERED_PARAMS_KEY] ||= [] + end + end +end diff --git a/lib/rack/filter_param/filter.rb b/lib/rack/filter_param/filter.rb new file mode 100644 index 0000000..7d43c32 --- /dev/null +++ b/lib/rack/filter_param/filter.rb @@ -0,0 +1,21 @@ +module Rack + class Filter + attr_reader :param, :path, :if_proc + + def initialize(options) + if options.is_a?(Hash) + @param = parse_param(options[:param]) + @path = options[:path] + @if_proc = options[:if] + else + @param = parse_param(options) + end + end + + private + + def parse_param(param) + param.is_a?(Symbol) ? param.to_s : param + end + end +end diff --git a/lib/rack/filter_param/middleware.rb b/lib/rack/filter_param/middleware.rb new file mode 100644 index 0000000..cd3266b --- /dev/null +++ b/lib/rack/filter_param/middleware.rb @@ -0,0 +1,17 @@ +module Rack + module FilterParam + class Middleware + def initialize(app, *filters) + @app = app + @filters = filters.flatten.map(&Filter.public_method(:new)) + end + + def call(env) + request = Request.new(env) + + @filters.each { |filter| ApplyFilter.new(filter, request).call } + @app.call(env) + end + end + end +end diff --git a/lib/rack/filter_param/version.rb b/lib/rack/filter_param/version.rb index 33ce8e8..4090048 100644 --- a/lib/rack/filter_param/version.rb +++ b/lib/rack/filter_param/version.rb @@ -1,5 +1,5 @@ module Rack - class FilterParam + module FilterParam VERSION = "0.2.1" end end diff --git a/spec/rack/filter_param_spec.rb b/spec/rack/filter_param_spec.rb index 6acd6de..1e3aad9 100644 --- a/spec/rack/filter_param_spec.rb +++ b/spec/rack/filter_param_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Rack::FilterParam do let(:headers) { {} } let(:rack_env) { {} } let(:params_to_test) { - last_request.env[described_class::ACTION_DISPATCH_KEY] || last_request.params + last_request.env[Rack::FilterParam::ACTION_DISPATCH_KEY] || last_request.params } before { @@ -225,7 +225,7 @@ RSpec.describe Rack::FilterParam do let(:params) { super().to_json } let(:rack_env) { - { described_class::ACTION_DISPATCH_KEY => params } + { Rack::FilterParam::ACTION_DISPATCH_KEY => params } } describe 'basic functionality' do