Coverage for manila/wsgi/common.py: 72%

30 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# Copyright 2010 OpenStack LLC. 

4# All Rights Reserved. 

5# 

6# Licensed under the Apache License, Version 2.0 (the "License"); you may 

7# not use this file except in compliance with the License. You may obtain 

8# a copy of the License at 

9# 

10# http://www.apache.org/licenses/LICENSE-2.0 

11# 

12# Unless required by applicable law or agreed to in writing, software 

13# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 

14# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 

15# License for the specific language governing permissions and limitations 

16# under the License. 

17 

18"""Utility methods for working with WSGI servers.""" 

19 

20import webob.dec 

21import webob.exc 

22 

23from manila.i18n import _ 

24 

25 

26class Request(webob.Request): 

27 pass 

28 

29 

30class Application(object): 

31 """Base WSGI application wrapper. Subclasses need to implement __call__.""" 

32 

33 @classmethod 

34 def factory(cls, global_config, **local_config): 

35 """Used for paste app factories in paste.deploy config files. 

36 

37 Any local configuration (that is, values under the [app:APPNAME] 

38 section of the paste config) will be passed into the `__init__` method 

39 as kwargs. 

40 

41 A hypothetical configuration would look like: 

42 

43 [app:wadl] 

44 latest_version = 1.3 

45 paste.app_factory = manila.api.fancy_api:Wadl.factory 

46 

47 which would result in a call to the `Wadl` class as 

48 

49 import manila.api.fancy_api 

50 fancy_api.Wadl(latest_version='1.3') 

51 

52 You could of course re-implement the `factory` method in subclasses, 

53 but using the kwarg passing it shouldn't be necessary. 

54 

55 """ 

56 return cls(**local_config) 

57 

58 def __call__(self, environ, start_response): 

59 r"""Subclasses will probably want to implement __call__ like this: 

60 

61 @webob.dec.wsgify(RequestClass=Request) 

62 def __call__(self, req): 

63 # Any of the following objects work as responses: 

64 

65 # Option 1: simple string 

66 res = 'message\n' 

67 

68 # Option 2: a nicely formatted HTTP exception page 

69 res = exc.HTTPForbidden(detail='Nice try') 

70 

71 # Option 3: a webob Response object (in case you need to play with 

72 # headers, or you want to be treated like an iterable, or or or) 

73 res = Response(); 

74 res.app_iter = open('somefile') 

75 

76 # Option 4: any wsgi app to be run next 

77 res = self.application 

78 

79 # Option 5: you can get a Response object for a wsgi app, too, to 

80 # play with headers etc 

81 res = req.get_response(self.application) 

82 

83 # You can then just return your response... 

84 return res 

85 # ... or set req.response and return None. 

86 req.response = res 

87 

88 See the end of http://pythonpaste.org/webob/modules/dec.html 

89 for more info. 

90 

91 """ 

92 raise NotImplementedError(_('You must implement __call__')) 

93 

94 

95class Middleware(Application): 

96 """Base WSGI middleware. 

97 

98 These classes require an application to be 

99 initialized that will be called next. By default the middleware will 

100 simply call its wrapped app, or you can override __call__ to customize its 

101 behavior. 

102 

103 """ 

104 

105 @classmethod 

106 def factory(cls, global_config, **local_config): 

107 """Used for paste app factories in paste.deploy config files. 

108 

109 Any local configuration (that is, values under the [filter:APPNAME] 

110 section of the paste config) will be passed into the `__init__` method 

111 as kwargs. 

112 

113 A hypothetical configuration would look like: 

114 

115 [filter:analytics] 

116 redis_host = 127.0.0.1 

117 paste.filter_factory = manila.api.analytics:Analytics.factory 

118 

119 which would result in a call to the `Analytics` class as 

120 

121 import manila.api.analytics 

122 analytics.Analytics(app_from_paste, redis_host='127.0.0.1') 

123 

124 You could of course re-implement the `factory` method in subclasses, 

125 but using the kwarg passing it shouldn't be necessary. 

126 

127 """ 

128 def _factory(app): 

129 return cls(app, **local_config) 

130 return _factory 

131 

132 def __init__(self, application): 

133 self.application = application 

134 

135 def process_request(self, req): 

136 """Called on each request. 

137 

138 If this returns None, the next application down the stack will be 

139 executed. If it returns a response then that response will be returned 

140 and execution will stop here. 

141 

142 """ 

143 return None 

144 

145 def process_response(self, response): 

146 """Do whatever you'd like to the response.""" 

147 return response 

148 

149 @webob.dec.wsgify(RequestClass=Request) 

150 def __call__(self, req): 

151 # pylint: disable=assignment-from-none 

152 response = self.process_request(req) 

153 if response: 

154 return response 

155 response = req.get_response(self.application) 

156 return self.process_response(response)