Use the following redirects feature of httplib2 where it returns the ultimate
URL in the content-location header to follow redirects for media download. http://httplib2.googlecode.com/hg/doc/html/libhttplib2.html#response-objects Reviewed in https://codereview.appspot.com/10393046/ Fixes issue #280.
This commit is contained in:
@@ -508,8 +508,6 @@ class MediaIoBaseDownload(object):
|
|||||||
self._progress = 0
|
self._progress = 0
|
||||||
self._total_size = None
|
self._total_size = None
|
||||||
self._done = False
|
self._done = False
|
||||||
self._original_follow_redirects = request.http.follow_redirects
|
|
||||||
request.http.follow_redirects = False
|
|
||||||
|
|
||||||
# Stubs for testing.
|
# Stubs for testing.
|
||||||
self._sleep = time.sleep
|
self._sleep = time.sleep
|
||||||
@@ -551,10 +549,9 @@ class MediaIoBaseDownload(object):
|
|||||||
if resp.status < 500:
|
if resp.status < 500:
|
||||||
break
|
break
|
||||||
|
|
||||||
if resp.status in [301, 302, 303, 307, 308] and 'location' in resp:
|
|
||||||
self._uri = resp['location']
|
|
||||||
resp, content = http.request(self._uri, headers=headers)
|
|
||||||
if resp.status in [200, 206]:
|
if resp.status in [200, 206]:
|
||||||
|
if 'content-location' in resp and resp['content-location'] != self._uri:
|
||||||
|
self._uri = resp['content-location']
|
||||||
self._progress += len(content)
|
self._progress += len(content)
|
||||||
self._fd.write(content)
|
self._fd.write(content)
|
||||||
|
|
||||||
@@ -565,7 +562,6 @@ class MediaIoBaseDownload(object):
|
|||||||
|
|
||||||
if self._progress == self._total_size:
|
if self._progress == self._total_size:
|
||||||
self._done = True
|
self._done = True
|
||||||
self._request.http.follow_redirects = self._original_follow_redirects
|
|
||||||
return MediaDownloadProgress(self._progress, self._total_size), self._done
|
return MediaDownloadProgress(self._progress, self._total_size), self._done
|
||||||
else:
|
else:
|
||||||
raise HttpError(resp, content, uri=self._uri)
|
raise HttpError(resp, content, uri=self._uri)
|
||||||
|
|||||||
@@ -350,32 +350,27 @@ class TestMediaIoBaseDownload(unittest.TestCase):
|
|||||||
self.assertEqual(0, download._progress)
|
self.assertEqual(0, download._progress)
|
||||||
self.assertEqual(None, download._total_size)
|
self.assertEqual(None, download._total_size)
|
||||||
self.assertEqual(False, download._done)
|
self.assertEqual(False, download._done)
|
||||||
self.assertEqual(True, download._original_follow_redirects)
|
|
||||||
self.assertEqual(self.request.uri, download._uri)
|
self.assertEqual(self.request.uri, download._uri)
|
||||||
|
|
||||||
status, done = download.next_chunk()
|
status, done = download.next_chunk()
|
||||||
|
|
||||||
self.assertEqual(self.fd.getvalue(), '123')
|
self.assertEqual(self.fd.getvalue(), '123')
|
||||||
self.assertEqual(False, done)
|
self.assertEqual(False, done)
|
||||||
self.assertEqual(False, self.request.http.follow_redirects)
|
|
||||||
self.assertEqual(3, download._progress)
|
self.assertEqual(3, download._progress)
|
||||||
self.assertEqual(5, download._total_size)
|
self.assertEqual(5, download._total_size)
|
||||||
self.assertEqual(3, status.resumable_progress)
|
self.assertEqual(3, status.resumable_progress)
|
||||||
self.assertEqual(True, download._original_follow_redirects)
|
|
||||||
|
|
||||||
status, done = download.next_chunk()
|
status, done = download.next_chunk()
|
||||||
|
|
||||||
self.assertEqual(True, download._original_follow_redirects)
|
|
||||||
self.assertEqual(self.fd.getvalue(), '12345')
|
self.assertEqual(self.fd.getvalue(), '12345')
|
||||||
self.assertEqual(True, done)
|
self.assertEqual(True, done)
|
||||||
self.assertEqual(True, self.request.http.follow_redirects)
|
|
||||||
self.assertEqual(5, download._progress)
|
self.assertEqual(5, download._progress)
|
||||||
self.assertEqual(5, download._total_size)
|
self.assertEqual(5, download._total_size)
|
||||||
|
|
||||||
def test_media_io_base_download_handle_redirects(self):
|
def test_media_io_base_download_handle_redirects(self):
|
||||||
self.request.http = HttpMockSequence([
|
self.request.http = HttpMockSequence([
|
||||||
({'status': '307',
|
({'status': '200',
|
||||||
'location': 'https://secure.example.net/lion'}, ''),
|
'content-location': 'https://secure.example.net/lion'}, ''),
|
||||||
({'status': '200',
|
({'status': '200',
|
||||||
'content-range': '0-2/5'}, 'abc'),
|
'content-range': '0-2/5'}, 'abc'),
|
||||||
])
|
])
|
||||||
@@ -386,10 +381,6 @@ class TestMediaIoBaseDownload(unittest.TestCase):
|
|||||||
status, done = download.next_chunk()
|
status, done = download.next_chunk()
|
||||||
|
|
||||||
self.assertEqual('https://secure.example.net/lion', download._uri)
|
self.assertEqual('https://secure.example.net/lion', download._uri)
|
||||||
self.assertEqual(self.fd.getvalue(), 'abc')
|
|
||||||
self.assertEqual(False, done)
|
|
||||||
self.assertEqual(3, download._progress)
|
|
||||||
self.assertEqual(5, download._total_size)
|
|
||||||
|
|
||||||
def test_media_io_base_download_handle_4xx(self):
|
def test_media_io_base_download_handle_4xx(self):
|
||||||
self.request.http = HttpMockSequence([
|
self.request.http = HttpMockSequence([
|
||||||
|
|||||||
Reference in New Issue
Block a user