diff --git a/botocore/handlers.py b/botocore/handlers.py index 2d984e4863..548ba9007d 100644 --- a/botocore/handlers.py +++ b/botocore/handlers.py @@ -169,6 +169,11 @@ def fix_s3_host(event_name, endpoint, request, auth, **kwargs): addressing. This allows us to avoid 301 redirects for all bucket names that can be CNAME'd. """ + if auth.auth_path is not None: + # The auth_path has already been applied (this may be a + # retried request). We don't need to perform this + # customization again. + return parts = urlsplit(request.url) auth.auth_path = parts.path path_parts = parts.path.split('/') diff --git a/tests/unit/test_handlers.py b/tests/unit/test_handlers.py index 32d61172ad..39a701ebf8 100644 --- a/tests/unit/test_handlers.py +++ b/tests/unit/test_handlers.py @@ -18,6 +18,7 @@ import mock import botocore.session +from botocore.awsrequest import AWSRequest from botocore.hooks import first_non_none_response from botocore.compat import quote from botocore import handlers @@ -161,6 +162,35 @@ def test_sse_headers(self): params['headers'][prefix + 'key-MD5'], 'N7UdGUp1E+RbVvZSTy1R8g==') + def test_fix_s3_host_initial(self): + endpoint = mock.Mock(region_name='us-west-2') + request = AWSRequest( + method='PUT',headers={}, + url='https://s3-us-west-2.amazonaws.com/bucket/key.txt' + ) + auth = mock.Mock() + auth.auth_path = None + handlers.fix_s3_host('foo', endpoint, request, auth) + self.assertEqual(request.url, 'https://bucket.s3.amazonaws.com/key.txt') + self.assertEqual(auth.auth_path, '/bucket/key.txt') + + def test_fix_s3_host_only_applied_once(self): + endpoint = mock.Mock(region_name='us-west-2') + request = AWSRequest( + method='PUT',headers={}, + url='https://s3-us-west-2.amazonaws.com/bucket/key.txt' + ) + auth = mock.Mock() + auth.auth_path = None + handlers.fix_s3_host('foo', endpoint, request, auth) + # Calling the handler again should not affect the end result: + handlers.fix_s3_host('foo', endpoint, request, auth) + self.assertEqual(request.url, 'https://bucket.s3.amazonaws.com/key.txt') + # This was a bug previously. We want to make sure that + # calling fix_s3_host() again does not alter the auth_path. + # Otherwise we'll get signature errors. + self.assertEqual(auth.auth_path, '/bucket/key.txt') + class TestRetryHandlerOrder(BaseSessionTest): def get_handler_names(self, responses): @@ -195,7 +225,3 @@ def test_s3_special_case_is_before_other_retry(self): self.assertTrue(s3_200_handler < general_retry_handler, "S3 200 error handler was supposed to be before " "the general retry handler, but it was not.") - - -if __name__ == '__main__': - unittest.main()