Merge "Only url-quote Keys when encoding-type=url"
This commit is contained in:
commit
6f699d877e
@ -16,6 +16,8 @@
|
|||||||
from base64 import standard_b64encode as b64encode
|
from base64 import standard_b64encode as b64encode
|
||||||
from base64 import standard_b64decode as b64decode
|
from base64 import standard_b64decode as b64decode
|
||||||
|
|
||||||
|
from six.moves.urllib.parse import quote
|
||||||
|
|
||||||
from swift.common.http import HTTP_OK
|
from swift.common.http import HTTP_OK
|
||||||
from swift.common.utils import json, public, config_true_value
|
from swift.common.utils import json, public, config_true_value
|
||||||
|
|
||||||
@ -171,11 +173,12 @@ class BucketController(Controller):
|
|||||||
SubElement(elem, 'Marker').text = req.params.get('marker')
|
SubElement(elem, 'Marker').text = req.params.get('marker')
|
||||||
if is_truncated and 'delimiter' in req.params:
|
if is_truncated and 'delimiter' in req.params:
|
||||||
if 'name' in objects[-1]:
|
if 'name' in objects[-1]:
|
||||||
SubElement(elem, 'NextMarker').text = \
|
name = objects[-1]['name']
|
||||||
objects[-1]['name']
|
else:
|
||||||
if 'subdir' in objects[-1]:
|
name = objects[-1]['subdir']
|
||||||
SubElement(elem, 'NextMarker').text = \
|
if encoding_type == 'url':
|
||||||
objects[-1]['subdir']
|
name = quote(name)
|
||||||
|
SubElement(elem, 'NextMarker').text = name
|
||||||
elif listing_type == 'version-2':
|
elif listing_type == 'version-2':
|
||||||
if is_truncated:
|
if is_truncated:
|
||||||
if 'name' in objects[-1]:
|
if 'name' in objects[-1]:
|
||||||
@ -197,7 +200,7 @@ class BucketController(Controller):
|
|||||||
if 'delimiter' in req.params:
|
if 'delimiter' in req.params:
|
||||||
SubElement(elem, 'Delimiter').text = req.params['delimiter']
|
SubElement(elem, 'Delimiter').text = req.params['delimiter']
|
||||||
|
|
||||||
if encoding_type is not None:
|
if encoding_type == 'url':
|
||||||
SubElement(elem, 'EncodingType').text = encoding_type
|
SubElement(elem, 'EncodingType').text = encoding_type
|
||||||
|
|
||||||
SubElement(elem, 'IsTruncated').text = \
|
SubElement(elem, 'IsTruncated').text = \
|
||||||
@ -205,14 +208,18 @@ class BucketController(Controller):
|
|||||||
|
|
||||||
for o in objects:
|
for o in objects:
|
||||||
if 'subdir' not in o:
|
if 'subdir' not in o:
|
||||||
|
name = o['name']
|
||||||
|
if encoding_type == 'url':
|
||||||
|
name = quote(name)
|
||||||
|
|
||||||
if listing_type == 'object-versions':
|
if listing_type == 'object-versions':
|
||||||
contents = SubElement(elem, 'Version')
|
contents = SubElement(elem, 'Version')
|
||||||
SubElement(contents, 'Key').text = o['name']
|
SubElement(contents, 'Key').text = name
|
||||||
SubElement(contents, 'VersionId').text = 'null'
|
SubElement(contents, 'VersionId').text = 'null'
|
||||||
SubElement(contents, 'IsLatest').text = 'true'
|
SubElement(contents, 'IsLatest').text = 'true'
|
||||||
else:
|
else:
|
||||||
contents = SubElement(elem, 'Contents')
|
contents = SubElement(elem, 'Contents')
|
||||||
SubElement(contents, 'Key').text = o['name']
|
SubElement(contents, 'Key').text = name
|
||||||
SubElement(contents, 'LastModified').text = \
|
SubElement(contents, 'LastModified').text = \
|
||||||
o['last_modified'][:-3] + 'Z'
|
o['last_modified'][:-3] + 'Z'
|
||||||
if 's3_etag' in o:
|
if 's3_etag' in o:
|
||||||
@ -231,9 +238,12 @@ class BucketController(Controller):
|
|||||||
for o in objects:
|
for o in objects:
|
||||||
if 'subdir' in o:
|
if 'subdir' in o:
|
||||||
common_prefixes = SubElement(elem, 'CommonPrefixes')
|
common_prefixes = SubElement(elem, 'CommonPrefixes')
|
||||||
SubElement(common_prefixes, 'Prefix').text = o['subdir']
|
name = o['subdir']
|
||||||
|
if encoding_type == 'url':
|
||||||
|
name = quote(name)
|
||||||
|
SubElement(common_prefixes, 'Prefix').text = name
|
||||||
|
|
||||||
body = tostring(elem, encoding_type=encoding_type)
|
body = tostring(elem)
|
||||||
|
|
||||||
return HTTPOk(body=body, content_type='application/xml')
|
return HTTPOk(body=body, content_type='application/xml')
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ from swift.common.swob import Range
|
|||||||
from swift.common.utils import json, public
|
from swift.common.utils import json, public
|
||||||
from swift.common.db import utf8encode
|
from swift.common.db import utf8encode
|
||||||
|
|
||||||
from six.moves.urllib.parse import urlparse # pylint: disable=F0401
|
from six.moves.urllib.parse import quote, urlparse
|
||||||
|
|
||||||
from swift.common.middleware.s3api.controllers.base import Controller, \
|
from swift.common.middleware.s3api.controllers.base import Controller, \
|
||||||
bucket_operation, object_operation, check_container_existence
|
bucket_operation, object_operation, check_container_existence
|
||||||
@ -319,7 +319,10 @@ class UploadsController(Controller):
|
|||||||
# created.
|
# created.
|
||||||
for u in uploads:
|
for u in uploads:
|
||||||
upload_elem = SubElement(result_elem, 'Upload')
|
upload_elem = SubElement(result_elem, 'Upload')
|
||||||
SubElement(upload_elem, 'Key').text = u['key']
|
name = u['key']
|
||||||
|
if encoding_type == 'url':
|
||||||
|
name = quote(name)
|
||||||
|
SubElement(upload_elem, 'Key').text = name
|
||||||
SubElement(upload_elem, 'UploadId').text = u['upload_id']
|
SubElement(upload_elem, 'UploadId').text = u['upload_id']
|
||||||
initiator_elem = SubElement(upload_elem, 'Initiator')
|
initiator_elem = SubElement(upload_elem, 'Initiator')
|
||||||
SubElement(initiator_elem, 'ID').text = req.user_id
|
SubElement(initiator_elem, 'ID').text = req.user_id
|
||||||
@ -335,7 +338,7 @@ class UploadsController(Controller):
|
|||||||
elem = SubElement(result_elem, 'CommonPrefixes')
|
elem = SubElement(result_elem, 'CommonPrefixes')
|
||||||
SubElement(elem, 'Prefix').text = p
|
SubElement(elem, 'Prefix').text = p
|
||||||
|
|
||||||
body = tostring(result_elem, encoding_type=encoding_type)
|
body = tostring(result_elem)
|
||||||
|
|
||||||
return HTTPOk(body=body, content_type='application/xml')
|
return HTTPOk(body=body, content_type='application/xml')
|
||||||
|
|
||||||
@ -456,7 +459,10 @@ class UploadController(Controller):
|
|||||||
|
|
||||||
result_elem = Element('ListPartsResult')
|
result_elem = Element('ListPartsResult')
|
||||||
SubElement(result_elem, 'Bucket').text = req.container_name
|
SubElement(result_elem, 'Bucket').text = req.container_name
|
||||||
SubElement(result_elem, 'Key').text = req.object_name
|
name = req.object_name
|
||||||
|
if encoding_type == 'url':
|
||||||
|
name = quote(name)
|
||||||
|
SubElement(result_elem, 'Key').text = name
|
||||||
SubElement(result_elem, 'UploadId').text = upload_id
|
SubElement(result_elem, 'UploadId').text = upload_id
|
||||||
|
|
||||||
initiator_elem = SubElement(result_elem, 'Initiator')
|
initiator_elem = SubElement(result_elem, 'Initiator')
|
||||||
@ -484,7 +490,7 @@ class UploadController(Controller):
|
|||||||
SubElement(part_elem, 'ETag').text = '"%s"' % i['hash']
|
SubElement(part_elem, 'ETag').text = '"%s"' % i['hash']
|
||||||
SubElement(part_elem, 'Size').text = str(i['bytes'])
|
SubElement(part_elem, 'Size').text = str(i['bytes'])
|
||||||
|
|
||||||
body = tostring(result_elem, encoding_type=encoding_type)
|
body = tostring(result_elem)
|
||||||
|
|
||||||
return HTTPOk(body=body, content_type='application/xml')
|
return HTTPOk(body=body, content_type='application/xml')
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import lxml.etree
|
import lxml.etree
|
||||||
from urllib import quote
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from pkg_resources import resource_stream # pylint: disable-msg=E0611
|
from pkg_resources import resource_stream # pylint: disable-msg=E0611
|
||||||
import six
|
import six
|
||||||
@ -86,7 +85,7 @@ def fromstring(text, root_tag=None, logger=None):
|
|||||||
return elem
|
return elem
|
||||||
|
|
||||||
|
|
||||||
def tostring(tree, encoding_type=None, use_s3ns=True):
|
def tostring(tree, use_s3ns=True):
|
||||||
if use_s3ns:
|
if use_s3ns:
|
||||||
nsmap = tree.nsmap.copy()
|
nsmap = tree.nsmap.copy()
|
||||||
nsmap[None] = XMLNS_S3
|
nsmap[None] = XMLNS_S3
|
||||||
@ -96,16 +95,6 @@ def tostring(tree, encoding_type=None, use_s3ns=True):
|
|||||||
root.extend(deepcopy(tree.getchildren()))
|
root.extend(deepcopy(tree.getchildren()))
|
||||||
tree = root
|
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, six.string_types):
|
|
||||||
e.text = quote(e.text)
|
|
||||||
|
|
||||||
return lxml.etree.tostring(tree, xml_declaration=True, encoding='UTF-8')
|
return lxml.etree.tostring(tree, xml_declaration=True, encoding='UTF-8')
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ import unittest
|
|||||||
import cgi
|
import cgi
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
|
from six.moves.urllib.parse import quote
|
||||||
|
|
||||||
from swift.common import swob
|
from swift.common import swob
|
||||||
from swift.common.swob import Request
|
from swift.common.swob import Request
|
||||||
from swift.common.utils import json
|
from swift.common.utils import json
|
||||||
@ -164,7 +166,33 @@ class TestS3ApiBucket(S3ApiTestCase):
|
|||||||
|
|
||||||
self.assertEqual(len(names), len(self.objects))
|
self.assertEqual(len(names), len(self.objects))
|
||||||
for i in self.objects:
|
for i in self.objects:
|
||||||
self.assertTrue(i[0] in names)
|
self.assertIn(i[0], names)
|
||||||
|
|
||||||
|
def test_bucket_GET_url_encoded(self):
|
||||||
|
bucket_name = 'junk'
|
||||||
|
req = Request.blank('/%s?encoding-type=url' % bucket_name,
|
||||||
|
environ={'REQUEST_METHOD': 'GET'},
|
||||||
|
headers={'Authorization': 'AWS test:tester:hmac',
|
||||||
|
'Date': self.get_date_header()})
|
||||||
|
status, headers, body = self.call_s3api(req)
|
||||||
|
self.assertEqual(status.split()[0], '200')
|
||||||
|
|
||||||
|
elem = fromstring(body, 'ListBucketResult')
|
||||||
|
name = elem.find('./Name').text
|
||||||
|
self.assertEqual(name, bucket_name)
|
||||||
|
|
||||||
|
objects = elem.iterchildren('Contents')
|
||||||
|
|
||||||
|
names = []
|
||||||
|
for o in objects:
|
||||||
|
names.append(o.find('./Key').text)
|
||||||
|
self.assertEqual('2011-01-05T02:19:14.275Z',
|
||||||
|
o.find('./LastModified').text)
|
||||||
|
self.assertEqual('"0"', o.find('./ETag').text)
|
||||||
|
|
||||||
|
self.assertEqual(len(names), len(self.objects))
|
||||||
|
for i in self.objects:
|
||||||
|
self.assertIn(quote(i[0]), names)
|
||||||
|
|
||||||
def test_bucket_GET_subdir(self):
|
def test_bucket_GET_subdir(self):
|
||||||
bucket_name = 'junk-subdir'
|
bucket_name = 'junk-subdir'
|
||||||
|
Loading…
Reference in New Issue
Block a user