Rails output compression
I want to be able to compress my output text that I send to the browser from my Rails app. This will include HTML, javascript, Ajax responses, plain text etc. Lighttpd will perform this function for the static files it serves, but not for the dynamic files, so I went looking for a solution.
There is a README for ActionPack that has this snippet of code:
after_filter { |c| c.response.body = GZip::compress(c.response.body) }I added this to my ApplicationController, and it doesn’t work.
I can’t find any GZip object in my Ruby or Rails code. I did find some output compression in the Ruby SOAP implementation, so I re-purposed that code for my after_filter. Here’s what I ended up with:
require 'stringio'
require 'zlib'
class ApplicationController < ActionController::Base
after_filter :compress
def compress
if self.request.env['HTTP_ACCEPT_ENCODING'].match(/gzip/)
if self.response.headers["Content-Transfer-Encoding"] != 'binary'
begin
ostream = StringIO.new
gz = Zlib::GzipWriter.new(ostream)
gz.write(self.response.body)
self.response.body = ostream.string
self.response.headers['Content-Encoding'] = 'gzip'
ensure
gz.close
end
end
end
end
end- The request must be checked to see if the browser supports gzip encoding before sending the compressed data
- I don’t do the gzip detection entirely to spec, if q=0 in the accept encoding header, GZIP should be disabled.
Since the request accept-encoding header must be checked, and the content-encoding header added, the original code example could never have worked correctly. My version of the code should work in most cases.
Update I added a check for the Content-Transfer-Encoding header. If this is ‘binary’, then don’t compress, as the response is an image, or something we don’t want to compress. Rails leaves this header off for text responses, like HTML.
Trackbacks
Use the following link to trackback from your own site:
http://blog.craz8.com/trackbacks?article_id=rails-output-compression&day=07&month=12&year=2005
Hello! Good Site! Thanks you! jqqyaiyfrbds