2014-08-27 73 views
1

我想將一個10-20MB的壓縮JSON對象發佈到rails控制器/操作。怎麼會只是繞過解析呢?我需要做的就是將它以原始格式寫入文件系統,以後可以進行壓縮。Rails 4.x - 旁路解壓縮和/或解析gzip json POST請求

我見過一個例子,試圖是解然後分析它 - http://arnab.ch/blog/2012/09/android-how-to-send-gzipped-json-in-http-request/

在嘗試使用爲出發點,POST-ING用gzip壓縮的JSON文件,它說,該文件是沒有的gzip格式。

echo '{"name":"test"}'|gzip >> test.json.gz 

curl -X POST -H 'Content-Encoding: gzip' -d @test.json.gz -H 'Content-Type: application/json' http://server.com/endpoint 

lib::GzipFile::Error (not in gzip format): 
    lib/middleware/compressed_requests.rb:31:in 'initialize' 
    lib/middleware/compressed_requests.rb:31:in 'new' 
    lib/middleware/compressed_requests.rb:31:in 'decode' 
    lib/middleware/compressed_requests.rb:18:in 'call' 


    Rendered /home/vagrant/.rvm/gems/ruby-2.1.2-railsexpress/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_source.erb (1.7ms) 
    Rendered /home/vagrant/.rvm/gems/ruby-2.1.2-railsexpress/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (3.0ms) 
    Rendered /home/vagrant/.rvm/gems/ruby-2.1.2-railsexpress/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (14.5ms) 
    Rendered /home/vagrant/.rvm/gems/ruby-2.1.2-railsexpress/gems/actionpack-4.1.4/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (49.7ms) 

如果我不添加中間件,它會拋出一個關於無法用json詞法錯誤解析請求的錯誤。

ActionDispatch::ParamsParser::ParseError (lexical error: invalid char in json text.)-�S�V�K�MU�R*I-.Q����@Z 

任何洞察力或替代方法將不勝感激。

回答

0

我得到了這個由猴修補ParamsParser類整理出來的。不是很優雅,但有訣竅。

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 
      ## BEGIN CUSTOM HANDLER FOR GZIP ENCODED JSON 
      if !['gzip'].include? env['HTTP_CONTENT_ENCODING'] 
      data = ActiveSupport::JSON.decode(request.raw_post) 
      else 
      data = request.raw_post 
      end 
      ## END CUSTOM HANDLER FOR GZIP ENCODED JSON 
      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