commit 9fa1d0c968977ef23e26556b0a8e8e76b32c7288 Author: Christian Heimes Date: Wed Jul 15 17:55:05 2015 +0200 Handle JSON decode error in handle_exceptions() pki.handle_exceptions() raises a JSON decode exception when the body of the HTTPException is not a valid JSON string. The JSON exception hides the true error message. The patch also fixes a bug in PKIException.from_json(). The code and ClassName attribute are now correctly set. Finally we have our first unit test. https://fedorahosted.org/pki/ticket/1488 https://fedorahosted.org/freeipa/ticket/5129 diff --git a/base/common/python/pki/__init__.py b/base/common/python/pki/__init__.py index c383cdb..39a0db7 100644 --- a/base/common/python/pki/__init__.py +++ b/base/common/python/pki/__init__.py @@ -24,6 +24,7 @@ This module contains top-level classes and functions used by the Dogtag project. from functools import wraps import os import re +import sys import requests @@ -205,10 +206,12 @@ class PKIException(Exception, ResourceMessage): :type json_value: str :return: pki.PKIException """ - ret = cls(json_value['Message'], json_value['Code'], - json_value['ClassName']) + ret = cls( + message=json_value['Message'], + code=json_value['Code'], + class_name=json_value['ClassName'] + ) for attr in json_value['Attributes']['Attribute']: - print str(attr) ret.add_attribute(attr["name"], attr["value"]) return ret @@ -293,15 +296,25 @@ def handle_exceptions(): """ Decorator to catch and re-throw PKIExceptions.""" try: return fn_call(inst, *args, **kwargs) - except requests.exceptions.HTTPError as exc: - clazz = exc.response.json()['ClassName'] - if clazz in EXCEPTION_MAPPINGS: - exception_class = EXCEPTION_MAPPINGS[clazz] - pki_exception = exception_class.from_json( - exc.response.json()) - raise pki_exception + except requests.exceptions.HTTPError: + # store exception information. json may raise another + # exception. We want to re-raise the HTTPError. + exc_type, exc_val, exc_tb = sys.exc_info() + try: + json = exc_val.response.json() + except ValueError: + # json raises ValueError. simplejson raises + # JSONDecodeError, which is a subclass of ValueError. + # re-raise original exception + raise exc_type, exc_val, exc_tb else: - raise exc + # clear reference cycle + exc_type = exc_val = exc_tb = None + clazz = json.get('ClassName') + if clazz and clazz in EXCEPTION_MAPPINGS: + exception_class = EXCEPTION_MAPPINGS[clazz] + pki_exception = exception_class.from_json(json) + raise pki_exception return handler