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

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 

17from oslo_log import log 

18import webob.dec 

19import webob.exc 

20 

21from manila.api.openstack import wsgi 

22from manila.i18n import _ 

23from manila import utils 

24from manila.wsgi import common as base_wsgi 

25 

26LOG = log.getLogger(__name__) 

27 

28 

29class FaultWrapper(base_wsgi.Middleware): 

30 """Calls down the middleware stack, making exceptions into faults.""" 

31 

32 _status_to_type = {} 

33 

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)() 

41 

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) 

49 

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 

55 

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) 

72 

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)