Merge "Make symlink work with Unicode account names"
This commit is contained in:
commit
05a6f6aad7
@ -161,7 +161,7 @@ from cgi import parse_header
|
||||
from six.moves.urllib.parse import unquote
|
||||
|
||||
from swift.common.utils import get_logger, register_swift_info, split_path, \
|
||||
MD5_OF_EMPTY_STRING, closing_if_possible
|
||||
MD5_OF_EMPTY_STRING, closing_if_possible, quote
|
||||
from swift.common.constraints import check_account_format
|
||||
from swift.common.wsgi import WSGIContext, make_subrequest
|
||||
from swift.common.request_helpers import get_sys_meta_prefix, \
|
||||
@ -208,6 +208,7 @@ def _check_symlink_header(req):
|
||||
req, TGT_OBJ_SYMLINK_HDR, 2,
|
||||
'X-Symlink-Target header must be of the '
|
||||
'form <container name>/<object name>')
|
||||
req.headers[TGT_OBJ_SYMLINK_HDR] = quote('%s/%s' % (container, obj))
|
||||
|
||||
# Check account format if it exists
|
||||
account = check_account_format(
|
||||
@ -217,7 +218,9 @@ def _check_symlink_header(req):
|
||||
# Extract request path
|
||||
_junk, req_acc, req_cont, req_obj = req.split_path(4, 4, True)
|
||||
|
||||
if not account:
|
||||
if account:
|
||||
req.headers[TGT_ACCT_SYMLINK_HDR] = quote(account)
|
||||
else:
|
||||
account = req_acc
|
||||
|
||||
# Check if symlink targets the symlink itself or not
|
||||
@ -378,9 +381,9 @@ class SymlinkObjectContext(WSGIContext):
|
||||
:returns: new request for target path if it's symlink otherwise
|
||||
None
|
||||
"""
|
||||
version, account, _junk = split_path(req.path, 2, 3, True)
|
||||
version, account, _junk = req.split_path(2, 3, True)
|
||||
account = self._response_header_value(
|
||||
TGT_ACCT_SYSMETA_SYMLINK_HDR) or account
|
||||
TGT_ACCT_SYSMETA_SYMLINK_HDR) or quote(account)
|
||||
target_path = os.path.join(
|
||||
'/', version, account,
|
||||
symlink_target.lstrip('/'))
|
||||
@ -485,7 +488,7 @@ class SymlinkObjectContext(WSGIContext):
|
||||
if tgt_co:
|
||||
version, account, _junk = req.split_path(2, 3, True)
|
||||
target_acc = self._response_header_value(
|
||||
TGT_ACCT_SYSMETA_SYMLINK_HDR) or account
|
||||
TGT_ACCT_SYSMETA_SYMLINK_HDR) or quote(account)
|
||||
location_hdr = os.path.join(
|
||||
'/', version, target_acc, tgt_co)
|
||||
req.environ['swift.leave_relative_location'] = True
|
||||
|
@ -270,23 +270,45 @@ class TestSymlink(Base):
|
||||
target_obj = 'dealde%2Fl04 011e%204c8df/flash.png'
|
||||
link_obj = uuid4().hex
|
||||
|
||||
# Now let's write a new target object and symlink will be able to
|
||||
# return object
|
||||
# create target using unnormalized path
|
||||
resp = retry(
|
||||
self._make_request, method='PUT', container=self.env.tgt_cont,
|
||||
obj=target_obj, body=TARGET_BODY)
|
||||
|
||||
self.assertEqual(resp.status, 201)
|
||||
# you can get it using either name
|
||||
resp = retry(
|
||||
self._make_request, method='GET', container=self.env.tgt_cont,
|
||||
obj=target_obj)
|
||||
self.assertEqual(resp.status, 200)
|
||||
self.assertEqual(resp.content, TARGET_BODY)
|
||||
normalized_quoted_obj = 'dealde/l04%20011e%204c8df/flash.png'
|
||||
self.assertEqual(normalized_quoted_obj, urllib.parse.quote(
|
||||
urllib.parse.unquote(target_obj)))
|
||||
resp = retry(
|
||||
self._make_request, method='GET', container=self.env.tgt_cont,
|
||||
obj=normalized_quoted_obj)
|
||||
self.assertEqual(resp.status, 200)
|
||||
self.assertEqual(resp.content, TARGET_BODY)
|
||||
|
||||
# PUT symlink
|
||||
# create a symlink using the un-normalized target path
|
||||
self._test_put_symlink(link_cont=self.env.link_cont, link_obj=link_obj,
|
||||
tgt_cont=self.env.tgt_cont,
|
||||
tgt_obj=target_obj)
|
||||
|
||||
# and it's normalized
|
||||
self._assertSymlink(
|
||||
self.env.link_cont, link_obj,
|
||||
expected_content_location="%s/%s" % (self.env.tgt_cont,
|
||||
target_obj))
|
||||
expected_content_location='%s/%s' % (
|
||||
self.env.tgt_cont, normalized_quoted_obj))
|
||||
|
||||
# create a symlink using the normalized target path
|
||||
self._test_put_symlink(link_cont=self.env.link_cont, link_obj=link_obj,
|
||||
tgt_cont=self.env.tgt_cont,
|
||||
tgt_obj=normalized_quoted_obj)
|
||||
# and it's ALSO normalized
|
||||
self._assertSymlink(
|
||||
self.env.link_cont, link_obj,
|
||||
expected_content_location='%s/%s' % (
|
||||
self.env.tgt_cont, normalized_quoted_obj))
|
||||
|
||||
def test_symlink_put_head_get(self):
|
||||
link_obj = uuid4().hex
|
||||
|
@ -18,7 +18,7 @@ from copy import deepcopy
|
||||
import json
|
||||
import time
|
||||
import unittest2
|
||||
from six.moves.urllib.parse import quote
|
||||
from six.moves.urllib.parse import quote, unquote
|
||||
|
||||
import test.functional as tf
|
||||
|
||||
@ -652,7 +652,7 @@ class TestObjectVersioning(Base):
|
||||
tgt_b.write("bbbbb")
|
||||
|
||||
symlink_name = Utils.create_name()
|
||||
sym_tgt_header = '%s/%s' % (container.name, tgt_a_name)
|
||||
sym_tgt_header = quote(unquote('%s/%s' % (container.name, tgt_a_name)))
|
||||
sym_headers_a = {'X-Symlink-Target': sym_tgt_header}
|
||||
symlink = container.file(symlink_name)
|
||||
symlink.write("", hdrs=sym_headers_a)
|
||||
@ -684,8 +684,9 @@ class TestObjectVersioning(Base):
|
||||
sym_info = symlink.info(parms={'symlink': 'get'})
|
||||
self.assertEqual("aaaaa", symlink.read())
|
||||
self.assertEqual(MD5_OF_EMPTY_STRING, sym_info['etag'])
|
||||
self.assertEqual('%s/%s' % (self.env.container.name, target.name),
|
||||
sym_info['x_symlink_target'])
|
||||
self.assertEqual(
|
||||
quote(unquote('%s/%s' % (self.env.container.name, target.name))),
|
||||
sym_info['x_symlink_target'])
|
||||
|
||||
def _setup_symlink(self):
|
||||
target = self.env.container.file('target-object')
|
||||
|
Loading…
Reference in New Issue
Block a user