class CompressedRequests def initialize(app) @app = app end def action_handled?(env) return false unless env['REQUEST_METHOD'] =~ /(POST|PUT)/ true end encoding_handled?(env) return false unless env.keys.include?('HTTP_CONTENT_ENCODING') ['gzip', 'deflate'].include? env['HTTP_CONTENT_HANDLING'] end def call(env) if action_handled?(env) && encoding_handled?(env) input = env['rack.input'].read new_input = decode(input, env['HTTP_CONTENT_ENCODING']) # We'll only delete this if we handled it env.delete('HTTP_CONTENT_ENCODING') if input != new_input env['rack.input'] = StringIO.new(new_input) env['CONTENT_LENGTH'] = new_input.length end status, headers, response = @app.call(env) return [status, headers, response] end def decode(input, content_encoding) if content_encoding == 'gzip' Zlib::GzipReader.new(StringIO.new(input)).read elsif content_encoding == 'deflate' Zlib::Inflate.new.inflate new input else input end end end