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
« 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.
18"""Utility methods for working with WSGI servers."""
20import webob.dec
21import webob.exc
23from manila.i18n import _
26class Request(webob.Request):
27 pass
30class Application(object):
31 """Base WSGI application wrapper. Subclasses need to implement __call__."""
33 @classmethod
34 def factory(cls, global_config, **local_config):
35 """Used for paste app factories in paste.deploy config files.
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.
41 A hypothetical configuration would look like:
43 [app:wadl]
44 latest_version = 1.3
45 paste.app_factory = manila.api.fancy_api:Wadl.factory
47 which would result in a call to the `Wadl` class as
49 import manila.api.fancy_api
50 fancy_api.Wadl(latest_version='1.3')
52 You could of course re-implement the `factory` method in subclasses,
53 but using the kwarg passing it shouldn't be necessary.
55 """
56 return cls(**local_config)
58 def __call__(self, environ, start_response):
59 r"""Subclasses will probably want to implement __call__ like this:
61 @webob.dec.wsgify(RequestClass=Request)
62 def __call__(self, req):
63 # Any of the following objects work as responses:
65 # Option 1: simple string
66 res = 'message\n'
68 # Option 2: a nicely formatted HTTP exception page
69 res = exc.HTTPForbidden(detail='Nice try')
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')
76 # Option 4: any wsgi app to be run next
77 res = self.application
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)
83 # You can then just return your response...
84 return res
85 # ... or set req.response and return None.
86 req.response = res
88 See the end of http://pythonpaste.org/webob/modules/dec.html
89 for more info.
91 """
92 raise NotImplementedError(_('You must implement __call__'))
95class Middleware(Application):
96 """Base WSGI middleware.
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.
103 """
105 @classmethod
106 def factory(cls, global_config, **local_config):
107 """Used for paste app factories in paste.deploy config files.
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.
113 A hypothetical configuration would look like:
115 [filter:analytics]
116 redis_host = 127.0.0.1
117 paste.filter_factory = manila.api.analytics:Analytics.factory
119 which would result in a call to the `Analytics` class as
121 import manila.api.analytics
122 analytics.Analytics(app_from_paste, redis_host='127.0.0.1')
124 You could of course re-implement the `factory` method in subclasses,
125 but using the kwarg passing it shouldn't be necessary.
127 """
128 def _factory(app):
129 return cls(app, **local_config)
130 return _factory
132 def __init__(self, application):
133 self.application = application
135 def process_request(self, req):
136 """Called on each request.
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.
142 """
143 return None
145 def process_response(self, response):
146 """Do whatever you'd like to the response."""
147 return response
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)