c7652ae1d8f71df91d99ad4c420f18611a3ba18d
[rails.git] / lib / output_compression / output_compression.rb
1 # OutputCompression
2 # Rails output compression filters 
3
4 # Adds two classmethods to ActionController that can be used as after-filters: 
5 # strip_whitespace and compress_output. 
6 # If you use page-caching, you MUST specify the compress_output filter AFTER 
7 # caches_page, otherwise the compressed data will be cached instead of the HTML 
8
9 # class MyController < ApplicationController 
10 #  after_filter :strip_whitespace 
11 #  caches_page :index 
12 #  after_filter :compress_output 
13 # end 
14
15 begin 
16   require 'zlib' 
17   require 'stringio' 
18   GZIP_SUPPORTED = true 
19 rescue 
20   GZIP_SUPPORTED = false 
21 end 
22
23 module CompressionSystem 
24   def compress_output 
25     return unless accepts_gzip?
26     output = StringIO.new 
27     def output.close 
28       # Zlib does a close. Bad Zlib... 
29       rewind 
30     end 
31     gz = Zlib::GzipWriter.new(output) 
32     gz.write(response.body) 
33     gz.close 
34     if output.length < response.body.length 
35       @old_response_body = response.body 
36       response.body = output.string 
37       response.headers['Content-encoding'] = @compression_encoding 
38     end 
39   end 
40   
41   def accepts_gzip? 
42     return false unless GZIP_SUPPORTED 
43     accepts = request.env['HTTP_ACCEPT_ENCODING'] 
44     return false unless accepts && accepts =~ /(x-gzip|gzip)/ 
45     @compression_encoding = $1 
46     true 
47   end
48   
49   def strip_whitespace
50     response.body.gsub!(/()|(.*?<\/script>)|()|()|\s+/m) do |m| 
51       if m =~ /^()(.*?)<\/script>$/m 
52         $1 + $2.strip.gsub(/\s+/, ' ').gsub('',"\n-->") + '' 
53       elsif m =~ /^$/m 
54         '' 
55       elsif m =~ /^<(textarea|pre)/ 
56         m 
57       else ' ' 
58       end 
59     end
60     response.body.gsub! /\s+\s+/, '>' 
61   end 
62 end 
63
64 class ActionController::Base 
65   include CompressionSystem 
66 end