diff --git a/botocore/handlers.py b/botocore/handlers.py index aa0ae98c0e..4e19cef73e 100644 --- a/botocore/handlers.py +++ b/botocore/handlers.py @@ -346,6 +346,14 @@ def add_expect_header(model, params, **kwargs): if 'body' in params: body = params['body'] if hasattr(body, 'read'): + check_body = utils.ensure_boolean( + os.environ.get( + 'BOTO_EXPERIMENTAL__NO_EMPTY_CONTINUE', + False, + ) + ) + if check_body and utils.determine_content_length(body) == 0: + return # Any file like object will use an expect 100-continue # header regardless of size. logger.debug("Adding expect 100 continue header to request.") diff --git a/tests/functional/test_s3.py b/tests/functional/test_s3.py index f51f41d264..caae590947 100644 --- a/tests/functional/test_s3.py +++ b/tests/functional/test_s3.py @@ -3619,3 +3619,31 @@ def test_escape_keys_in_xml_put_bucket_lifecycle_configuration(self): self.assertNotIn(b"my\r\n\rprefix", request.body) self.assertIn(b"my prefix", request.body) self.assert_correct_content_md5(request) + + +class TestExpectContinueBehavior(BaseSessionTest): + def test_sets_100_continute_with_body(self): + op_kwargs = { + "Bucket": "mybucket", + "Key": "mykey", + "Body": b"foo", + } + s3 = _create_s3_client() + with ClientHTTPStubber(s3) as http_stubber: + http_stubber.add_response() + s3.put_object(**op_kwargs) + expect_header = http_stubber.requests[-1].headers.get("Expect") + self.assertIsNotNone(expect_header) + self.assertEqual(expect_header, b"100-continue") + + def test_does_not_set_100_continute_with_empty_body(self): + environ = {'BOTO_EXPERIMENTAL__NO_EMPTY_CONTINUE': "True"} + self.environ_patch = mock.patch('os.environ', environ) + self.environ_patch.start() + op_kwargs = {"Bucket": "mybucket", "Key": "mykey", "Body": ""} + s3 = _create_s3_client() + with ClientHTTPStubber(s3) as http_stubber: + http_stubber.add_response() + s3.put_object(**op_kwargs) + expect_header = http_stubber.requests[-1].headers.get("Expect") + self.assertIsNone(expect_header)