Merge "Container sync no longer sending swift_bytes value"
This commit is contained in:
@@ -2688,6 +2688,14 @@ def override_bytes_from_content_type(listing_dict, logger=None):
|
|||||||
listing_dict['content_type'] = content_type
|
listing_dict['content_type'] = content_type
|
||||||
|
|
||||||
|
|
||||||
|
def clean_content_type(value):
|
||||||
|
if ';' in value:
|
||||||
|
left, right = value.rsplit(';', 1)
|
||||||
|
if right.lstrip().startswith('swift_bytes='):
|
||||||
|
return left
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def quote(value, safe='/'):
|
def quote(value, safe='/'):
|
||||||
"""
|
"""
|
||||||
Patched version of urllib.quote that encodes utf-8 strings before quoting
|
Patched version of urllib.quote that encodes utf-8 strings before quoting
|
||||||
|
@@ -29,9 +29,10 @@ from swift.common.direct_client import direct_get_object
|
|||||||
from swift.common.internal_client import delete_object, put_object
|
from swift.common.internal_client import delete_object, put_object
|
||||||
from swift.common.exceptions import ClientException
|
from swift.common.exceptions import ClientException
|
||||||
from swift.common.ring import Ring
|
from swift.common.ring import Ring
|
||||||
from swift.common.utils import audit_location_generator, get_logger, \
|
from swift.common.utils import (
|
||||||
hash_path, config_true_value, validate_sync_to, whataremyips, \
|
audit_location_generator, clean_content_type, config_true_value,
|
||||||
FileLikeIter, urlparse, quote
|
FileLikeIter, get_logger, hash_path, quote, urlparse, validate_sync_to,
|
||||||
|
whataremyips)
|
||||||
from swift.common.daemon import Daemon
|
from swift.common.daemon import Daemon
|
||||||
from swift.common.http import HTTP_UNAUTHORIZED, HTTP_NOT_FOUND
|
from swift.common.http import HTTP_UNAUTHORIZED, HTTP_NOT_FOUND
|
||||||
|
|
||||||
@@ -403,6 +404,9 @@ class ContainerSync(Daemon):
|
|||||||
del headers[key]
|
del headers[key]
|
||||||
if 'etag' in headers:
|
if 'etag' in headers:
|
||||||
headers['etag'] = headers['etag'].strip('"')
|
headers['etag'] = headers['etag'].strip('"')
|
||||||
|
if 'content-type' in headers:
|
||||||
|
headers['content-type'] = clean_content_type(
|
||||||
|
headers['content-type'])
|
||||||
headers['x-timestamp'] = row['created_at']
|
headers['x-timestamp'] = row['created_at']
|
||||||
if realm and realm_key:
|
if realm and realm_key:
|
||||||
nonce = uuid.uuid4().hex
|
nonce = uuid.uuid4().hex
|
||||||
|
@@ -35,9 +35,10 @@ from eventlet import GreenPile
|
|||||||
from eventlet.queue import Queue
|
from eventlet.queue import Queue
|
||||||
from eventlet.timeout import Timeout
|
from eventlet.timeout import Timeout
|
||||||
|
|
||||||
from swift.common.utils import ContextPool, normalize_timestamp, \
|
from swift.common.utils import (
|
||||||
config_true_value, public, json, csv_append, GreenthreadSafeIterator, \
|
clean_content_type, config_true_value, ContextPool, csv_append,
|
||||||
quorum_size, GreenAsyncPile, normalize_delete_at_timestamp
|
GreenAsyncPile, GreenthreadSafeIterator, json,
|
||||||
|
normalize_delete_at_timestamp, normalize_timestamp, public, quorum_size)
|
||||||
from swift.common.bufferedhttp import http_connect
|
from swift.common.bufferedhttp import http_connect
|
||||||
from swift.common.constraints import check_metadata, check_object_creation, \
|
from swift.common.constraints import check_metadata, check_object_creation, \
|
||||||
check_copy_from_header
|
check_copy_from_header
|
||||||
@@ -206,11 +207,8 @@ class ObjectController(Controller):
|
|||||||
req.swift_entity_path)
|
req.swift_entity_path)
|
||||||
|
|
||||||
if ';' in resp.headers.get('content-type', ''):
|
if ';' in resp.headers.get('content-type', ''):
|
||||||
# strip off swift_bytes from content-type
|
resp.content_type = clean_content_type(
|
||||||
content_type, check_extra_meta = \
|
resp.headers['content-type'])
|
||||||
resp.headers['content-type'].rsplit(';', 1)
|
|
||||||
if check_extra_meta.lstrip().startswith('swift_bytes='):
|
|
||||||
resp.content_type = content_type
|
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
@public
|
@public
|
||||||
|
@@ -1962,6 +1962,22 @@ cluster_dfw1 = http://dfw1.host/v1/
|
|||||||
self.assertEquals(listing_dict['content_type'],
|
self.assertEquals(listing_dict['content_type'],
|
||||||
'text/plain;hello="world"')
|
'text/plain;hello="world"')
|
||||||
|
|
||||||
|
def test_clean_content_type(self):
|
||||||
|
subtests = {
|
||||||
|
'': '', 'text/plain': 'text/plain',
|
||||||
|
'text/plain; someother=thing': 'text/plain; someother=thing',
|
||||||
|
'text/plain; swift_bytes=123': 'text/plain',
|
||||||
|
'text/plain; someother=thing; swift_bytes=123':
|
||||||
|
'text/plain; someother=thing',
|
||||||
|
# Since Swift always tacks on the swift_bytes, clean_content_type()
|
||||||
|
# only strips swift_bytes if it's last. The next item simply shows
|
||||||
|
# that if for some other odd reason it's not last,
|
||||||
|
# clean_content_type() will not remove it from the header.
|
||||||
|
'text/plain; swift_bytes=123; someother=thing':
|
||||||
|
'text/plain; swift_bytes=123; someother=thing'}
|
||||||
|
for before, after in subtests.items():
|
||||||
|
self.assertEqual(utils.clean_content_type(before), after)
|
||||||
|
|
||||||
def test_quote(self):
|
def test_quote(self):
|
||||||
res = utils.quote('/v1/a/c3/subdirx/')
|
res = utils.quote('/v1/a/c3/subdirx/')
|
||||||
assert res == '/v1/a/c3/subdirx/'
|
assert res == '/v1/a/c3/subdirx/'
|
||||||
|
@@ -751,13 +751,15 @@ class TestContainerSync(unittest.TestCase):
|
|||||||
'US abcdef ef62c64bb88a33fa00722daa23d5d43253164962',
|
'US abcdef ef62c64bb88a33fa00722daa23d5d43253164962',
|
||||||
'x-timestamp': '1.2',
|
'x-timestamp': '1.2',
|
||||||
'etag': 'etagvalue',
|
'etag': 'etagvalue',
|
||||||
'other-header': 'other header value'})
|
'other-header': 'other header value',
|
||||||
|
'content-type': 'text/plain'})
|
||||||
else:
|
else:
|
||||||
self.assertEquals(headers, {
|
self.assertEquals(headers, {
|
||||||
'x-container-sync-key': 'key',
|
'x-container-sync-key': 'key',
|
||||||
'x-timestamp': '1.2',
|
'x-timestamp': '1.2',
|
||||||
'other-header': 'other header value',
|
'other-header': 'other header value',
|
||||||
'etag': 'etagvalue'})
|
'etag': 'etagvalue',
|
||||||
|
'content-type': 'text/plain'})
|
||||||
self.assertEquals(contents.read(), 'contents')
|
self.assertEquals(contents.read(), 'contents')
|
||||||
self.assertEquals(proxy, 'http://proxy')
|
self.assertEquals(proxy, 'http://proxy')
|
||||||
|
|
||||||
@@ -770,7 +772,8 @@ class TestContainerSync(unittest.TestCase):
|
|||||||
def fake_direct_get_object(node, part, account, container, obj,
|
def fake_direct_get_object(node, part, account, container, obj,
|
||||||
resp_chunk_size=1):
|
resp_chunk_size=1):
|
||||||
return ({'other-header': 'other header value',
|
return ({'other-header': 'other header value',
|
||||||
'etag': '"etagvalue"', 'x-timestamp': '1.2'},
|
'etag': '"etagvalue"', 'x-timestamp': '1.2',
|
||||||
|
'content-type': 'text/plain; swift_bytes=123'},
|
||||||
iter('contents'))
|
iter('contents'))
|
||||||
|
|
||||||
sync.direct_get_object = fake_direct_get_object
|
sync.direct_get_object = fake_direct_get_object
|
||||||
@@ -790,7 +793,8 @@ class TestContainerSync(unittest.TestCase):
|
|||||||
'last-modified': 'last modified value',
|
'last-modified': 'last modified value',
|
||||||
'x-timestamp': '1.2',
|
'x-timestamp': '1.2',
|
||||||
'other-header': 'other header value',
|
'other-header': 'other header value',
|
||||||
'etag': '"etagvalue"'},
|
'etag': '"etagvalue"',
|
||||||
|
'content-type': 'text/plain; swift_bytes=123'},
|
||||||
iter('contents'))
|
iter('contents'))
|
||||||
|
|
||||||
sync.direct_get_object = fake_direct_get_object
|
sync.direct_get_object = fake_direct_get_object
|
||||||
|
Reference in New Issue
Block a user