Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using gzip compression in Sinatra with Ruby

Note: I had another similar question about how to GZIP data using Ruby's zlib which technically was answered and I didn't feel I could start evolving the question since it had been answered so although this question is related it is not the same...

The following code (I believe) is GZIP'ing a static CSS file and storing the results in the result variable. But what do I do with this in the sense: how can I send this data back to the browser so it is recognised as being GZIP'ed rather than the original file size (e.g. when checking my YSlow score I want to see it correctly marking me for making sure I GZIP static resources).

z = Zlib::Deflate.new(6, 31)
z.deflate(File.read('public/Assets/Styles/build.css'))
z.flush
@result = z.finish # could also of done: result = z.deflate(file, Zlib::FINISH) 
z.close

...one thing to note is that in my previous question the respondent clarified that Zlib::Deflate.deflate will not produce gzip-encoded data. It will only produce zlib-encoded data and so I would need to use Zlib::Deflate.new with the windowBits argument equal to 31 to start a gzip stream.

But when I run this code I don't actually know what to do with the result variable and its content. There is no information on the internet (that I can find) about how to send GZIP encoded static resources (like JavaScript, CSS, HTML etc) to the browser, this making the page load quicker. It seems every Ruby article I read is based on someone using Ruby on Rails!!?

Any help really appreciated.

like image 220
Integralist Avatar asked Jun 17 '12 15:06

Integralist


2 Answers

After zipping the file you would simply return the result and ensure to set the header Content-Encoding: gzip for the response. Google has a nice, little introduction to gzip compression and what you have to watch out for. Here is what you could do in Sinatra:

get '/whatever' do
  headers['Content-Encoding'] = 'gzip'
  StringIO.new.tap do |io|
    gz = Zlib::GzipWriter.new(io)
    begin
      gz.write(File.read('public/Assets/Styles/build.css'))
    ensure
      gz.close
    end
  end.string
end

One final word of caution, though. You should probably choose this approach only for content that you created on the fly or if you just want to use gzip compression in a few places.

If, however, your goal is to serve most or even all of your static resources with gzip compression enabled, then it will be a much better solution to rely on what is already supported by your web server instead of polluting your code with this detail. There's a good chance that you can enable gzip compression with some configuration settings. Here's an example of how it is done for nginx.

Another alternative would be to use the Rack::Deflater middleware.

like image 73
emboss Avatar answered Nov 04 '22 12:11

emboss


Just to highlight 'Rack::Deflater' way as an 'answer' ->

As mentioned in the comment above, just put the compression in config.ru

use Rack::Deflater

thats pretty much it!

like image 39
Rishi Avatar answered Nov 04 '22 12:11

Rishi