Skip to content

Commit

Permalink
Fix 500 for bogus Range request to 0-byte object.
Browse files Browse the repository at this point in the history
The proxy was trying to pop a byterange off a Range header that didn't
contain syntactically-valid byteranges. This worked about as well as
you'd expect. Now we detect the bogus value and remove the header
entirely.

Change-Id: I24b92f900d33ec79880c7db2870378489d5a6810
  • Loading branch information
smerritt committed Aug 20, 2015
1 parent ef8f14f commit be66aa8
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 1 deletion.
7 changes: 6 additions & 1 deletion swift/proxy/controllers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,12 @@ def pop_range(self):
If we have no Range header, this is a no-op.
"""
if 'Range' in self.backend_headers:
req_range = Range(self.backend_headers['Range'])
try:
req_range = Range(self.backend_headers['Range'])
except ValueError:
# there's a Range header, but it's garbage, so get rid of it
self.backend_headers.pop('Range')
return
begin, end = req_range.ranges.pop(0)
if len(req_range.ranges) > 0:
self.backend_headers['Range'] = str(req_range)
Expand Down
40 changes: 40 additions & 0 deletions test/unit/proxy/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,46 @@ def test_GET_ranges(self):
'bytes 4123-4523/5800')
self.assertEqual(second_range_body, obj[4123:4524])

@unpatch_policies
def test_GET_bad_range_zero_byte(self):
prolis = _test_sockets[0]
prosrv = _test_servers[0]
sock = connect_tcp(('localhost', prolis.getsockname()[1]))
fd = sock.makefile()

path = '/v1/a/c/o.zerobyte'
fd.write('PUT %s HTTP/1.1\r\n'
'Host: localhost\r\n'
'Connection: close\r\n'
'X-Storage-Token: t\r\n'
'Content-Length: 0\r\n'
'Content-Type: application/octet-stream\r\n'
'\r\n' % (path,))
fd.flush()
headers = readuntil2crlfs(fd)
exp = 'HTTP/1.1 201'
self.assertEqual(headers[:len(exp)], exp)

# bad byte-range
req = Request.blank(
path,
environ={'REQUEST_METHOD': 'GET'},
headers={'Content-Type': 'application/octet-stream',
'Range': 'bytes=spaghetti-carbonara'})
res = req.get_response(prosrv)
self.assertEqual(res.status_int, 200)
self.assertEqual(res.body, '')

# not a byte-range
req = Request.blank(
path,
environ={'REQUEST_METHOD': 'GET'},
headers={'Content-Type': 'application/octet-stream',
'Range': 'Kotta'})
res = req.get_response(prosrv)
self.assertEqual(res.status_int, 200)
self.assertEqual(res.body, '')

@unpatch_policies
def test_GET_ranges_resuming(self):
prolis = _test_sockets[0]
Expand Down

0 comments on commit be66aa8

Please sign in to comment.