Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle 307 redirect for file-like object, don't use isinstance check #236

Merged
merged 1 commit into from
Feb 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion botocore/awsrequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,13 @@ def __init__(self, original_request):

def reset_stream_on_redirect(self, response, **kwargs):
if response.status_code in REDIRECT_STATI and \
isinstance(self.body, file_type):
self._looks_like_file(self.body):
logger.debug("Redirect received, rewinding stream: %s", self.body)
self.reset_stream()

def _looks_like_file(self, body):
return hasattr(body, 'read') and hasattr(body, 'seek')

def reset_stream(self):
# Trying to reset a stream when there is a no stream will
# just immediately return. It's not an error, it will produce
Expand Down
30 changes: 29 additions & 1 deletion tests/unit/test_awsrequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,42 @@ def test_cannot_reset_stream_raises_error(self):
# This means that we read the body:
body.read()
# And create a response object that indicates
# a redirect.
# a redirect
fake_response = Mock()
fake_response.status_code = 307

# Then requests calls our reset_stream hook.
with self.assertRaises(UnseekableStreamError):
self.prepared_request.reset_stream_on_redirect(fake_response)

def test_duck_type_for_file_check(self):
# As part of determining whether or not we can rewind a stream
# we first need to determine if the thing is a file like object.
# We should not be using an isinstance check. Instead, we should
# be using duck type checks.
class LooksLikeFile(object):
def __init__(self):
self.seek_called = False

def read(self, amount=None):
pass

def seek(self, where):
self.seek_called = True

looks_like_file = LooksLikeFile()
self.prepared_request.body = looks_like_file

fake_response = Mock()
fake_response.status_code = 307

# Then requests calls our reset_stream hook.
self.prepared_request.reset_stream_on_redirect(fake_response)

# The stream should now be reset.
self.assertTrue(looks_like_file.seek_called)



if __name__ == "__main__":
unittest.main()