failing test: slo download raises SwiftError
Fix swiftclient output regression introduced by the related change: - output for SLO object download: fix incorrect warning from SwiftReader about SLO object ETag header not matching MD5 checksum - output for object stat: fix duplicated ETag Related-Change: Ice9cc9fe68684563f18ee527996e5a4292230a96 Change-Id: I5b2d79f89d1b6016de69d6b58879e5c2ef31e107
This commit is contained in:
parent
ce4fb27b53
commit
e9fd8df3f0
|
@ -740,7 +740,7 @@ def get_auth(auth_url, user, key, **kwargs):
|
|||
def resp_header_dict(resp):
|
||||
resp_headers = CaseInsensitiveDict()
|
||||
for header, value in resp.getheaders():
|
||||
header = parse_header_string(header)
|
||||
header = parse_header_string(header).lower()
|
||||
resp_headers[header] = parse_header_string(value)
|
||||
return resp_headers
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
|
||||
from swiftclient.utils import prt_bytes, split_request_headers
|
||||
|
||||
|
||||
|
@ -201,7 +203,9 @@ def headers_to_items(headers, meta_prefix='', exclude_headers=None):
|
|||
exclude_headers = exclude_headers or []
|
||||
other_items = []
|
||||
meta_items = []
|
||||
for key, value in headers.items():
|
||||
if isinstance(headers, dict):
|
||||
headers = CaseInsensitiveDict(headers)
|
||||
for key, value in headers.lower_items():
|
||||
if key not in exclude_headers:
|
||||
if key.startswith(meta_prefix):
|
||||
meta_key = 'Meta %s' % key[len(meta_prefix):].title()
|
||||
|
|
|
@ -455,7 +455,7 @@ class _SwiftReader:
|
|||
'x-object-manifest',
|
||||
'x-static-large-object',
|
||||
])
|
||||
if bad_md5_headers.intersection(headers):
|
||||
if any(h in headers for h in bad_md5_headers):
|
||||
# This isn't a useful checksum
|
||||
self._expected_md5 = ''
|
||||
|
||||
|
|
|
@ -17,6 +17,8 @@ from io import StringIO
|
|||
import unittest
|
||||
from unittest import mock
|
||||
|
||||
from requests.structures import CaseInsensitiveDict
|
||||
|
||||
from swiftclient import command_helpers as h
|
||||
from swiftclient.multithreading import OutputManager
|
||||
|
||||
|
@ -245,5 +247,32 @@ Content-Encoding: gzip
|
|||
ETag: 68b329da9893e34099c7d8ad5cb9c940
|
||||
Meta Color: blue
|
||||
Content-Encoding: gzip
|
||||
"""
|
||||
self.assertOut(expected)
|
||||
|
||||
def test_stat_object_case_insensitive_headers(self):
|
||||
self.options['verbose'] += 1
|
||||
# stub head object request
|
||||
stub_headers = CaseInsensitiveDict({
|
||||
'content-length': 2 ** 20,
|
||||
'x-object-meta-color': 'blue',
|
||||
'ETag': '68b329da9893e34099c7d8ad5cb9c940',
|
||||
'content-encoding': 'gzip',
|
||||
})
|
||||
self.conn.head_object.return_value = stub_headers
|
||||
args = ('c', 'o')
|
||||
with self.output_manager as output_manager:
|
||||
items, headers = h.stat_object(self.conn, self.options, *args)
|
||||
h.print_object_stats(items, headers, output_manager)
|
||||
expected = """
|
||||
URL: http://storage/v1/a/c/o
|
||||
Auth Token: tk12345
|
||||
Account: a
|
||||
Container: c
|
||||
Object: o
|
||||
Content Length: 1048576
|
||||
ETag: 68b329da9893e34099c7d8ad5cb9c940
|
||||
Meta Color: blue
|
||||
Content-Encoding: gzip
|
||||
"""
|
||||
self.assertOut(expected)
|
||||
|
|
|
@ -242,6 +242,28 @@ class TestSwiftReader(unittest.TestCase):
|
|||
self.assertEqual(sr._actual_md5.hexdigest(),
|
||||
md5('abc'.encode() * 3).hexdigest())
|
||||
|
||||
def test_swift_reader_knows_slo_etag_is_not_md5(self):
|
||||
segment_bodies = [b'abc', b'def', b'ghi']
|
||||
# slo etag is md5 of the sum of md5 of segments
|
||||
slo_etag = md5(b''.join(
|
||||
md5(b).hexdigest().encode()
|
||||
for b in segment_bodies
|
||||
)).hexdigest()
|
||||
headers = CaseInsensitiveDict({
|
||||
'Content-Length': len(b''.join(segment_bodies)),
|
||||
# XXX 'x-static-large-object': 'true' "works" for this test, but
|
||||
# it's not like requests or resp_header_dict returns
|
||||
'X-Static-Large-Object': 'true',
|
||||
'ETag': '"%s"' % slo_etag
|
||||
})
|
||||
sr = self.sr('path', segment_bodies, headers)
|
||||
# x-static-large-object; so no exception is raised!
|
||||
actual_md5 = md5(b''.join(sr)).hexdigest()
|
||||
self.assertEqual(sr._actual_read, 9)
|
||||
self.assertIsNone(sr._actual_md5)
|
||||
self.assertEqual(actual_md5,
|
||||
md5(b''.join(segment_bodies)).hexdigest())
|
||||
|
||||
|
||||
class _TestServiceBase(unittest.TestCase):
|
||||
def _get_mock_connection(self, attempts=2):
|
||||
|
|
Loading…
Reference in New Issue