You can quickly reduce the amount of data transferred from your Rack or Rails application with Rack::Deflater. Anecdotal evidence shows a reduction from a 50Kb JSON response into about 6Kb. It may be a huge deal for your mobile clients.
For a Rails application, modify config/application.rb or config/environment.rb.
``` ruby config/application.rb Acme::Application.configure do config.middleware.use Rack::Deflater end
For a Rack application, add the middleware in config.ru.
``` ruby config.ru
use Rack::Deflater
run Acme::Instance
Note that the order of the middleware is very important. For example, we also use Rack::JSONP that adds automatic JSONP support to our API. It must be invoked before Rack::Deflater or it will attempt to wrap compressed content. Rack middleware is executed in reverse order [source].
``` ruby config/application.rb config.middleware.use Rack::Deflater config.middleware.use Rack::JSONP
A couple of handy RSpec tests to add to your application. You will need to modify this code with a valid API path and expected response.
``` ruby spec/api/rack_deflater_spec.rb
require 'spec_helper'
describe Rack::Deflater do
it "produces an identical eTag whether content is deflated or not" do
get "/api/acme"
response.headers["Content-Encoding"].should be_nil
etag = response.headers["Etag"]
content_length = response.headers["Content-Length"].to_i
get "/api/acme", {}, { "HTTP_ACCEPT_ENCODING" => "gzip" }
response.headers["Etag"].should == etag
response.headers["Content-Length"].to_i.should_not == content_length
response.headers["Content-Encoding"].should == "gzip"
end
it "deflates JSONP content" do
get "/api/acme?callback=parseResponse", {}, { "HTTP_ACCEPT_ENCODING" => "deflate" }
response.headers["Content-Encoding"].should == "deflate"
inflated_response_body = Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(response.body.to_s)
inflated_response_body.should == "parseResponse(...)"
end
end
Comments