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:
Clay Gerrard 2024-04-17 13:59:56 -05:00 committed by Yan Xiao
parent ce4fb27b53
commit e9fd8df3f0
5 changed files with 58 additions and 3 deletions

View File

@ -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

View File

@ -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()

View File

@ -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 = ''

View File

@ -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)

View File

@ -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):