about summary refs log tree commit
path: root/lib/metropolis/deflate.rb
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2010-11-30 16:26:20 -0800
committerEric Wong <normalperson@yhbt.net>2010-11-30 16:26:20 -0800
commit27eb2d7ebd29239a5043a528c97c6dd218d03217 (patch)
tree7eb9ccc289cd78af10374c01fb80061f0abeeff3 /lib/metropolis/deflate.rb
parent03755186d6cb968d44d7eb04de3ed2d047180272 (diff)
downloadmetropolis-27eb2d7ebd29239a5043a528c97c6dd218d03217.tar.gz
support pass-through :encoding for deflate and gzip
These allow serving pre-compressed data off disk and
on-the-fly uncompressing for the few clients that do
not accept compressed responses.
Diffstat (limited to 'lib/metropolis/deflate.rb')
-rw-r--r--lib/metropolis/deflate.rb45
1 files changed, 45 insertions, 0 deletions
diff --git a/lib/metropolis/deflate.rb b/lib/metropolis/deflate.rb
new file mode 100644
index 0000000..d585b43
--- /dev/null
+++ b/lib/metropolis/deflate.rb
@@ -0,0 +1,45 @@
+# -*- encoding: binary -*-
+require "zlib"
+
+# allows storing pre-deflated data on disk and serving it
+# as-is for clients that accept that deflate encoding
+module Metropolis::Deflate
+  def get(key, env)
+    status, headers, body = r = super
+    if 200 == status && /\bdeflate\b/ !~ env['HTTP_ACCEPT_ENCODING']
+      inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
+      body[0] = "#{inflater.inflate(body[0])}#{inflater.finish}"
+      inflater.end
+      headers['Content-Length'] = body[0].size.to_s
+      headers.delete('Content-Encoding')
+      headers.delete('Vary')
+    end
+    r
+  end
+
+  def put(key, env)
+    Wrapper.new(env)
+    super(key, env)
+  end
+
+  def self.extended(obj)
+    obj.instance_eval do
+      @headers['Content-Encoding'] = 'deflate'
+      @headers['Vary'] = 'Accept-Encoding'
+    end
+  end
+
+  class Wrapper < Metropolis::InputWrapper
+
+    def read_all
+      deflater = Zlib::Deflate.new(
+        Zlib::DEFAULT_COMPRESSION,
+        # drop the zlib header which causes both Safari and IE to choke
+        -Zlib::MAX_WBITS,
+        Zlib::DEF_MEM_LEVEL,
+        Zlib::DEFAULT_STRATEGY
+      )
+      "#{deflater.deflate(@input.read)}#{deflater.finish}"
+    end
+  end
+end