Coverage for manila/api/middleware/fault.py: 100%
40 statements
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2026-02-18 22:19 +0000
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.
17from oslo_log import log
18import webob.dec
19import webob.exc
21from manila.api.openstack import wsgi
22from manila.i18n import _
23from manila import utils
24from manila.wsgi import common as base_wsgi
26LOG = log.getLogger(__name__)
29class FaultWrapper(base_wsgi.Middleware):
30 """Calls down the middleware stack, making exceptions into faults."""
32 _status_to_type = {}
34 @staticmethod
35 def status_to_type(status):
36 if not FaultWrapper._status_to_type:
37 for clazz in utils.walk_class_hierarchy(webob.exc.HTTPError):
38 FaultWrapper._status_to_type[clazz.code] = clazz
39 return FaultWrapper._status_to_type.get(
40 status, webob.exc.HTTPInternalServerError)()
42 def _error(self, inner, req):
43 if isinstance(inner, UnicodeDecodeError):
44 msg = _("Error decoding your request. Either the URL or the "
45 "request body contained characters that could not be "
46 "decoded by Manila.")
47 return wsgi.Fault(webob.exc.HTTPBadRequest(explanation=msg))
48 LOG.exception("Caught error: %s", inner)
50 safe = getattr(inner, 'safe', False)
51 headers = getattr(inner, 'headers', None)
52 status = getattr(inner, 'code', 500)
53 if status is None:
54 status = 500
56 msg_dict = dict(url=req.url, status=status)
57 LOG.info("%(url)s returned with HTTP %(status)d", msg_dict)
58 outer = self.status_to_type(status)
59 if headers:
60 outer.headers = headers
61 # NOTE(johannes): We leave the explanation empty here on
62 # purpose. It could possibly have sensitive information
63 # that should not be returned back to the user. See
64 # bugs 868360 and 874472
65 # NOTE(eglynn): However, it would be over-conservative and
66 # inconsistent with the EC2 API to hide every exception,
67 # including those that are safe to expose, see bug 1021373
68 if safe:
69 outer.explanation = '%s: %s' % (inner.__class__.__name__,
70 inner)
71 return wsgi.Fault(outer)
73 @webob.dec.wsgify(RequestClass=wsgi.Request)
74 def __call__(self, req):
75 try:
76 return req.get_response(self.application)
77 except Exception as ex:
78 return self._error(ex, req)