In the past I've used this solution, but since Rails 5 deprecated ParamsParser
middleware, it doesn't work anymore.
How to accept gzipped requests in a rails 5 application?
Asked Answered
Just add this:
# config/initializers/middlewares.rb
require 'compressed_requests'
Rails.application.configure do
config.middleware.insert_before 0, CompressedRequests
end
Then add the middleware from this Gist to 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
You can test it with:
# config/routes.rb
post '/', to: 'welcome#create'
# app/controllers/welcome_controller.rb
class WelcomeController < ActionController::Base
def create
render json: params
end
end
And do the request:
$ curl --data-binary @<(echo "Uncompressed data" | gzip) \
-H "CONTENT_ENCODING: gzip" \
localhost:3000
{"Uncompressed data\n":null,"controller":"welcome","action":"create"}%
this should work if you insert the middleware right before Rack::Head
config.middleware.insert_before Rack::Head, "CompressedRequests"
this should do the trick
you can check your app's middleware stack with the following command
rake middleware
your response is almost the same of @itsnikolay, I only accepted his instead of yours because he put a little more explanation and tests. But thanks anyway :) –
Linkage
i added it first! haha but does not matter as long as it solved ur prob :) –
Matthieu
If you have NginX in front of Unicorns, then you can just tell NginX to uncompress the data for you
http://www.pataliebre.net/howto-make-nginx-decompress-a-gzipped-request.html#.WBzSt-ErIUE
https://www.nginx.com/resources/admin-guide/compression-and-decompression/
this doesn't work. it only decompress responses, not requests. –
Linkage
On your routes.rb file:
post 'my_endpoint', to: 'api#my_endpoint'
On your api_controller.rb:
class ApiController < ActionController::Base
def my_endpoint
render json: JSON.parse(ActiveSupport::Gzip.decompress(request.body.string))
end
end
I've tested this on a brand new Rails 5 app using the Paw client:
is isn't really a good solution, since it's specific per action and you would be doing the decompression by hand every time. –
Linkage
@DiegoPlentz if you want to reuse this you could have a
decompressed_body
method holding the important bits (JSON.parse(ActiveSupport::Gzip.decompress(request.body.string))
). That method could live in your API base controller, or in a controller concern enabling you to reuse it and keeping your code DRY. –
Underhill © 2022 - 2024 — McMap. All rights reserved.
ActionDispatch::Cookies
? Which is the middleware after it and still exists. – Charlesettacharleston