From b2afebea6089c2d399db01761401d2580575c977 Mon Sep 17 00:00:00 2001 From: MORITA Kazutaka Date: Wed, 13 Aug 2014 05:00:02 +0900 Subject: [PATCH] etree: add support for url-encoding Change-Id: I8e0395b6495e46605a77f38a583d62cf9ad62f84 --- swift3/controllers/bucket.py | 10 +++++++++- swift3/controllers/multi_upload.py | 19 ++++++++++++++++--- swift3/etree.py | 13 ++++++++++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/swift3/controllers/bucket.py b/swift3/controllers/bucket.py index ffef75ad..ff35f526 100644 --- a/swift3/controllers/bucket.py +++ b/swift3/controllers/bucket.py @@ -52,6 +52,11 @@ class BucketController(Controller): max_keys = int(req.params.get('max-keys', CONF.max_bucket_listing)) max_keys = min(max_keys, CONF.max_bucket_listing) + encoding_type = req.params.get('encoding-type') + if encoding_type is not None and encoding_type != 'url': + err_msg = 'Invalid Encoding Method specified in Request' + raise InvalidArgument('encoding-type', encoding_type, err_msg) + query = { 'format': 'json', 'limit': max_keys + 1, @@ -76,6 +81,9 @@ class BucketController(Controller): if 'delimiter' in req.params: SubElement(elem, 'Delimiter').text = req.params['delimiter'] + if encoding_type is not None: + SubElement(elem, 'EncodingType').text = encoding_type + if max_keys > 0 and len(objects) == max_keys + 1: is_truncated = 'true' else: @@ -100,7 +108,7 @@ class BucketController(Controller): common_prefixes = SubElement(elem, 'CommonPrefixes') SubElement(common_prefixes, 'Prefix').text = o['subdir'] - body = tostring(elem) + body = tostring(elem, encoding_type=encoding_type) return HTTPOk(body=body, content_type='application/xml') diff --git a/swift3/controllers/multi_upload.py b/swift3/controllers/multi_upload.py index e509ce14..2513f0a3 100644 --- a/swift3/controllers/multi_upload.py +++ b/swift3/controllers/multi_upload.py @@ -131,6 +131,11 @@ class UploadsController(Controller): """ Handles List Multipart Uploads """ + encoding_type = req.params.get('encoding-type') + if encoding_type is not None and encoding_type != 'url': + err_msg = 'Invalid Encoding Method specified in Request' + raise InvalidArgument('encoding-type', encoding_type, err_msg) + # TODO: add support for prefix, key-marker, upload-id-marker, and # max-uploads queries. query = { @@ -167,7 +172,10 @@ class UploadsController(Controller): SubElement(result_elem, 'NextUploadIdMarker').text = nextuploadmarker SubElement(result_elem, 'MaxUploads').text = str(DEFAULT_MAX_UPLOADS) - # TODO: add support for EncodingType + + if encoding_type is not None: + SubElement(result_elem, 'EncodingType').text = encoding_type + SubElement(result_elem, 'IsTruncated').text = 'false' # TODO: don't show uploads which are initiated before this bucket is @@ -186,7 +194,7 @@ class UploadsController(Controller): SubElement(upload_elem, 'Initiated').text = \ u['last_modified'][:-3] + 'Z' - body = tostring(result_elem) + body = tostring(result_elem, encoding_type=encoding_type) return HTTPOk(body=body, content_type='application/xml') @@ -233,6 +241,11 @@ class UploadController(Controller): """ Handles List Parts. """ + encoding_type = req.params.get('encoding-type') + if encoding_type is not None and encoding_type != 'url': + err_msg = 'Invalid Encoding Method specified in Request' + raise InvalidArgument('encoding-type', encoding_type, err_msg) + upload_id = req.params['uploadId'] _check_upload_info(req, self.app, upload_id) @@ -286,7 +299,7 @@ class UploadController(Controller): SubElement(part_elem, 'ETag').text = i['hash'] SubElement(part_elem, 'Size').text = str(i['bytes']) - body = tostring(result_elem) + body = tostring(result_elem, encoding_type=encoding_type) return HTTPOk(body=body, content_type='application/xml') diff --git a/swift3/etree.py b/swift3/etree.py index 35747bee..264ab737 100644 --- a/swift3/etree.py +++ b/swift3/etree.py @@ -14,6 +14,7 @@ # limitations under the License. import lxml.etree +from urllib import quote from copy import deepcopy from pkg_resources import resource_stream @@ -78,7 +79,7 @@ def fromstring(text, root_tag=None): return elem -def tostring(tree, use_s3ns=True): +def tostring(tree, encoding_type=None, use_s3ns=True): if use_s3ns: nsmap = tree.nsmap.copy() nsmap[None] = XMLNS_S3 @@ -88,6 +89,16 @@ def tostring(tree, use_s3ns=True): root.extend(deepcopy(tree.getchildren())) tree = root + if encoding_type == 'url': + tree = deepcopy(tree) + for e in tree.iter(): + # Some elements are not url-encoded even when we specify + # encoding_type=url. + blacklist = ['LastModified', 'ID', 'DisplayName', 'Initiated'] + if e.tag not in blacklist: + if isinstance(e.text, basestring): + e.text = quote(e.text) + return lxml.etree.tostring(tree, xml_declaration=True, encoding='UTF-8')