diff --git a/moto/s3/responses.py b/moto/s3/responses.py index bf1db432a..80a0a9421 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -80,10 +80,19 @@ def key_response(uri_info, method, body, headers): s3_backend.copy_key(src_bucket, src_key, bucket_name, key_name) template = Template(S3_OBJECT_COPY_RESPONSE) return template.render(key=src_key) - if body: - new_key = s3_backend.set_key(bucket_name, key_name, body) - template = Template(S3_OBJECT_RESPONSE) - return template.render(key=new_key), dict(etag=new_key.etag) + if body is not None: + key = s3_backend.get_key(bucket_name, key_name) + if not key or body: + # We want to write the key in once of two circumstances. + # - The key does not currently exist. + # - The key already exists, but body is a truthy value. + # This allows us to write empty strings to keys for the first + # write, but not subsequent. This is because HTTPretty sends + # an empty string on connection close. This is a temporary fix + # while HTTPretty gets fixed. + new_key = s3_backend.set_key(bucket_name, key_name, body) + template = Template(S3_OBJECT_RESPONSE) + return template.render(key=new_key), dict(etag=new_key.etag) key = s3_backend.get_key(bucket_name, key_name) if key: return "", dict(etag=key.etag) diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index 144e25301..31e011bfc 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -51,6 +51,17 @@ def test_missing_key_urllib2(): urllib2.urlopen.when.called_with("http://foobar.s3.amazonaws.com/the-key").should.throw(urllib2.HTTPError) +@mock_s3 +def test_empty_key(): + conn = boto.connect_s3('the_key', 'the_secret') + bucket = conn.create_bucket("foobar") + key = Key(bucket) + key.key = "the-key" + key.set_contents_from_string("") + + bucket.get_key("the-key").get_contents_as_string().should.equal('') + + @mock_s3 def test_copy_key(): conn = boto.connect_s3('the_key', 'the_secret')