##// END OF EJS Templates
http-app: use filter predicate to filter out bad backends submitted into the app.
marcink -
r152:1a982f31 default
parent child Browse files
Show More
@@ -1,395 +1,403 b''
1 # RhodeCode VCSServer provides access to different vcs backends via network.
1 # RhodeCode VCSServer provides access to different vcs backends via network.
2 # Copyright (C) 2014-2017 RodeCode GmbH
2 # Copyright (C) 2014-2017 RodeCode GmbH
3 #
3 #
4 # This program is free software; you can redistribute it and/or modify
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 3 of the License, or
6 # the Free Software Foundation; either version 3 of the License, or
7 # (at your option) any later version.
7 # (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software Foundation,
15 # along with this program; if not, write to the Free Software Foundation,
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
18 import base64
18 import base64
19 import locale
19 import locale
20 import logging
20 import logging
21 import uuid
21 import uuid
22 import wsgiref.util
22 import wsgiref.util
23 import traceback
23 import traceback
24 from itertools import chain
24 from itertools import chain
25
25
26 import msgpack
26 import msgpack
27 from beaker.cache import CacheManager
27 from beaker.cache import CacheManager
28 from beaker.util import parse_cache_config_options
28 from beaker.util import parse_cache_config_options
29 from pyramid.config import Configurator
29 from pyramid.config import Configurator
30 from pyramid.wsgi import wsgiapp
30 from pyramid.wsgi import wsgiapp
31
31
32 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
32 from vcsserver import remote_wsgi, scm_app, settings, hgpatches
33 from vcsserver.echo_stub import remote_wsgi as remote_wsgi_stub
33 from vcsserver.echo_stub import remote_wsgi as remote_wsgi_stub
34 from vcsserver.echo_stub.echo_app import EchoApp
34 from vcsserver.echo_stub.echo_app import EchoApp
35 from vcsserver.exceptions import HTTPRepoLocked
35 from vcsserver.exceptions import HTTPRepoLocked
36 from vcsserver.server import VcsServer
36 from vcsserver.server import VcsServer
37
37
38 try:
38 try:
39 from vcsserver.git import GitFactory, GitRemote
39 from vcsserver.git import GitFactory, GitRemote
40 except ImportError:
40 except ImportError:
41 GitFactory = None
41 GitFactory = None
42 GitRemote = None
42 GitRemote = None
43 try:
43 try:
44 from vcsserver.hg import MercurialFactory, HgRemote
44 from vcsserver.hg import MercurialFactory, HgRemote
45 except ImportError:
45 except ImportError:
46 MercurialFactory = None
46 MercurialFactory = None
47 HgRemote = None
47 HgRemote = None
48 try:
48 try:
49 from vcsserver.svn import SubversionFactory, SvnRemote
49 from vcsserver.svn import SubversionFactory, SvnRemote
50 except ImportError:
50 except ImportError:
51 SubversionFactory = None
51 SubversionFactory = None
52 SvnRemote = None
52 SvnRemote = None
53
53
54 log = logging.getLogger(__name__)
54 log = logging.getLogger(__name__)
55
55
56
56
57 class VCS(object):
57 class VCS(object):
58 def __init__(self, locale=None, cache_config=None):
58 def __init__(self, locale=None, cache_config=None):
59 self.locale = locale
59 self.locale = locale
60 self.cache_config = cache_config
60 self.cache_config = cache_config
61 self._configure_locale()
61 self._configure_locale()
62 self._initialize_cache()
62 self._initialize_cache()
63
63
64 if GitFactory and GitRemote:
64 if GitFactory and GitRemote:
65 git_repo_cache = self.cache.get_cache_region(
65 git_repo_cache = self.cache.get_cache_region(
66 'git', region='repo_object')
66 'git', region='repo_object')
67 git_factory = GitFactory(git_repo_cache)
67 git_factory = GitFactory(git_repo_cache)
68 self._git_remote = GitRemote(git_factory)
68 self._git_remote = GitRemote(git_factory)
69 else:
69 else:
70 log.info("Git client import failed")
70 log.info("Git client import failed")
71
71
72 if MercurialFactory and HgRemote:
72 if MercurialFactory and HgRemote:
73 hg_repo_cache = self.cache.get_cache_region(
73 hg_repo_cache = self.cache.get_cache_region(
74 'hg', region='repo_object')
74 'hg', region='repo_object')
75 hg_factory = MercurialFactory(hg_repo_cache)
75 hg_factory = MercurialFactory(hg_repo_cache)
76 self._hg_remote = HgRemote(hg_factory)
76 self._hg_remote = HgRemote(hg_factory)
77 else:
77 else:
78 log.info("Mercurial client import failed")
78 log.info("Mercurial client import failed")
79
79
80 if SubversionFactory and SvnRemote:
80 if SubversionFactory and SvnRemote:
81 svn_repo_cache = self.cache.get_cache_region(
81 svn_repo_cache = self.cache.get_cache_region(
82 'svn', region='repo_object')
82 'svn', region='repo_object')
83 svn_factory = SubversionFactory(svn_repo_cache)
83 svn_factory = SubversionFactory(svn_repo_cache)
84 self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory)
84 self._svn_remote = SvnRemote(svn_factory, hg_factory=hg_factory)
85 else:
85 else:
86 log.info("Subversion client import failed")
86 log.info("Subversion client import failed")
87
87
88 self._vcsserver = VcsServer()
88 self._vcsserver = VcsServer()
89
89
90 def _initialize_cache(self):
90 def _initialize_cache(self):
91 cache_config = parse_cache_config_options(self.cache_config)
91 cache_config = parse_cache_config_options(self.cache_config)
92 log.info('Initializing beaker cache: %s' % cache_config)
92 log.info('Initializing beaker cache: %s' % cache_config)
93 self.cache = CacheManager(**cache_config)
93 self.cache = CacheManager(**cache_config)
94
94
95 def _configure_locale(self):
95 def _configure_locale(self):
96 if self.locale:
96 if self.locale:
97 log.info('Settings locale: `LC_ALL` to %s' % self.locale)
97 log.info('Settings locale: `LC_ALL` to %s' % self.locale)
98 else:
98 else:
99 log.info(
99 log.info(
100 'Configuring locale subsystem based on environment variables')
100 'Configuring locale subsystem based on environment variables')
101 try:
101 try:
102 # If self.locale is the empty string, then the locale
102 # If self.locale is the empty string, then the locale
103 # module will use the environment variables. See the
103 # module will use the environment variables. See the
104 # documentation of the package `locale`.
104 # documentation of the package `locale`.
105 locale.setlocale(locale.LC_ALL, self.locale)
105 locale.setlocale(locale.LC_ALL, self.locale)
106
106
107 language_code, encoding = locale.getlocale()
107 language_code, encoding = locale.getlocale()
108 log.info(
108 log.info(
109 'Locale set to language code "%s" with encoding "%s".',
109 'Locale set to language code "%s" with encoding "%s".',
110 language_code, encoding)
110 language_code, encoding)
111 except locale.Error:
111 except locale.Error:
112 log.exception(
112 log.exception(
113 'Cannot set locale, not configuring the locale system')
113 'Cannot set locale, not configuring the locale system')
114
114
115
115
116 class WsgiProxy(object):
116 class WsgiProxy(object):
117 def __init__(self, wsgi):
117 def __init__(self, wsgi):
118 self.wsgi = wsgi
118 self.wsgi = wsgi
119
119
120 def __call__(self, environ, start_response):
120 def __call__(self, environ, start_response):
121 input_data = environ['wsgi.input'].read()
121 input_data = environ['wsgi.input'].read()
122 input_data = msgpack.unpackb(input_data)
122 input_data = msgpack.unpackb(input_data)
123
123
124 error = None
124 error = None
125 try:
125 try:
126 data, status, headers = self.wsgi.handle(
126 data, status, headers = self.wsgi.handle(
127 input_data['environment'], input_data['input_data'],
127 input_data['environment'], input_data['input_data'],
128 *input_data['args'], **input_data['kwargs'])
128 *input_data['args'], **input_data['kwargs'])
129 except Exception as e:
129 except Exception as e:
130 data, status, headers = [], None, None
130 data, status, headers = [], None, None
131 error = {
131 error = {
132 'message': str(e),
132 'message': str(e),
133 '_vcs_kind': getattr(e, '_vcs_kind', None)
133 '_vcs_kind': getattr(e, '_vcs_kind', None)
134 }
134 }
135
135
136 start_response(200, {})
136 start_response(200, {})
137 return self._iterator(error, status, headers, data)
137 return self._iterator(error, status, headers, data)
138
138
139 def _iterator(self, error, status, headers, data):
139 def _iterator(self, error, status, headers, data):
140 initial_data = [
140 initial_data = [
141 error,
141 error,
142 status,
142 status,
143 headers,
143 headers,
144 ]
144 ]
145
145
146 for d in chain(initial_data, data):
146 for d in chain(initial_data, data):
147 yield msgpack.packb(d)
147 yield msgpack.packb(d)
148
148
149
149
150 class HTTPApplication(object):
150 class HTTPApplication(object):
151 ALLOWED_EXCEPTIONS = ('KeyError', 'URLError')
151 ALLOWED_EXCEPTIONS = ('KeyError', 'URLError')
152
152
153 remote_wsgi = remote_wsgi
153 remote_wsgi = remote_wsgi
154 _use_echo_app = False
154 _use_echo_app = False
155
155
156 def __init__(self, settings=None):
156 def __init__(self, settings=None):
157 self.config = Configurator(settings=settings)
157 self.config = Configurator(settings=settings)
158 locale = settings.get('locale', '') or 'en_US.UTF-8'
158 locale = settings.get('locale', '') or 'en_US.UTF-8'
159 vcs = VCS(locale=locale, cache_config=settings)
159 vcs = VCS(locale=locale, cache_config=settings)
160 self._remotes = {
160 self._remotes = {
161 'hg': vcs._hg_remote,
161 'hg': vcs._hg_remote,
162 'git': vcs._git_remote,
162 'git': vcs._git_remote,
163 'svn': vcs._svn_remote,
163 'svn': vcs._svn_remote,
164 'server': vcs._vcsserver,
164 'server': vcs._vcsserver,
165 }
165 }
166 if settings.get('dev.use_echo_app', 'false').lower() == 'true':
166 if settings.get('dev.use_echo_app', 'false').lower() == 'true':
167 self._use_echo_app = True
167 self._use_echo_app = True
168 log.warning("Using EchoApp for VCS operations.")
168 log.warning("Using EchoApp for VCS operations.")
169 self.remote_wsgi = remote_wsgi_stub
169 self.remote_wsgi = remote_wsgi_stub
170 self._configure_settings(settings)
170 self._configure_settings(settings)
171 self._configure()
171 self._configure()
172
172
173 def _configure_settings(self, app_settings):
173 def _configure_settings(self, app_settings):
174 """
174 """
175 Configure the settings module.
175 Configure the settings module.
176 """
176 """
177 git_path = app_settings.get('git_path', None)
177 git_path = app_settings.get('git_path', None)
178 if git_path:
178 if git_path:
179 settings.GIT_EXECUTABLE = git_path
179 settings.GIT_EXECUTABLE = git_path
180
180
181 def _configure(self):
181 def _configure(self):
182 self.config.add_renderer(
182 self.config.add_renderer(
183 name='msgpack',
183 name='msgpack',
184 factory=self._msgpack_renderer_factory)
184 factory=self._msgpack_renderer_factory)
185
185
186 self.config.add_route('service', '/_service')
186 self.config.add_route('service', '/_service')
187 self.config.add_route('status', '/status')
187 self.config.add_route('status', '/status')
188 self.config.add_route('hg_proxy', '/proxy/hg')
188 self.config.add_route('hg_proxy', '/proxy/hg')
189 self.config.add_route('git_proxy', '/proxy/git')
189 self.config.add_route('git_proxy', '/proxy/git')
190 self.config.add_route('vcs', '/{backend}')
190 self.config.add_route('vcs', '/{backend}')
191 self.config.add_route('stream_git', '/stream/git/*repo_name')
191 self.config.add_route('stream_git', '/stream/git/*repo_name')
192 self.config.add_route('stream_hg', '/stream/hg/*repo_name')
192 self.config.add_route('stream_hg', '/stream/hg/*repo_name')
193
193
194 self.config.add_view(
194 self.config.add_view(
195 self.status_view, route_name='status', renderer='json')
195 self.status_view, route_name='status', renderer='json')
196 self.config.add_view(
196 self.config.add_view(
197 self.service_view, route_name='service', renderer='msgpack')
197 self.service_view, route_name='service', renderer='msgpack')
198
198
199 self.config.add_view(self.hg_proxy(), route_name='hg_proxy')
199 self.config.add_view(self.hg_proxy(), route_name='hg_proxy')
200 self.config.add_view(self.git_proxy(), route_name='git_proxy')
200 self.config.add_view(self.git_proxy(), route_name='git_proxy')
201 self.config.add_view(
201 self.config.add_view(
202 self.vcs_view, route_name='vcs', renderer='msgpack')
202 self.vcs_view, route_name='vcs', renderer='msgpack',
203 custom_predicates=[self.is_vcs_view])
203
204
204 self.config.add_view(self.hg_stream(), route_name='stream_hg')
205 self.config.add_view(self.hg_stream(), route_name='stream_hg')
205 self.config.add_view(self.git_stream(), route_name='stream_git')
206 self.config.add_view(self.git_stream(), route_name='stream_git')
206
207
207 def notfound(request):
208 def notfound(request):
208 return {'status': '404 NOT FOUND'}
209 return {'status': '404 NOT FOUND'}
209 self.config.add_notfound_view(notfound, renderer='json')
210 self.config.add_notfound_view(notfound, renderer='json')
210
211
211 self.config.add_view(
212 self.config.add_view(
212 self.handle_vcs_exception, context=Exception,
213 self.handle_vcs_exception, context=Exception,
213 custom_predicates=[self.is_vcs_exception])
214 custom_predicates=[self.is_vcs_exception])
214
215
215 self.config.add_view(
216 self.config.add_view(
216 self.general_error_handler, context=Exception)
217 self.general_error_handler, context=Exception)
217
218
218
219 def wsgi_app(self):
219 def wsgi_app(self):
220 return self.config.make_wsgi_app()
220 return self.config.make_wsgi_app()
221
221
222 def vcs_view(self, request):
222 def vcs_view(self, request):
223 remote = self._remotes[request.matchdict['backend']]
223 remote = self._remotes[request.matchdict['backend']]
224 payload = msgpack.unpackb(request.body, use_list=True)
224 payload = msgpack.unpackb(request.body, use_list=True)
225 method = payload.get('method')
225 method = payload.get('method')
226 params = payload.get('params')
226 params = payload.get('params')
227 wire = params.get('wire')
227 wire = params.get('wire')
228 args = params.get('args')
228 args = params.get('args')
229 kwargs = params.get('kwargs')
229 kwargs = params.get('kwargs')
230 if wire:
230 if wire:
231 try:
231 try:
232 wire['context'] = uuid.UUID(wire['context'])
232 wire['context'] = uuid.UUID(wire['context'])
233 except KeyError:
233 except KeyError:
234 pass
234 pass
235 args.insert(0, wire)
235 args.insert(0, wire)
236
236
237 try:
237 try:
238 resp = getattr(remote, method)(*args, **kwargs)
238 resp = getattr(remote, method)(*args, **kwargs)
239 except Exception as e:
239 except Exception as e:
240 tb_info = traceback.format_exc()
240 tb_info = traceback.format_exc()
241
241
242 type_ = e.__class__.__name__
242 type_ = e.__class__.__name__
243 if type_ not in self.ALLOWED_EXCEPTIONS:
243 if type_ not in self.ALLOWED_EXCEPTIONS:
244 type_ = None
244 type_ = None
245
245
246 resp = {
246 resp = {
247 'id': payload.get('id'),
247 'id': payload.get('id'),
248 'error': {
248 'error': {
249 'message': e.message,
249 'message': e.message,
250 'traceback': tb_info,
250 'traceback': tb_info,
251 'type': type_
251 'type': type_
252 }
252 }
253 }
253 }
254 try:
254 try:
255 resp['error']['_vcs_kind'] = e._vcs_kind
255 resp['error']['_vcs_kind'] = e._vcs_kind
256 except AttributeError:
256 except AttributeError:
257 pass
257 pass
258 else:
258 else:
259 resp = {
259 resp = {
260 'id': payload.get('id'),
260 'id': payload.get('id'),
261 'result': resp
261 'result': resp
262 }
262 }
263
263
264 return resp
264 return resp
265
265
266 def status_view(self, request):
266 def status_view(self, request):
267 return {'status': 'OK'}
267 return {'status': 'OK'}
268
268
269 def service_view(self, request):
269 def service_view(self, request):
270 import vcsserver
270 import vcsserver
271 payload = msgpack.unpackb(request.body, use_list=True)
271 payload = msgpack.unpackb(request.body, use_list=True)
272 resp = {
272 resp = {
273 'id': payload.get('id'),
273 'id': payload.get('id'),
274 'result': dict(
274 'result': dict(
275 version=vcsserver.__version__,
275 version=vcsserver.__version__,
276 config={},
276 config={},
277 payload=payload,
277 payload=payload,
278 )
278 )
279 }
279 }
280 return resp
280 return resp
281
281
282 def _msgpack_renderer_factory(self, info):
282 def _msgpack_renderer_factory(self, info):
283 def _render(value, system):
283 def _render(value, system):
284 value = msgpack.packb(value)
284 value = msgpack.packb(value)
285 request = system.get('request')
285 request = system.get('request')
286 if request is not None:
286 if request is not None:
287 response = request.response
287 response = request.response
288 ct = response.content_type
288 ct = response.content_type
289 if ct == response.default_content_type:
289 if ct == response.default_content_type:
290 response.content_type = 'application/x-msgpack'
290 response.content_type = 'application/x-msgpack'
291 return value
291 return value
292 return _render
292 return _render
293
293
294 def hg_proxy(self):
294 def hg_proxy(self):
295 @wsgiapp
295 @wsgiapp
296 def _hg_proxy(environ, start_response):
296 def _hg_proxy(environ, start_response):
297 app = WsgiProxy(self.remote_wsgi.HgRemoteWsgi())
297 app = WsgiProxy(self.remote_wsgi.HgRemoteWsgi())
298 return app(environ, start_response)
298 return app(environ, start_response)
299 return _hg_proxy
299 return _hg_proxy
300
300
301 def git_proxy(self):
301 def git_proxy(self):
302 @wsgiapp
302 @wsgiapp
303 def _git_proxy(environ, start_response):
303 def _git_proxy(environ, start_response):
304 app = WsgiProxy(self.remote_wsgi.GitRemoteWsgi())
304 app = WsgiProxy(self.remote_wsgi.GitRemoteWsgi())
305 return app(environ, start_response)
305 return app(environ, start_response)
306 return _git_proxy
306 return _git_proxy
307
307
308 def hg_stream(self):
308 def hg_stream(self):
309 if self._use_echo_app:
309 if self._use_echo_app:
310 @wsgiapp
310 @wsgiapp
311 def _hg_stream(environ, start_response):
311 def _hg_stream(environ, start_response):
312 app = EchoApp('fake_path', 'fake_name', None)
312 app = EchoApp('fake_path', 'fake_name', None)
313 return app(environ, start_response)
313 return app(environ, start_response)
314 return _hg_stream
314 return _hg_stream
315 else:
315 else:
316 @wsgiapp
316 @wsgiapp
317 def _hg_stream(environ, start_response):
317 def _hg_stream(environ, start_response):
318 repo_path = environ['HTTP_X_RC_REPO_PATH']
318 repo_path = environ['HTTP_X_RC_REPO_PATH']
319 repo_name = environ['HTTP_X_RC_REPO_NAME']
319 repo_name = environ['HTTP_X_RC_REPO_NAME']
320 packed_config = base64.b64decode(
320 packed_config = base64.b64decode(
321 environ['HTTP_X_RC_REPO_CONFIG'])
321 environ['HTTP_X_RC_REPO_CONFIG'])
322 config = msgpack.unpackb(packed_config)
322 config = msgpack.unpackb(packed_config)
323 app = scm_app.create_hg_wsgi_app(
323 app = scm_app.create_hg_wsgi_app(
324 repo_path, repo_name, config)
324 repo_path, repo_name, config)
325
325
326 # Consitent path information for hgweb
326 # Consitent path information for hgweb
327 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
327 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
328 environ['REPO_NAME'] = repo_name
328 environ['REPO_NAME'] = repo_name
329 return app(environ, ResponseFilter(start_response))
329 return app(environ, ResponseFilter(start_response))
330 return _hg_stream
330 return _hg_stream
331
331
332 def git_stream(self):
332 def git_stream(self):
333 if self._use_echo_app:
333 if self._use_echo_app:
334 @wsgiapp
334 @wsgiapp
335 def _git_stream(environ, start_response):
335 def _git_stream(environ, start_response):
336 app = EchoApp('fake_path', 'fake_name', None)
336 app = EchoApp('fake_path', 'fake_name', None)
337 return app(environ, start_response)
337 return app(environ, start_response)
338 return _git_stream
338 return _git_stream
339 else:
339 else:
340 @wsgiapp
340 @wsgiapp
341 def _git_stream(environ, start_response):
341 def _git_stream(environ, start_response):
342 repo_path = environ['HTTP_X_RC_REPO_PATH']
342 repo_path = environ['HTTP_X_RC_REPO_PATH']
343 repo_name = environ['HTTP_X_RC_REPO_NAME']
343 repo_name = environ['HTTP_X_RC_REPO_NAME']
344 packed_config = base64.b64decode(
344 packed_config = base64.b64decode(
345 environ['HTTP_X_RC_REPO_CONFIG'])
345 environ['HTTP_X_RC_REPO_CONFIG'])
346 config = msgpack.unpackb(packed_config)
346 config = msgpack.unpackb(packed_config)
347
347
348 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
348 environ['PATH_INFO'] = environ['HTTP_X_RC_PATH_INFO']
349 app = scm_app.create_git_wsgi_app(
349 app = scm_app.create_git_wsgi_app(
350 repo_path, repo_name, config)
350 repo_path, repo_name, config)
351 return app(environ, start_response)
351 return app(environ, start_response)
352 return _git_stream
352 return _git_stream
353
353
354 def is_vcs_view(self, context, request):
355 """
356 View predicate that returns true if given backend is supported by
357 defined remotes.
358 """
359 backend = request.matchdict.get('backend')
360 return backend in self._remotes
361
354 def is_vcs_exception(self, context, request):
362 def is_vcs_exception(self, context, request):
355 """
363 """
356 View predicate that returns true if the context object is a VCS
364 View predicate that returns true if the context object is a VCS
357 exception.
365 exception.
358 """
366 """
359 return hasattr(context, '_vcs_kind')
367 return hasattr(context, '_vcs_kind')
360
368
361 def handle_vcs_exception(self, exception, request):
369 def handle_vcs_exception(self, exception, request):
362 if exception._vcs_kind == 'repo_locked':
370 if exception._vcs_kind == 'repo_locked':
363 # Get custom repo-locked status code if present.
371 # Get custom repo-locked status code if present.
364 status_code = request.headers.get('X-RC-Locked-Status-Code')
372 status_code = request.headers.get('X-RC-Locked-Status-Code')
365 return HTTPRepoLocked(
373 return HTTPRepoLocked(
366 title=exception.message, status_code=status_code)
374 title=exception.message, status_code=status_code)
367
375
368 # Re-raise exception if we can not handle it.
376 # Re-raise exception if we can not handle it.
369 raise exception
377 raise exception
370
378
371 def general_error_handler(self, exception, request):
379 def general_error_handler(self, exception, request):
372 log.exception(
380 log.exception(
373 'error occurred handling this request for path: %s',
381 'error occurred handling this request for path: %s',
374 request.path)
382 request.path)
375 raise exception
383 raise exception
376
384
377
385
378 class ResponseFilter(object):
386 class ResponseFilter(object):
379
387
380 def __init__(self, start_response):
388 def __init__(self, start_response):
381 self._start_response = start_response
389 self._start_response = start_response
382
390
383 def __call__(self, status, response_headers, exc_info=None):
391 def __call__(self, status, response_headers, exc_info=None):
384 headers = tuple(
392 headers = tuple(
385 (h, v) for h, v in response_headers
393 (h, v) for h, v in response_headers
386 if not wsgiref.util.is_hop_by_hop(h))
394 if not wsgiref.util.is_hop_by_hop(h))
387 return self._start_response(status, headers, exc_info)
395 return self._start_response(status, headers, exc_info)
388
396
389
397
390 def main(global_config, **settings):
398 def main(global_config, **settings):
391 if MercurialFactory:
399 if MercurialFactory:
392 hgpatches.patch_largefiles_capabilities()
400 hgpatches.patch_largefiles_capabilities()
393 hgpatches.patch_subrepo_type_mapping()
401 hgpatches.patch_subrepo_type_mapping()
394 app = HTTPApplication(settings=settings)
402 app = HTTPApplication(settings=settings)
395 return app.wsgi_app()
403 return app.wsgi_app()
General Comments 0
You need to be logged in to leave comments. Login now