Skip to content
This repository
Newer
Older
100644 104 lines (90 sloc) 2.873 kb
a31ee950 »
2008-07-02 Implemented Rack::Deflater
1 require "zlib"
cabc20df »
2008-07-04 added gzip support to Rack::Deflater
2 require "stringio"
e44d9088 »
2008-12-20 Fixed Rack::Deflater to handle responses with Last-Modified header
3 require "time" # for Time.httpdate
d6fa6afd »
2009-01-14 Explicitly require request, response, and utils
4 require 'rack/utils'
a31ee950 »
2008-07-02 Implemented Rack::Deflater
5
6 module Rack
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
7 class Deflater
8 def initialize(app)
9 @app = app
3b116580 »
2008-12-20 Added Accept-Encoding to HTTP Vary header
10 end
11
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
12 def call(env)
13 status, headers, body = @app.call(env)
14 headers = Utils::HeaderHash.new(headers)
15
16 # Skip compressing empty entity body responses and responses with
17 # no-transform set.
18 if Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) ||
71030b9d »
2009-08-05 Revert "Add common HTTP strings to Rack::Const"
19 headers['Cache-Control'].to_s =~ /\bno-transform\b/
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
20 return [status, headers, body]
21 end
22
23 request = Request.new(env)
24
25 encoding = Utils.select_best_encoding(%w(gzip deflate identity),
26 request.accept_encoding)
27
28 # Set the Vary HTTP header.
29 vary = headers["Vary"].to_s.split(",").map { |v| v.strip }
30 unless vary.include?("*") || vary.include?("Accept-Encoding")
31 headers["Vary"] = vary.push("Accept-Encoding").join(",")
32 end
33
34 case encoding
35 when "gzip"
71030b9d »
2009-08-05 Revert "Add common HTTP strings to Rack::Const"
36 headers['Content-Encoding'] = "gzip"
37 headers.delete('Content-Length')
38 mtime = headers.key?("Last-Modified") ?
39 Time.httpdate(headers["Last-Modified"]) : Time.now
c81542e2 »
2009-03-13 Rack::Deflater streaming
40 [status, headers, GzipStream.new(body, mtime)]
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
41 when "deflate"
71030b9d »
2009-08-05 Revert "Add common HTTP strings to Rack::Const"
42 headers['Content-Encoding'] = "deflate"
43 headers.delete('Content-Length')
c81542e2 »
2009-03-13 Rack::Deflater streaming
44 [status, headers, DeflateStream.new(body)]
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
45 when "identity"
46 [status, headers, body]
47 when nil
35c0890b »
2012-11-03 Ensure that deflater always closes bodies.
48 body.close if body.respond_to?(:close)
3576a34f »
2009-02-03 Fix spec failures in Rack::Deflator under 1.9
49 message = "An acceptable encoding for the requested resource #{request.fullpath} could not be found."
71030b9d »
2009-08-05 Revert "Add common HTTP strings to Rack::Const"
50 [406, {"Content-Type" => "text/plain", "Content-Length" => message.length.to_s}, [message]]
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
51 end
a31ee950 »
2008-07-02 Implemented Rack::Deflater
52 end
53
c81542e2 »
2009-03-13 Rack::Deflater streaming
54 class GzipStream
55 def initialize(body, mtime)
56 @body = body
57 @mtime = mtime
58 end
cabc20df »
2008-07-04 added gzip support to Rack::Deflater
59
c81542e2 »
2009-03-13 Rack::Deflater streaming
60 def each(&block)
61 @writer = block
62 gzip =::Zlib::GzipWriter.new(self)
63 gzip.mtime = @mtime
37d2b2fe »
2011-01-18 deflater flushes each chunk of the response
64 @body.each { |part|
65 gzip.write(part)
66 gzip.flush
67 }
35c0890b »
2012-11-03 Ensure that deflater always closes bodies.
68 ensure
c81542e2 »
2009-03-13 Rack::Deflater streaming
69 @body.close if @body.respond_to?(:close)
70 gzip.close
71 @writer = nil
72 end
cabc20df »
2008-07-04 added gzip support to Rack::Deflater
73
c81542e2 »
2009-03-13 Rack::Deflater streaming
74 def write(data)
75 @writer.call(data)
76 end
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
77 end
cabc20df »
2008-07-04 added gzip support to Rack::Deflater
78
c81542e2 »
2009-03-13 Rack::Deflater streaming
79 class DeflateStream
80 DEFLATE_ARGS = [
81 Zlib::DEFAULT_COMPRESSION,
82 # drop the zlib header which causes both Safari and IE to choke
83 -Zlib::MAX_WBITS,
84 Zlib::DEF_MEM_LEVEL,
85 Zlib::DEFAULT_STRATEGY
86 ]
f3b542a5 »
2008-07-05 deflater.rb - Move out the Zlib::Deflate constructor arguments to a c…
87
c81542e2 »
2009-03-13 Rack::Deflater streaming
88 def initialize(body)
89 @body = body
90 end
a31ee950 »
2008-07-02 Implemented Rack::Deflater
91
c81542e2 »
2009-03-13 Rack::Deflater streaming
92 def each
93 deflater = ::Zlib::Deflate.new(*DEFLATE_ARGS)
37d2b2fe »
2011-01-18 deflater flushes each chunk of the response
94 @body.each { |part| yield deflater.deflate(part, Zlib::SYNC_FLUSH) }
c81542e2 »
2009-03-13 Rack::Deflater streaming
95 yield deflater.finish
96 nil
35c0890b »
2012-11-03 Ensure that deflater always closes bodies.
97 ensure
98 @body.close if @body.respond_to?(:close)
99 deflater.close
c81542e2 »
2009-03-13 Rack::Deflater streaming
100 end
2f79f55c »
2009-01-21 Deflater sets Content-Length header [#9 state:resolved]
101 end
a31ee950 »
2008-07-02 Implemented Rack::Deflater
102 end
103 end
Something went wrong with that request. Please try again.