如何在 Rails 5 应用程序中接受 gzip 压缩的请求?

问题描述 投票:0回答:4

过去我使用过这个解决方案,但自从 Rails 5 已弃用

ParamsParser
中间件以来,它不再起作用了。

ruby-on-rails rack ruby-on-rails-5
4个回答
7
投票

只需添加以下内容:

# config/initializers/middlewares.rb
require 'compressed_requests'

Rails.application.configure do
  config.middleware.insert_before 0, CompressedRequests
end

然后将中间件从this Gist添加到

lib/middleware/compressed_requests.rb

class CompressedRequests
  def initialize(app)
    @app = app
  end

  def method_handled?(env)
    !!(env['REQUEST_METHOD'] =~ /(POST|PUT)/)
  end

  def encoding_handled?(env)
    ['gzip', 'deflate'].include? env['HTTP_CONTENT_ENCODING']
  end
  
  def call(env)
    if method_handled?(env) && encoding_handled?(env)
      extracted = decode(env['rack.input'], env['HTTP_CONTENT_ENCODING'])

      env.delete('HTTP_CONTENT_ENCODING')
      env['CONTENT_LENGTH'] = extracted.bytesize
      env['rack.input'] = StringIO.new(extracted)
    end

    @app.call(env)
  end
  
  def decode(input, content_encoding)
    case content_encoding
      when 'gzip' then Zlib::GzipReader.new(input).read
      when 'deflate' then Zlib::Inflate.inflate(input.read)
    end
  end
end

您可以使用以下方法进行测试:

# config/routes.rb
post '/', to: 'welcome#create'

# app/controllers/welcome_controller.rb
class WelcomeController < ActionController::Base
  def create
    render json: params
  end
end

并执行请求:

$ curl --data-binary @<(echo "Uncompressed data" | gzip) \
  -H "CONTENT_ENCODING: gzip" \
  localhost:3000
{"Uncompressed data\n":null,"controller":"welcome","action":"create"}%

3
投票

如果您在

Rack::Head

之前插入中间件,这应该可以工作
config.middleware.insert_before Rack::Head, "CompressedRequests"

这应该可以解决问题

您可以使用以下命令检查应用程序的中间件堆栈

rake middleware


2
投票

在您的 routes.rb 文件上:

post 'my_endpoint', to: 'api#my_endpoint'

在您的api_controller.rb上:

class ApiController < ActionController::Base
  def my_endpoint
    render json: JSON.parse(ActiveSupport::Gzip.decompress(request.body.string))
  end
end

我已经使用 Paw 客户端在全新的 Rails 5 应用程序上对此进行了测试:

© www.soinside.com 2019 - 2024. All rights reserved.