From caf73557cdbce9d8028e2792a1aae5b3f620219b Mon Sep 17 00:00:00 2001 From: Steve Pulec Date: Mon, 6 May 2013 23:33:59 -0400 Subject: [PATCH] Fix issue with large S3 values. Closes #11. --- moto/s3/models.py | 11 +++++++++++ moto/s3/responses.py | 13 ++++++++++++- tests/test_s3/test_s3.py | 11 +++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/moto/s3/models.py b/moto/s3/models.py index 7912edfe9..0a84ba731 100644 --- a/moto/s3/models.py +++ b/moto/s3/models.py @@ -11,6 +11,10 @@ class FakeKey(object): self.value = value self.last_modified = datetime.datetime.now() + def append_to_value(self, value): + self.value += value + self.last_modified = datetime.datetime.now() + @property def etag(self): value_md5 = md5.new() @@ -81,6 +85,13 @@ class S3Backend(BaseBackend): return new_key + def append_to_key(self, bucket_name, key_name, value): + key_name = clean_key_name(key_name) + + key = self.get_key(bucket_name, key_name) + key.append_to_value(value) + return key + def get_key(self, bucket_name, key_name): key_name = clean_key_name(key_name) bucket = self.get_bucket(bucket_name) diff --git a/moto/s3/responses.py b/moto/s3/responses.py index 018719aa5..1d69384da 100644 --- a/moto/s3/responses.py +++ b/moto/s3/responses.py @@ -106,7 +106,18 @@ def _key_response(request, full_url, 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) - new_key = s3_backend.set_key(bucket_name, key_name, body) + streaming_request = hasattr(request, 'streaming') and request.streaming + closing_connection = headers.get('connection') == 'close' + if closing_connection and streaming_request: + # Closing the connection of a streaming request. No more data + new_key = s3_backend.get_key(bucket_name, key_name) + elif streaming_request: + # Streaming request, more data + new_key = s3_backend.append_to_key(bucket_name, key_name, body) + else: + # Initial data + new_key = s3_backend.set_key(bucket_name, key_name, body) + request.streaming = True template = Template(S3_OBJECT_RESPONSE) headers.update(new_key.response_dict) return 200, headers, template.render(key=new_key) diff --git a/tests/test_s3/test_s3.py b/tests/test_s3/test_s3.py index a68e511e3..264b8bb08 100644 --- a/tests/test_s3/test_s3.py +++ b/tests/test_s3/test_s3.py @@ -78,6 +78,17 @@ def test_empty_key_set_on_existing_key(): bucket.get_key("the-key").get_contents_as_string().should.equal('') +@mock_s3 +def test_large_key_save(): + 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("foobar" * 100000) + + bucket.get_key("the-key").get_contents_as_string().should.equal('foobar' * 100000) + + @mock_s3 def test_copy_key(): conn = boto.connect_s3('the_key', 'the_secret')