机架自定义中间件给出错误" ActionDispatch :: Http :: Parameters :: ParseError"

时间:2017-11-14 21:07:44

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

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

中配置了中间件
config.middleware.use CustomMiddleware

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

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

我可以访问参数并根据需要进行操作。但是当我将env obj传递给作为接收者的app对象时。我正在

"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对象并对参数进行硬编码,则没有这样的解析错误。我的控制器正在响应数据w.r.t来硬编码参数。

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

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

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

2 个答案:

答案 0 :(得分:0)

添加了一个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

答案 1 :(得分:0)

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

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

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

env['rack.input'].rewind 

request.body.rewind

现在您的请求又有参数了,Rails 可以简单地继续工作了。