ensure that we safely encode ec2 utf8 responses
The ec2 response layer assumed that all strings coming back for results were always ascii, and exploded horribly if they weren't due to the use of a str() function late in the game. This updates the code to use safe_encode correctly when the object gets rendered. This also adds unit tests for the rendering functionality in ec2/apirequest so that we can actually feel confident that it does the right things with unicode. Change-Id: I348a728e3559fdbf0d1bc66616cc278c3370cd29 Closes-Bug: #1306479
This commit is contained in:
parent
a5f09ddddf
commit
0da4d72ae6
@ -23,10 +23,12 @@ import datetime
|
|||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
|
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
|
import six
|
||||||
|
|
||||||
from nova.api.ec2 import ec2utils
|
from nova.api.ec2 import ec2utils
|
||||||
from nova import exception
|
from nova import exception
|
||||||
from nova.openstack.common import log as logging
|
from nova.openstack.common import log as logging
|
||||||
|
from nova.openstack.common import strutils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -134,6 +136,7 @@ class APIRequest(object):
|
|||||||
data_el.appendChild(
|
data_el.appendChild(
|
||||||
xml.createTextNode(_database_to_isoformat(data)))
|
xml.createTextNode(_database_to_isoformat(data)))
|
||||||
elif data is not None:
|
elif data is not None:
|
||||||
data_el.appendChild(xml.createTextNode(str(data)))
|
data_el.appendChild(xml.createTextNode(
|
||||||
|
strutils.safe_encode(six.text_type(data))))
|
||||||
|
|
||||||
return data_el
|
return data_el
|
||||||
|
73
nova/tests/api/ec2/test_apirequest.py
Normal file
73
nova/tests/api/ec2/test_apirequest.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
"""Unit tests for the API Request internals."""
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
|
from nova.api.ec2 import apirequest
|
||||||
|
from nova import test
|
||||||
|
|
||||||
|
|
||||||
|
class APIRequestTestCase(test.NoDBTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(APIRequestTestCase, self).setUp()
|
||||||
|
self.req = apirequest.APIRequest("FakeController", "FakeAction",
|
||||||
|
"FakeVersion", {})
|
||||||
|
self.resp = {
|
||||||
|
'string': 'foo',
|
||||||
|
'int': 1,
|
||||||
|
'long': long(1),
|
||||||
|
'bool': False,
|
||||||
|
'dict': {
|
||||||
|
'string': 'foo',
|
||||||
|
'int': 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# The previous will produce an output that looks like the
|
||||||
|
# following (excusing line wrap for 80 cols):
|
||||||
|
#
|
||||||
|
# <FakeActionResponse xmlns="http://ec2.amazonaws.com/doc/\
|
||||||
|
# FakeVersion/">
|
||||||
|
# <requestId>uuid</requestId>
|
||||||
|
# <int>1</int>
|
||||||
|
# <dict>
|
||||||
|
# <int>1</int>
|
||||||
|
# <string>foo</string>
|
||||||
|
# </dict>
|
||||||
|
# <bool>false</bool>
|
||||||
|
# <string>foo</string>
|
||||||
|
# </FakeActionResponse>
|
||||||
|
#
|
||||||
|
# We don't attempt to ever test for the full document because
|
||||||
|
# hash seed order might impact it's rendering order. The fact
|
||||||
|
# that running the function doesn't explode is a big part of
|
||||||
|
# the win.
|
||||||
|
|
||||||
|
def test_render_response_ascii(self):
|
||||||
|
data = self.req._render_response(self.resp, 'uuid')
|
||||||
|
self.assertIn('<FakeActionResponse xmlns="http://ec2.amazonaws.com/'
|
||||||
|
'doc/FakeVersion/', data)
|
||||||
|
self.assertIn('<int>1</int>', data)
|
||||||
|
self.assertIn('<string>foo</string>', data)
|
||||||
|
|
||||||
|
def test_render_response_utf8(self):
|
||||||
|
resp = copy.deepcopy(self.resp)
|
||||||
|
resp['utf8'] = unichr(40960) + u'abcd' + unichr(1972)
|
||||||
|
data = self.req._render_response(resp, 'uuid')
|
||||||
|
self.assertIn('<utf8>ꀀabcd޴</utf8>', data)
|
Loading…
Reference in New Issue
Block a user