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