diff --git a/swift3/controllers/multi_upload.py b/swift3/controllers/multi_upload.py index 60f47b07..9fadd472 100644 --- a/swift3/controllers/multi_upload.py +++ b/swift3/controllers/multi_upload.py @@ -578,8 +578,14 @@ class UploadController(Controller): headers=headers) except BadSwiftRequest as e: msg = str(e) - if msg.startswith('Each segment, except the last, ' - 'must be at least '): + msg_pre_260 = 'Each segment, except the last, must be at least ' + # see https://github.com/openstack/swift/commit/c0866ce + msg_260 = ('too small; each segment, except the last, must be ' + 'at least ') + # see https://github.com/openstack/swift/commit/7f636a5 + msg_post_260 = 'too small; each segment must be at least 1 byte' + if msg.startswith(msg_pre_260) or \ + msg_260 in msg or msg_post_260 in msg: # FIXME: AWS S3 allows a smaller object than 5 MB if there is # only one part. Use a COPY request to copy the part object # from the segments container instead. diff --git a/swift3/test/unit/test_multi_upload.py b/swift3/test/unit/test_multi_upload.py index cedcb519..3a1051c2 100644 --- a/swift3/test/unit/test_multi_upload.py +++ b/swift3/test/unit/test_multi_upload.py @@ -634,6 +634,31 @@ class TestSwift3MultiUpload(Swift3TestCase): self.assertEquals(headers.get('X-Object-Meta-Foo'), 'bar') self.assertEquals(headers.get('Content-Type'), 'baz/quux') + def test_object_multipart_upload_complete_segment_too_small(self): + msgs = [ + # pre-2.6.0 swift + 'Each segment, except the last, must be at least 1234 bytes.', + # swift 2.6.0 + 'Index 0: too small; each segment, except the last, must be ' + 'at least 1234 bytes.', + # swift 2.7.0+ + 'Index 0: too small; each segment must be at least 1 byte.', + ] + + for msg in msgs: + req = Request.blank( + '/bucket/object?uploadId=X', + environ={'REQUEST_METHOD': 'POST'}, + headers={'Authorization': 'AWS test:tester:hmac', + 'Date': self.get_date_header(), }, + body=xml) + + self.swift.register('PUT', '/v1/AUTH_test/bucket/object', + swob.HTTPBadRequest, {}, msg) + status, headers, body = self.call_swift3(req) + self.assertEquals(status.split()[0], '400') + self.assertEquals(self._get_error_code(body), 'EntityTooSmall') + def test_object_multipart_upload_complete_single_zero_length_segment(self): segment_bucket = '/v1/AUTH_test/empty-bucket+segments' put_headers = {'etag': self.etag, 'last-modified': self.last_modified}