From 27eb2d7ebd29239a5043a528c97c6dd218d03217 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 30 Nov 2010 16:26:20 -0800 Subject: 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. --- lib/metropolis/deflate.rb | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 lib/metropolis/deflate.rb (limited to 'lib/metropolis/deflate.rb') 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 -- cgit v1.2.3-24-ge0c7