【问题标题】:Rack custom middleware giving error "ActionDispatch::Http::Parameters::ParseError"机架自定义中间件给出错误“ActionDispatch::Http::Parameters::ParseError”
【发布时间】:2018-04-27 22:59:54
【问题描述】:

我正在为我的 rails 应用程序编写一个自定义中间件,以解密/加密发布请求中的参数。我已经在'config/environments/staging.rb'配置了中间件

config.middleware.use CustomMiddleware

为了读取请求参数,我正在像这样读取 env obj

rack_input = env['rack.input'].read

我能够访问参数并根据需要进行操作。但是当我将env obj 传递给作为接收器的应用程序对象时。我得到了

"ActionDispatch::Http::Parameters::ParseError" 

完全错误

Error occurred while parsing request parameters.
Contents:


F, [2017-11-15T02:13:50.230088 #24060] FATAL -- : [9aa25c7e-56e7-4894-ba30-3a01f60ae4fc]   
F, [2017-11-15T02:13:50.230340 #24060] FATAL -- : [9aa25c7e-56e7-4894-ba30-3a01f60ae4fc] ActionDispatch::Http::Parameters::ParseError (no implicit conversion of nil into String):
F, [2017-11-15T02:13:50.230563 #24060] FATAL -- : [9aa25c7e-56e7-4894-ba30-3a01f60ae4fc]   
F, [2017-11-15T02:13:50.230782 #24060] FATAL -- : [9aa25c7e-56e7-4894-ba30-3a01f60ae4fc] app/middleware/custom_middleware.rb:34:in `call'

我的代码有点像这样

class CustomMiddleware
  include Encryption   

  def initialize(app)
    @app = app
  end

  def set_payload_params(env)
    rack_input = env['rack.input'].read
    @args = JSON.parse(rack_input) rescue {}
  end

  def call(env)
    request = Rack::Request.new(env)
    set_payload_params(env)

    payload = @args['payload']

    decrypt_params
    status, headers, response = @app.call(env)
    encrypt_params

  end

如果我不读取 env 对象并对参数进行硬编码,则不存在此类解析错误。我的控制器正在响应硬编码参数的数据。

我的 Rails 版本是 5.1.4 我的 ruby​​ 版本是 2.4.2

我在另一个 Rails 应用程序(4.2.8)中做了一个类似的中间件,它工作正常。

对此的任何见解都会有很大帮助。提前致谢。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 ruby-on-rails-5 rack


    【解决方案1】:

    添加了在自定义中间件中将 content-type 设置为“”的 hack,避免了在将输入转发到堆栈中的下一个组件之前解析输入。

     class CustomMiddleware   
    
       include Encryption   
    
       def initialize(app)
         @app = app   end
    
       def set_payload_params(env)
         rack_input = env['rack.input'].read
         @args = JSON.parse(rack_input) rescue {}   end
    
       def call(env)
         env['CONTENT_TYPE'] = ''
         request = Rack::Request.new(env)
         set_payload_params(env)
    
         payload = @args['payload']
    
         decrypt_params
         status, headers, response = @app.call(env)
         encrypt_params
    
      end
    

    【讨论】:

      【解决方案2】:

      这个错误是由于在中间件中读取参数为空(这是流)后发生的。

      rack_input = env['rack.input'].read
      

      执行此代码后,机架参数为空。现在你需要制作

      env['rack.input'].rewind 
      

      request.body.rewind
      

      现在你的请求又有了参数,Rails 可以继续工作了。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多