lib/rack/conditionalget.rb in rack-1.2.8 vs lib/rack/conditionalget.rb in rack-1.3.0.beta

- old
+ new

@@ -18,30 +18,49 @@ def initialize(app) @app = app end def call(env) - return @app.call(env) unless %w[GET HEAD].include?(env['REQUEST_METHOD']) - - status, headers, body = @app.call(env) - headers = Utils::HeaderHash.new(headers) - if etag_matches?(env, headers) || modified_since?(env, headers) - status = 304 - headers.delete('Content-Type') - headers.delete('Content-Length') - body = [] + case env['REQUEST_METHOD'] + when "GET", "HEAD" + status, headers, body = @app.call(env) + headers = Utils::HeaderHash.new(headers) + if status == 200 && fresh?(env, headers) + status = 304 + headers.delete('Content-Type') + headers.delete('Content-Length') + body = [] + end + [status, headers, body] + else + @app.call(env) end - [status, headers, body] end private - def etag_matches?(env, headers) - etag = headers['Etag'] and etag == env['HTTP_IF_NONE_MATCH'] + + def fresh?(env, headers) + modified_since = env['HTTP_IF_MODIFIED_SINCE'] + none_match = env['HTTP_IF_NONE_MATCH'] + + return false unless modified_since || none_match + + success = true + success &&= modified_since?(to_rfc2822(modified_since), headers) if modified_since + success &&= etag_matches?(none_match, headers) if none_match + success end - def modified_since?(env, headers) - last_modified = headers['Last-Modified'] and - last_modified == env['HTTP_IF_MODIFIED_SINCE'] + def etag_matches?(none_match, headers) + etag = headers['ETag'] and etag == none_match end - end + def modified_since?(modified_since, headers) + last_modified = to_rfc2822(headers['Last-Modified']) and + modified_since >= last_modified + end + + def to_rfc2822(since) + Time.rfc2822(since) rescue nil + end + end end