fault.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. # Copyright 2010 United States Government as represented by the
  2. # Administrator of the National Aeronautics and Space Administration.
  3. # All Rights Reserved.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  6. # not use this file except in compliance with the License. You may obtain
  7. # a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  13. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  14. # License for the specific language governing permissions and limitations
  15. # under the License.
  16. from oslo_log import log as logging
  17. import six
  18. import webob.dec
  19. import webob.exc
  20. from coriolis.api import wsgi
  21. from coriolis import exception
  22. from coriolis.i18n import _, _LE, _LI # noqa
  23. from coriolis import utils
  24. LOG = logging.getLogger(__name__)
  25. class FaultWrapper(wsgi.Middleware):
  26. """Calls down the middleware stack, making exceptions into faults."""
  27. _status_to_type = {}
  28. @staticmethod
  29. def status_to_type(status):
  30. if not FaultWrapper._status_to_type:
  31. for clazz in utils.walk_class_hierarchy(webob.exc.HTTPError):
  32. FaultWrapper._status_to_type[clazz.code] = clazz
  33. return FaultWrapper._status_to_type.get(
  34. status, webob.exc.HTTPInternalServerError)()
  35. def _error(self, inner, req):
  36. LOG.exception(_LE("Caught error: %(type)s %(error)s"),
  37. {'type': type(inner),
  38. 'error': inner})
  39. safe = getattr(inner, 'safe', False)
  40. headers = getattr(inner, 'headers', None)
  41. status = getattr(inner, 'code', 500)
  42. if status is None:
  43. status = 500
  44. msg_dict = dict(url=req.url, status=status)
  45. LOG.info(_LI("%(url)s returned with HTTP %(status)d"), msg_dict)
  46. outer = self.status_to_type(status)
  47. if headers:
  48. outer.headers = headers
  49. if safe:
  50. msg = (inner.msg if isinstance(inner, exception.CoriolisException)
  51. else six.text_type(inner))
  52. params = {'exception': inner.__class__.__name__,
  53. 'explanation': msg}
  54. outer.explanation = _('%(exception)s: %(explanation)s') % params
  55. return wsgi.Fault(outer)
  56. @webob.dec.wsgify(RequestClass=wsgi.Request)
  57. def __call__(self, req):
  58. try:
  59. return req.get_response(self.application)
  60. except Exception as ex:
  61. return self._error(ex, req)