如何在 Rails for Android 中使用 gzip 压缩 JSON?

Posted

技术标签:

【中文标题】如何在 Rails for Android 中使用 gzip 压缩 JSON?【英文标题】:How to compress JSON with gzip in Rails for Android? 【发布时间】:2012-08-17 00:02:18 【问题描述】:

我正在运行带有 Ruby 1.9.3p194 的 Rails 3.2.7,以从 SQLite 数据库输出 JSON 数据。

render :json => result.to_json

android 应用程序使用通过 HTTP-GET 加载的 JSON 文件:

HttpClient httpclient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(urlPath);
HttpResponse response = httpclient.execute(httpGet);
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity, HTTP.UTF_8);
JSONObject jsonObject = new JSONObject(result);

平台支持:

我在API中读到Rails offers gzip support如下:

ActiveSupport::Gzip.compress(result)

我也从HTTP/1.1, RFC2626, section 14.3 猜想我可以配置 HTTP 请求的标头:

httpPost.setHeader("Accept-Encoding", "gzip");

我还发现section 3.5 "Content Codings"中包含的信息很有趣:

所有内容编码值不区分大小写。 HTTP/1.1 在 Accept-Encoding(第 14.3 节)和 Content-Encoding(第 14.11 节)标头字段中使用内容编码值。 互联网号码分配机构 (IANA) 充当内容编码值令牌的注册机构。最初,注册表包含 以下标记: gzip 由文件压缩程序“gzip”(GNU zip)产生的编码格式,如 RFC 1952 [25] 中所述。

这篇文章进一步解释了how to handle GZIP encoded content with Android。

服务器测试:

因此,我不知道如何找出数据是否已被服务器压缩。 为了测试 Rails 是否输出 gzip,我尝试按照建议使用 curl here:

$ curl --head -H "Accept-Encoding: gzip" http://localhost:3000/posts.json

但是,输出并没有告诉我是否支持 gzip:

HTTP/1.1 200 OK 
Content-Type: application/json; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "f6f6732c747466f75052f88b1eff393b"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 74ee0562c05adea679deb701f1b8fd88
X-Runtime: 0.004205
Content-Length: 0
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)
Date: Thu, 16 Aug 2012 23:33:25 GMT
Connection: Keep-Alive

我也试过curl--compressed参数...

$ curl --compressed --head -H "Accept-Encoding: gzip" http://localhost:3000/posts.json

输出与前一个命令相同的标头信息。当我跑...

$ curl --compressed -H "Accept-Encoding: gzip" http://localhost:3000/posts.json

JSON 数据作为可读文本打印到控制台。我看不到压缩是否发生。也许,因为 curl 已经解压缩了响应?!

在线测试

我也试过在线测试HTTP Compression Test提到here。它确认 JSON 内容“未压缩”。第二个网站GIDZipTest 链接here 承认检测结果为阴性。

问题:

    如何从 Rails 输出 gzip 压缩的 JSON? 如何配置 HTTP 客户端以请求 gzip 压缩数据? 当我在 Heroku (PostgreSQL) 上运行 Rails 服务器时,相同的配置是否仍然有效...?

经验教训

据我所知,我必须为 REST 服务器配置的只是 use Rack::Deflater。需要明确的是:我的代码中没有使用ActiveSupport::Gzip.compress()。如果有人感兴趣,这就是启用 GZIP 压缩时标头的样子。

HTTP/1.1 200 OK 
Content-Type: application/json; charset=utf-8
X-Ua-Compatible: IE=Edge
Etag: "8170a04be41673bf25824256740a9460"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 700b9536f6a20164d31b8528bde423af
X-Runtime: 0.369337
Vary: Accept-Encoding
Content-Encoding: gzip
Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20)
Date: Tue, 21 Aug 2012 12:10:48 GMT
Content-Length: 20
Connection: Keep-Alive

现在我知道了神奇的关键字,很容易search and find articles on use Rack::Deflater

【问题讨论】:

【参考方案1】:

也许你应该使用 Rack::Deflater? 在 config.ru 中插入:

require ::File.expand_path('../config/environment',  __FILE__)
use Rack::Deflater
run MyAppName::Application

并配置您的 http 请求标头:

我可以配置 HTTP 请求的标头:

httpPost.setHeader("Accept-Encoding", "gzip");

附:相同的配置适用于 Heroku

【讨论】:

我是否需要创建一个 Rack 应用程序才能在 Heroku 上运行它?我没有使用 Rack 应用程序的经验。我的项目是一个简单的 Rails 应用程序。 不,你不需要创造一些“特别”的东西。 Deflater 是中间件组件,您有 Rack 兼容的 Web 框架(Rails 3),只需使用它。就是这样:) 您能否为您的答案添加解释,为什么我不需要需要使用ActiveSupport::Gzip.compress()而只需要配置use Rack::Deflater JJD,我不知道该说什么:) 也许你可以使用 ActiveSupport::Gzip.compress() 但你还应该实现另一个与 HTTP 压缩相关的逻辑(在 Deflater 中已经实现了) github.com/rack/rack/blob/master/lib/rack/deflater.rb)。 Deflater 是整个应用程序的通用解决方案。我认为您可以将它用于所有服务器资源。

以上是关于如何在 Rails for Android 中使用 gzip 压缩 JSON?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Rails 视图中干燥条件 content_for?

如何使用 React 和 Rails 创建表单?

如何忽略 Zeitwerk for Rails 6 中的文件夹?

如何在 Rails 中使用来自 npm 的反应组件

如何使用 RSpec 在 Rails 中测试:包含验证

使用SASS for Ruby on Rails时如何使用border-radius属性删除导航栏圆角?