Commit 347d33d6 by Kirill Smelkov

slapproxy: Teach slapproxy to handle non-ascii instance parameters

1. when forming instance parameters xml dict on client side, we cannot
   use str() to convert parameter_value to string - because it breaks e.g.
   this way:

   In [1]: s = u'Привет Мир!'
   In [2]: str(s)
   UnicodeEncodeError                        Traceback (most recent call

   UnicodeEncodeError: 'ascii' codec can't encode characters in position
   0-5: ordinal not in range(128)

   Fix is: convert arguments to unicode strings.

2. when decoding xml on server side it was erroneously assumed to be
   always unicode, and this way xml.encode('utf-8') fails if xml is str
   but with non-ascii characters:

   In [3]: r = 'hello world'

   In [4]: r.encode('utf-8')
   Out[4]: 'hello world'

   In [5]: t = s.encode('utf-8')

   In [6]: t
   Out[6]: '\xd0\x9f\xd1\x80\xd0\xb8\xd0\xb2\xd0\xb5\xd1\x82 \xd0\x9c\xd0\xb8\xd1\x80!'

   In [7]: t.encode('utf-8')
   UnicodeDecodeError                        Traceback (most recent call last)

   UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128)

   Fix is: don't assume xml string is unicode and decode it only, if it
           is unicode, and leave as it is if it is just str.
1 parent af7de08e
......@@ -50,10 +50,19 @@ class UnauthorizedError(Exception):
# cast everything to string, utf-8 encoded
def to_str(v):
if isinstance(v, str):
return v
if not isinstance(v, unicode):
v = unicode(v)
return v.encode('utf-8')
def xml2dict(xml):
result_dict = {}
if xml is not None and xml != '':
tree = etree.fromstring(xml.encode('utf-8'))
tree = etree.fromstring(to_str(xml))
for element in tree.iter(tag=etree.Element):
if element.tag == 'parameter':
key = element.get('id')
......@@ -70,7 +79,7 @@ def dict2xml(dictionary):
instance = etree.Element('instance')
for parameter_id, parameter_value in dictionary.iteritems():
# cast everything to string
parameter_value = str(parameter_value)
parameter_value = unicode(parameter_value)
etree.SubElement(instance, "parameter",
attrib={'id': parameter_id}).text = parameter_value
return etree.tostring(instance,
......@@ -463,6 +463,15 @@ class TestRequest(MasterMixin):
self.request('http://sr//', None, 'MyFirstInstance', 'slappart2').__dict__,
self.request('http://sr//', None, 'frontend', 'slappart2').__dict__)
def test_request_with_nonascii_parameters(self):
Verify that request with non-ascii parameters is correctly accepted
request = self.request('http://sr//', None, 'myinstance', 'slappart0',
partition_parameter_kw={'text': u'Привет Мир!'})
self.assertIsInstance(request, slapos.slap.ComputerPartition)
class TestSlaveRequest(MasterMixin):
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!