我有一个使用Rails编写的API,每次请求都会返回JSON响应。
响应可能非常大,因此我需要使用gzip压缩JSON响应。
想知道如何在Rails控制器中实现这一点?
我已经添加了以下代码:
use Rack::Deflater
在config.ru文件中。
我还需要更改渲染JSON的那一行吗?
render :json => response.to_json()
还有,我如何检查响应是否为gzip格式?
我从终端执行了一个curl请求,只看到普通的JSON数据。
我有一个使用Rails编写的API,每次请求都会返回JSON响应。
响应可能非常大,因此我需要使用gzip压缩JSON响应。
想知道如何在Rails控制器中实现这一点?
我已经添加了以下代码:
use Rack::Deflater
在config.ru文件中。
我还需要更改渲染JSON的那一行吗?
render :json => response.to_json()
还有,我如何检查响应是否为gzip格式?
我从终端执行了一个curl请求,只看到普通的JSON数据。
我的文章"使用 Rack::Deflater 进行内容压缩"介绍了几种整合 Rack::Deflater 的方法。最简单的方法是只需在config/application.rb
中更新:
module YourApp
class Application < Rails::Application
config.middleware.use Rack::Deflater
end
end
如果客户端明确表示它们可以处理压缩,那么您将自动使用deflate / gzip压缩所有控制器响应。
如果要响应以gzip格式呈现,我们不需要更改render
方法的调用。
如果请求带有Accept-Encoding: gzip
头,则Rails将自动使用gzip压缩JSON响应。
如果您不希望用户发送带有预设标头的请求,可以在控制器中手动向请求添加标头,然后呈现响应:
request.env['HTTP_ACCEPT_ENCODING'] = 'gzip'
render :json => response.to_json()
Rack::Deflater
中间件才能让 Rails 压缩 JSON 响应,即使你已经将 Accept-Encoding 请求头设置为 'gzip,deflate'。请注意,压缩需要请求头的支持。 - sameers您可以设置自定义头来查询Curl以获取经过gzip压缩的响应。
$ curl -H "Accept-Encoding: gzip, deflate" localhost:3000/posts.json > posts_json.gz
$ gzip -d posts_json.gz
$ cat posts_json
如果它不起作用,请回帖并附上rake中间件
的输出,以帮助我们进一步排除故障。
res = {} # huge data hash
json = res.to_json
Zlib::GzipWriter.open('public/api/huge_data.json.gz') { |gz| gz.write json }
并定期更新此文件
config.ru
文件中。# config/application.rb or config/environment.rb depends on your Rails version
config.middleware.use Rack::Deflater
module MyApp
class Application < Rails::Application
config.middleware.insert_before Rack::ETag, Rack::Deflater
end
end
Rack::Deflater
和Rack::ETag
的顺序很重要,因为Rack::Deflater
使用Zlib::GzipWriter
来压缩响应正文,默认情况下会带有时间戳,这意味着即使原始响应正文相同,压缩后的响应正文每秒都会改变。
要复现此问题,请运行以下脚本:
"require 'rack/etag'
require 'rack/deflater'
require 'rack/content_length'
@app = Rack::Builder.new do
use Rack::ETag
use Rack::Deflater
use Rack::ContentLength
run ->(*) { [200, {}, ['hello world']] }
end
def puts_etag
puts @app.call({ 'HTTP_ACCEPT_ENCODING' => 'gzip' })[1]['ETag']
end
puts_etag
sleep 1
puts_etag
Rack::ETag
和 Rack::Deflater
的行,以获得预期的输出。
Rails 默认使用 Rack::ETag
,而 config.middleware.use
只是追加。要在 Rack::Etag
之前插入 Rack::Deflater
,请改用 config.middleware.insert_before
。
config.middleware.use Rack::Deflater
,压缩只在Mac OS(Chrome、FF和Safary)上开始工作。在Windows上,我在FF和IE中收到没有'Content-Encoding: gzip;'的响应(仅在Chrome中工作)。P.S. "Accept-Encoding: gzip"在所有浏览器中都存在。你知道为什么吗? - bmalets