improve and test etag handling for unsafe http methods. fixes #311, closes #312.

This commit is contained in:
Konstantin Haase 2011-06-29 11:27:30 +02:00
parent 3d9de1fe86
commit 0799e0e482
2 changed files with 37 additions and 12 deletions

View File

@ -39,6 +39,14 @@ module Sinatra
@env.include? "HTTP_X_FORWARDED_HOST"
end
def safe?
get? or head? or options? or trace?
end
def idempotent?
safe? or put? or delete?
end
private
def accept_entry(entry)
@ -303,18 +311,12 @@ module Sinatra
value = 'W/' + value if kind == :weak
response['ETag'] = value
case env['REQUEST_METHOD']
when /^(GET)|(HEAD)$/
# Conditional GET check
if etags = env['HTTP_IF_NONE_MATCH']
etags = etags.split(/\s*,\s*/)
halt 304 if etags.include?(value) || etags.include?('*')
end
when /^(PUT)|(POST)|(DELETE)$/
# Conditional PUT/POST/DELETE
if etags = env['HTTP_IF_MATCH']
etags = etags.split(/\s*, \s*/)
halt 412 unless etags.include?(value) || etags.include?('*')
if etags = env['HTTP_IF_NONE_MATCH']
etags = etags.split(/\s*,\s*/)
if etags.include?(value) or etags.include?('*')
halt 304 if request.safe?
else
halt 412 unless request.safe?
end
end
end

View File

@ -951,6 +951,11 @@ class HelpersTest < Test::Unit::TestCase
etag 'FOO'
'Boo!'
end
post '/' do
etag 'FOO'
'Matches!'
end
}
end
@ -965,6 +970,24 @@ class HelpersTest < Test::Unit::TestCase
assert_equal 'Boo!', body
end
it 'returns a body when posting with no If-None-Match header' do
post '/'
assert_equal 200, status
assert_equal 'Matches!', body
end
it 'returns a body when conditional post matches' do
post '/', {}, { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
assert_equal 200, status
assert_equal 'Matches!', body
end
it 'halts with 412 when conditional post misses' do
post '/', {}, { 'HTTP_IF_NONE_MATCH' => '"BAR"' }
assert_equal 412, status
assert_equal '', body
end
it 'halts when a conditional GET matches' do
get '/', {}, { 'HTTP_IF_NONE_MATCH' => '"FOO"' }
assert_equal 304, status