s3api errors for unsupported headers x-delete-at, x-delete-after
We need to support the aforementioned headers in our s3 apis and raise an InvalidArgumentError if a s3 client makes a request Change-Id: I2c5b18e52da7f33b31ba386cdbd042f90b69ef97
This commit is contained in:
parent
38124221d7
commit
d363236a24
@ -83,7 +83,6 @@ from swift.common.middleware.s3api.s3response import InvalidArgument, \
|
|||||||
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
|
InvalidPart, BucketAlreadyExists, EntityTooSmall, InvalidPartOrder, \
|
||||||
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
|
InvalidRequest, HTTPOk, HTTPNoContent, NoSuchKey, NoSuchUpload, \
|
||||||
NoSuchBucket, BucketAlreadyOwnedByYou
|
NoSuchBucket, BucketAlreadyOwnedByYou
|
||||||
from swift.common.middleware.s3api.exception import BadSwiftRequest
|
|
||||||
from swift.common.middleware.s3api.utils import unique_id, \
|
from swift.common.middleware.s3api.utils import unique_id, \
|
||||||
MULTIUPLOAD_SUFFIX, S3Timestamp, sysmeta_header
|
MULTIUPLOAD_SUFFIX, S3Timestamp, sysmeta_header
|
||||||
from swift.common.middleware.s3api.etree import Element, SubElement, \
|
from swift.common.middleware.s3api.etree import Element, SubElement, \
|
||||||
@ -801,8 +800,8 @@ class UploadController(Controller):
|
|||||||
status=body['Response Status'],
|
status=body['Response Status'],
|
||||||
msg='\n'.join(': '.join(err)
|
msg='\n'.join(': '.join(err)
|
||||||
for err in body['Errors']))
|
for err in body['Errors']))
|
||||||
except BadSwiftRequest as e:
|
except InvalidRequest as err_resp:
|
||||||
msg = str(e)
|
msg = err_resp._msg
|
||||||
if too_small_message in msg:
|
if too_small_message in msg:
|
||||||
raise EntityTooSmall(msg)
|
raise EntityTooSmall(msg)
|
||||||
elif ', Etag Mismatch' in msg:
|
elif ', Etag Mismatch' in msg:
|
||||||
|
@ -22,10 +22,6 @@ class NotS3Request(S3Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BadSwiftRequest(S3Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class ACLError(S3Exception):
|
class ACLError(S3Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -57,8 +57,7 @@ from swift.common.middleware.s3api.s3response import AccessDenied, \
|
|||||||
MalformedXML, InvalidRequest, RequestTimeout, InvalidBucketName, \
|
MalformedXML, InvalidRequest, RequestTimeout, InvalidBucketName, \
|
||||||
BadDigest, AuthorizationHeaderMalformed, SlowDown, \
|
BadDigest, AuthorizationHeaderMalformed, SlowDown, \
|
||||||
AuthorizationQueryParametersError, ServiceUnavailable, BrokenMPU
|
AuthorizationQueryParametersError, ServiceUnavailable, BrokenMPU
|
||||||
from swift.common.middleware.s3api.exception import NotS3Request, \
|
from swift.common.middleware.s3api.exception import NotS3Request
|
||||||
BadSwiftRequest
|
|
||||||
from swift.common.middleware.s3api.utils import utf8encode, \
|
from swift.common.middleware.s3api.utils import utf8encode, \
|
||||||
S3Timestamp, mktime, MULTIUPLOAD_SUFFIX
|
S3Timestamp, mktime, MULTIUPLOAD_SUFFIX
|
||||||
from swift.common.middleware.s3api.subresource import decode_acl, encode_acl
|
from swift.common.middleware.s3api.subresource import decode_acl, encode_acl
|
||||||
@ -642,7 +641,7 @@ class S3Request(swob.Request):
|
|||||||
bucket, self.conf.dns_compliant_bucket_names):
|
bucket, self.conf.dns_compliant_bucket_names):
|
||||||
# Ignore GET service case
|
# Ignore GET service case
|
||||||
raise InvalidBucketName(bucket)
|
raise InvalidBucketName(bucket)
|
||||||
return (bucket, obj)
|
return bucket, obj
|
||||||
|
|
||||||
def _parse_query_authentication(self):
|
def _parse_query_authentication(self):
|
||||||
"""
|
"""
|
||||||
@ -779,7 +778,6 @@ class S3Request(swob.Request):
|
|||||||
raise InvalidArgument('x-amz-copy-source',
|
raise InvalidArgument('x-amz-copy-source',
|
||||||
self.headers['X-Amz-Copy-Source'],
|
self.headers['X-Amz-Copy-Source'],
|
||||||
msg)
|
msg)
|
||||||
|
|
||||||
if 'x-amz-metadata-directive' in self.headers:
|
if 'x-amz-metadata-directive' in self.headers:
|
||||||
value = self.headers['x-amz-metadata-directive']
|
value = self.headers['x-amz-metadata-directive']
|
||||||
if value not in ('COPY', 'REPLACE'):
|
if value not in ('COPY', 'REPLACE'):
|
||||||
@ -1399,7 +1397,17 @@ class S3Request(swob.Request):
|
|||||||
raise err_resp()
|
raise err_resp()
|
||||||
|
|
||||||
if status == HTTP_BAD_REQUEST:
|
if status == HTTP_BAD_REQUEST:
|
||||||
raise BadSwiftRequest(err_msg.decode('utf8'))
|
err_str = err_msg.decode('utf8')
|
||||||
|
if 'X-Delete-At' in err_str:
|
||||||
|
raise InvalidArgument('X-Delete-At',
|
||||||
|
self.headers['X-Delete-At'],
|
||||||
|
err_str)
|
||||||
|
if 'X-Delete-After' in err_msg.decode('utf8'):
|
||||||
|
raise InvalidArgument('X-Delete-After',
|
||||||
|
self.headers['X-Delete-After'],
|
||||||
|
err_str)
|
||||||
|
else:
|
||||||
|
raise InvalidRequest(msg=err_str)
|
||||||
if status == HTTP_UNAUTHORIZED:
|
if status == HTTP_UNAUTHORIZED:
|
||||||
raise SignatureDoesNotMatch(
|
raise SignatureDoesNotMatch(
|
||||||
**self.signature_does_not_match_kwargs())
|
**self.signature_does_not_match_kwargs())
|
||||||
|
@ -29,6 +29,7 @@ from time import mktime
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
import test.functional as tf
|
import test.functional as tf
|
||||||
|
from swift.common import utils
|
||||||
|
|
||||||
from swift.common.middleware.s3api.etree import fromstring
|
from swift.common.middleware.s3api.etree import fromstring
|
||||||
from swift.common.middleware.s3api.utils import S3Timestamp
|
from swift.common.middleware.s3api.utils import S3Timestamp
|
||||||
@ -36,7 +37,8 @@ from swift.common.utils import md5, quote
|
|||||||
|
|
||||||
from test.functional.s3api import S3ApiBase
|
from test.functional.s3api import S3ApiBase
|
||||||
from test.functional.s3api.s3_test_client import Connection
|
from test.functional.s3api.s3_test_client import Connection
|
||||||
from test.functional.s3api.utils import get_error_code, calculate_md5
|
from test.functional.s3api.utils import get_error_code, calculate_md5, \
|
||||||
|
get_error_msg
|
||||||
|
|
||||||
DAY = 86400.0 # 60 * 60 * 24 (sec)
|
DAY = 86400.0 # 60 * 60 * 24 (sec)
|
||||||
|
|
||||||
@ -417,6 +419,53 @@ class TestS3ApiObject(S3ApiBase):
|
|||||||
self.assertCommonResponseHeaders(headers)
|
self.assertCommonResponseHeaders(headers)
|
||||||
self._assertObjectEtag(self.bucket, obj, etag)
|
self._assertObjectEtag(self.bucket, obj, etag)
|
||||||
|
|
||||||
|
def test_put_object_valid_delete_headers(self):
|
||||||
|
obj = 'object'
|
||||||
|
content = b'abcdefghij'
|
||||||
|
ts = utils.Timestamp.now()
|
||||||
|
delete_at = {'X-Delete-At': str(int(ts) + 70)}
|
||||||
|
delete_after = {'X-Delete-After': str(int(ts) + 130)}
|
||||||
|
status, delete_at, body = \
|
||||||
|
self.conn.make_request('PUT', self.bucket, obj, delete_at, content)
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
status, delete_after, body = \
|
||||||
|
self.conn.make_request('PUT', self.bucket, obj, delete_after,
|
||||||
|
content)
|
||||||
|
self.assertEqual(status, 200)
|
||||||
|
|
||||||
|
def test_put_object_invalid_x_delete_at(self):
|
||||||
|
obj = 'object'
|
||||||
|
content = b'abcdefghij'
|
||||||
|
ts = utils.Timestamp.now()
|
||||||
|
headers = {'X-Delete-At': str(int(ts) - 140)}
|
||||||
|
status, headers, body = \
|
||||||
|
self.conn.make_request('PUT', self.bucket, obj, headers, content)
|
||||||
|
self.assertEqual(status, 400)
|
||||||
|
self.assertEqual(get_error_code(body), 'InvalidArgument')
|
||||||
|
self.assertEqual(get_error_msg(body), 'X-Delete-At in past')
|
||||||
|
headers = {'X-Delete-At': 'test'}
|
||||||
|
status, headers, body = \
|
||||||
|
self.conn.make_request('PUT', self.bucket, obj, headers, content)
|
||||||
|
self.assertEqual(status, 400)
|
||||||
|
self.assertEqual(get_error_code(body), 'InvalidArgument')
|
||||||
|
self.assertEqual(get_error_msg(body), 'Non-integer X-Delete-At')
|
||||||
|
|
||||||
|
def test_put_object_invalid_x_delete_after(self):
|
||||||
|
obj = 'object'
|
||||||
|
content = b'abcdefghij'
|
||||||
|
headers = {'X-Delete-After': 'test'}
|
||||||
|
status, headers, body = \
|
||||||
|
self.conn.make_request('PUT', self.bucket, obj, headers, content)
|
||||||
|
self.assertEqual(status, 400)
|
||||||
|
self.assertEqual(get_error_code(body), 'InvalidArgument')
|
||||||
|
self.assertEqual(get_error_msg(body), 'Non-integer X-Delete-After')
|
||||||
|
headers = {'X-Delete-After': '-140'}
|
||||||
|
status, headers, body = \
|
||||||
|
self.conn.make_request('PUT', self.bucket, obj, headers, content)
|
||||||
|
self.assertEqual(status, 400)
|
||||||
|
self.assertEqual(get_error_code(body), 'InvalidArgument')
|
||||||
|
self.assertEqual(get_error_msg(body), 'X-Delete-After in past')
|
||||||
|
|
||||||
def test_put_object_copy_source_params(self):
|
def test_put_object_copy_source_params(self):
|
||||||
obj = 'object'
|
obj = 'object'
|
||||||
src_headers = {'X-Amz-Meta-Test': 'src'}
|
src_headers = {'X-Amz-Meta-Test': 'src'}
|
||||||
|
Loading…
Reference in New Issue
Block a user