From 7077d4b6d3eb25c856c83b7c8a22210216fde645 Mon Sep 17 00:00:00 2001 From: Joshua Peek Date: Fri, 11 Dec 2009 15:52:08 -0600 Subject: Import etag middleware from contrib into core --- lib/rack.rb | 1 + lib/rack/etag.rb | 23 +++++++++++++++++++++++ test/spec_rack_etag.rb | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 lib/rack/etag.rb create mode 100644 test/spec_rack_etag.rb diff --git a/lib/rack.rb b/lib/rack.rb index b2aed6a5..20b3c379 100644 --- a/lib/rack.rb +++ b/lib/rack.rb @@ -31,6 +31,7 @@ module Rack autoload :Config, "rack/config" autoload :ContentLength, "rack/content_length" autoload :ContentType, "rack/content_type" + autoload :ETag, "rack/etag" autoload :File, "rack/file" autoload :Deflater, "rack/deflater" autoload :Directory, "rack/directory" diff --git a/lib/rack/etag.rb b/lib/rack/etag.rb new file mode 100644 index 00000000..06dbc6aa --- /dev/null +++ b/lib/rack/etag.rb @@ -0,0 +1,23 @@ +require 'digest/md5' + +module Rack + # Automatically sets the ETag header on all String bodies + class ETag + def initialize(app) + @app = app + end + + def call(env) + status, headers, body = @app.call(env) + + if !headers.has_key?('ETag') + parts = [] + body.each { |part| parts << part.to_s } + headers['ETag'] = %("#{Digest::MD5.hexdigest(parts.join(""))}") + [status, headers, parts] + else + [status, headers, body] + end + end + end +end diff --git a/test/spec_rack_etag.rb b/test/spec_rack_etag.rb new file mode 100644 index 00000000..73cd31ac --- /dev/null +++ b/test/spec_rack_etag.rb @@ -0,0 +1,17 @@ +require 'test/spec' +require 'rack/mock' +require 'rack/etag' + +context "Rack::ETag" do + specify "sets ETag if none is set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.equal "\"65a8e27d8879283831b664bd8b7f0ad4\"" + end + + specify "does not change ETag if it is already set" do + app = lambda { |env| [200, {'Content-Type' => 'text/plain', 'ETag' => '"abc"'}, ["Hello, World!"]] } + response = Rack::ETag.new(app).call({}) + response[1]['ETag'].should.equal "\"abc\"" + end +end -- cgit v1.2.3-24-ge0c7