##// END OF EJS Templates
wsgi-stack: Refactor the error handling view into a middleware class.
Martin Bornhold -
r944:7f7e85a7 default
parent child Browse files
Show More
@@ -0,0 +1,104 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2016-2016 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21
22 import logging
23
24 from pyramid import httpexceptions
25 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
26 from pyramid.threadlocal import get_current_request
27
28 from rhodecode.lib.exceptions import VCSServerUnavailable
29 from rhodecode.lib.vcs.exceptions import VCSCommunicationError
30
31
32 log = logging.getLogger(__name__)
33
34
35 class PylonsErrorHandlingMiddleware(object):
36 """
37 This middleware is wrapped around the old pylons application to catch
38 errors and invoke our error handling view to return a proper error page.
39 """
40 def __init__(self, app, error_view, reraise=False):
41 self.app = app
42 self.error_view = error_view
43 self.reraise = reraise
44
45 def __call__(self, environ, start_response):
46 # We need to use the pyramid request here instead of creating a custom
47 # instance from the environ because this request maybe passed to the
48 # error handler view which is a pyramid view and expects a pyramid
49 # request which has been processed by the pyramid router.
50 request = get_current_request()
51
52 response = self.handle_request(request)
53 return response(environ, start_response)
54
55 def is_vcs_response(self, response):
56 return 'X-RhodeCode-Backend' in response.headers
57
58 def is_http_error(self, response):
59 # webob type error responses
60 return (400 <= response.status_int <= 599)
61
62 def is_error_handling_needed(self, response):
63 return (self.is_http_error(response) and not
64 self.is_vcs_response(response))
65
66 def handle_request(self, request):
67 """
68 Calls the underlying WSGI app (typically the old RhodeCode pylons app)
69 and returns the response if no error happened. In case of an error it
70 invokes the error handling view to return a proper error page as
71 response.
72
73 - old webob type exceptions get converted to pyramid exceptions
74 - pyramid exceptions are passed to the error handler view
75 """
76 try:
77 response = request.get_response(self.app)
78 if self.is_error_handling_needed(response):
79 response = webob_to_pyramid_http_response(response)
80 return self.error_view(response, request)
81 except HTTPError as e: # pyramid type exceptions
82 return self.error_view(e, request)
83 except Exception as e:
84 log.exception(e)
85
86 if self.reraise:
87 raise
88
89 if isinstance(e, VCSCommunicationError):
90 return self.error_view(VCSServerUnavailable(), request)
91
92 return self.error_view(HTTPInternalServerError(), request)
93
94 return response
95
96
97 def webob_to_pyramid_http_response(webob_response):
98 ResponseClass = httpexceptions.status_map[webob_response.status_int]
99 pyramid_response = ResponseClass(webob_response.status)
100 pyramid_response.status = webob_response.status
101 pyramid_response.headers.update(webob_response.headers)
102 if pyramid_response.headers['content-type'] == 'text/html':
103 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
104 return pyramid_response
General Comments 0
You need to be logged in to leave comments. Login now