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