Try decoding string to UTF-8 on error message fail

Database Errors from SQLAlchemy tend to get mangled into ASCII. If an
error is process that contains UTF-8 data in ASCII form if fails to
build the message and will lead to a 5xx error. Catch the error and try
to decode it to create the message again, if that doesn't work at least
fail gracefully.

Closes-Bug: 1253905
Change-Id: Iecb1170387c51064918780dc6de07db7ca8aeeee
(cherry picked from commit dcefe5874d)
This commit is contained in:
Jamie Lennox 2013-11-22 16:52:42 +10:00 committed by Clark Boylan
parent 152eba3a91
commit e7d6a7f94f
2 changed files with 31 additions and 1 deletions

View File

@ -14,8 +14,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import six
from keystone.common import config
from keystone.openstack.common import log as logging
from keystone.openstack.common import strutils
CONF = config.CONF
@ -56,7 +59,20 @@ class Error(StandardError):
"""
if not message:
message = self.message_format % kwargs
try:
message = self.message_format % kwargs
except UnicodeDecodeError:
try:
kwargs = dict([(k, strutils.safe_decode(v)) for k, v in
six.iteritems(kwargs)])
except UnicodeDecodeError:
# NOTE(jamielennox): This is the complete failure case
# at least by showing the template we have some idea
# of where the error is coming from
message = self.message_format
else:
message = self.message_format % kwargs
return message

View File

@ -85,6 +85,20 @@ class ExceptionTestCase(tests.TestCase):
except UnicodeEncodeError:
self.fail("unicode error message not supported")
def test_unicode_string(self):
e = exception.ValidationError(attribute='xx',
target='Long \xe2\x80\x93 Dash')
self.assertIn(u'\u2013', e.message)
def test_invalid_unicode_string(self):
# NOTE(jamielennox): This is a complete failure case so what is
# returned in the e.message is not that important so long as there is
# an error with a message
e = exception.ValidationError(attribute='xx',
target='\xe7a va')
self.assertIn('%(attribute)', e.message)
class SecurityErrorTestCase(ExceptionTestCase):
"""Tests whether security-related info is exposed to the API user."""