diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/params_parser.rb')
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/params_parser.rb | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb new file mode 100644 index 0000000000..b426183488 --- /dev/null +++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb @@ -0,0 +1,60 @@ +require 'active_support/core_ext/hash/conversions' +require 'action_dispatch/http/request' +require 'active_support/core_ext/hash/indifferent_access' + +module ActionDispatch + class ParamsParser + class ParseError < StandardError + attr_reader :original_exception + + def initialize(message, original_exception) + super(message) + @original_exception = original_exception + end + end + + DEFAULT_PARSERS = { Mime::JSON => :json } + + def initialize(app, parsers = {}) + @app, @parsers = app, DEFAULT_PARSERS.merge(parsers) + end + + def call(env) + if params = parse_formatted_parameters(env) + env["action_dispatch.request.request_parameters"] = params + end + + @app.call(env) + end + + private + def parse_formatted_parameters(env) + request = Request.new(env) + + return false if request.content_length.zero? + + strategy = @parsers[request.content_mime_type] + + return false unless strategy + + case strategy + when Proc + strategy.call(request.raw_post) + when :json + data = ActiveSupport::JSON.decode(request.raw_post) + data = {:_json => data} unless data.is_a?(Hash) + Request::Utils.deep_munge(data).with_indifferent_access + else + false + end + rescue Exception => e # JSON or Ruby code block errors + logger(env).debug "Error occurred while parsing request parameters.\nContents:\n\n#{request.raw_post}" + + raise ParseError.new(e.message, e) + end + + def logger(env) + env['action_dispatch.logger'] || ActiveSupport::Logger.new($stderr) + end + end +end |