Show More
@@ -8,7 +8,6 b'' | |||||
8 |
|
8 | |||
9 | [DEFAULT] |
|
9 | [DEFAULT] | |
10 | debug = true |
|
10 | debug = true | |
11 | pdebug = false |
|
|||
12 | ################################################################################ |
|
11 | ################################################################################ | |
13 | ## Uncomment and replace with the email address which should receive ## |
|
12 | ## Uncomment and replace with the email address which should receive ## | |
14 | ## any error reports after an application crash ## |
|
13 | ## any error reports after an application crash ## |
@@ -8,7 +8,6 b'' | |||||
8 |
|
8 | |||
9 | [DEFAULT] |
|
9 | [DEFAULT] | |
10 | debug = true |
|
10 | debug = true | |
11 | pdebug = false |
|
|||
12 | ################################################################################ |
|
11 | ################################################################################ | |
13 | ## Uncomment and replace with the email address which should receive ## |
|
12 | ## Uncomment and replace with the email address which should receive ## | |
14 | ## any error reports after an application crash ## |
|
13 | ## any error reports after an application crash ## |
@@ -25,13 +25,15 b' import logging' | |||||
25 |
|
25 | |||
26 | from paste.registry import RegistryManager |
|
26 | from paste.registry import RegistryManager | |
27 | from paste.gzipper import make_gzip_middleware |
|
27 | from paste.gzipper import make_gzip_middleware | |
28 | from pylons.middleware import ErrorHandler, StatusCodeRedirect |
|
|||
29 | from pylons.wsgiapp import PylonsApp |
|
28 | from pylons.wsgiapp import PylonsApp | |
30 | from pyramid.authorization import ACLAuthorizationPolicy |
|
29 | from pyramid.authorization import ACLAuthorizationPolicy | |
31 | from pyramid.config import Configurator |
|
30 | from pyramid.config import Configurator | |
32 | from pyramid.static import static_view |
|
31 | from pyramid.static import static_view | |
33 | from pyramid.settings import asbool, aslist |
|
32 | from pyramid.settings import asbool, aslist | |
34 | from pyramid.wsgi import wsgiapp |
|
33 | from pyramid.wsgi import wsgiapp | |
|
34 | from pyramid.httpexceptions import HTTPError | |||
|
35 | import pyramid.httpexceptions as httpexceptions | |||
|
36 | from pyramid.renderers import render_to_response | |||
35 | from routes.middleware import RoutesMiddleware |
|
37 | from routes.middleware import RoutesMiddleware | |
36 | import routes.util |
|
38 | import routes.util | |
37 |
|
39 | |||
@@ -87,38 +89,15 b' def make_app(global_conf, full_stack=Tru' | |||||
87 | app = csrf.OriginChecker(app, expected_origin, |
|
89 | app = csrf.OriginChecker(app, expected_origin, | |
88 | skip_urls=[routes.util.url_for('api')]) |
|
90 | skip_urls=[routes.util.url_for('api')]) | |
89 |
|
91 | |||
90 | # Add RoutesMiddleware. Currently we have two instances in the stack. This |
|
|||
91 | # is the lower one to make the StatusCodeRedirect middleware happy. |
|
|||
92 | # TODO: johbo: This is not optimal, search for a better solution. |
|
|||
93 | app = RoutesMiddleware(app, config['routes.map']) |
|
|||
94 |
|
||||
95 | # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) |
|
|||
96 | if asbool(config['pdebug']): |
|
|||
97 | from rhodecode.lib.profiler import ProfilingMiddleware |
|
|||
98 | app = ProfilingMiddleware(app) |
|
|||
99 |
|
||||
100 | # Protect from VCS Server error related pages when server is not available |
|
|||
101 | vcs_server_enabled = asbool(config.get('vcs.server.enable', 'true')) |
|
|||
102 | if not vcs_server_enabled: |
|
|||
103 | app = DisableVCSPagesWrapper(app) |
|
|||
104 |
|
92 | |||
105 | if asbool(full_stack): |
|
93 | if asbool(full_stack): | |
106 |
|
94 | |||
107 | # Appenlight monitoring and error handler |
|
95 | # Appenlight monitoring and error handler | |
108 | app, appenlight_client = wrap_in_appenlight_if_enabled(app, config) |
|
96 | app, appenlight_client = wrap_in_appenlight_if_enabled(app, config) | |
109 |
|
97 | |||
110 | # Handle Python exceptions |
|
|||
111 | app = ErrorHandler(app, global_conf, **config['pylons.errorware']) |
|
|||
112 |
|
||||
113 | # we want our low level middleware to get to the request ASAP. We don't |
|
98 | # we want our low level middleware to get to the request ASAP. We don't | |
114 | # need any pylons stack middleware in them |
|
99 | # need any pylons stack middleware in them | |
115 | app = VCSMiddleware(app, config, appenlight_client) |
|
100 | app = VCSMiddleware(app, config, appenlight_client) | |
116 | # Display error documents for 401, 403, 404 status codes (and |
|
|||
117 | # 500 when debug is disabled) |
|
|||
118 | if asbool(config['debug']): |
|
|||
119 | app = StatusCodeRedirect(app) |
|
|||
120 | else: |
|
|||
121 | app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) |
|
|||
122 |
|
101 | |||
123 | # enable https redirects based on HTTP_X_URL_SCHEME set by proxy |
|
102 | # enable https redirects based on HTTP_X_URL_SCHEME set by proxy | |
124 | app = HttpsFixup(app, config) |
|
103 | app = HttpsFixup(app, config) | |
@@ -179,6 +158,36 b' def add_pylons_compat_data(registry, glo' | |||||
179 | registry._pylons_compat_settings = settings |
|
158 | registry._pylons_compat_settings = settings | |
180 |
|
159 | |||
181 |
|
160 | |||
|
161 | def error_handler(exc, request): | |||
|
162 | # TODO: dan: replace the old pylons error controller with this | |||
|
163 | from rhodecode.model.settings import SettingsModel | |||
|
164 | from rhodecode.lib.utils2 import AttributeDict | |||
|
165 | ||||
|
166 | try: | |||
|
167 | rc_config = SettingsModel().get_all_settings() | |||
|
168 | except Exception: | |||
|
169 | log.exception('failed to fetch settings') | |||
|
170 | rc_config = {} | |||
|
171 | ||||
|
172 | c = AttributeDict() | |||
|
173 | c.error_message = exc.status | |||
|
174 | c.error_explanation = exc.explanation or str(exc) | |||
|
175 | c.visual = AttributeDict() | |||
|
176 | ||||
|
177 | c.visual.rhodecode_support_url = ( | |||
|
178 | request.registry.settings.get('rhodecode_support_url') or | |||
|
179 | request.route_url('rhodecode_support') | |||
|
180 | ) | |||
|
181 | c.redirect_time = 0 | |||
|
182 | c.rhodecode_name = rc_config.get('rhodecode_title') | |||
|
183 | if not c.rhodecode_name: | |||
|
184 | c.rhodecode_name = 'Rhodecode' | |||
|
185 | ||||
|
186 | response = render_to_response( | |||
|
187 | '/errors/error_document.html', {'c': c}, request=request) | |||
|
188 | return response | |||
|
189 | ||||
|
190 | ||||
182 | def includeme(config): |
|
191 | def includeme(config): | |
183 | settings = config.registry.settings |
|
192 | settings = config.registry.settings | |
184 |
|
193 | |||
@@ -189,6 +198,8 b' def includeme(config):' | |||||
189 | config.include('rhodecode.login') |
|
198 | config.include('rhodecode.login') | |
190 | config.include('rhodecode.tweens') |
|
199 | config.include('rhodecode.tweens') | |
191 | config.include('rhodecode.api') |
|
200 | config.include('rhodecode.api') | |
|
201 | config.add_route( | |||
|
202 | 'rhodecode_support', 'https://rhodecode.com/help/', static=True) | |||
192 |
|
203 | |||
193 | # Set the authorization policy. |
|
204 | # Set the authorization policy. | |
194 | authz_policy = ACLAuthorizationPolicy() |
|
205 | authz_policy = ACLAuthorizationPolicy() | |
@@ -207,17 +218,43 b' def includeme(config):' | |||||
207 | for inc in includes: |
|
218 | for inc in includes: | |
208 | config.include(inc) |
|
219 | config.include(inc) | |
209 |
|
220 | |||
|
221 | pylons_app = make_app( | |||
|
222 | config.registry._pylons_compat_global_config, | |||
|
223 | **config.registry._pylons_compat_settings) | |||
|
224 | config.registry._pylons_compat_config = pylons_app.config | |||
|
225 | ||||
|
226 | pylons_app_as_view = wsgiapp(pylons_app) | |||
|
227 | ||||
|
228 | # Protect from VCS Server error related pages when server is not available | |||
|
229 | vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true')) | |||
|
230 | if not vcs_server_enabled: | |||
|
231 | pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view) | |||
|
232 | ||||
|
233 | ||||
|
234 | def pylons_app_with_error_handler(context, request): | |||
|
235 | """ | |||
|
236 | Handle exceptions from rc pylons app: | |||
|
237 | ||||
|
238 | - old webob type exceptions get converted to pyramid exceptions | |||
|
239 | - pyramid exceptions are passed to the error handler view | |||
|
240 | """ | |||
|
241 | try: | |||
|
242 | response = pylons_app_as_view(context, request) | |||
|
243 | if 400 <= response.status_int <= 599: # webob type error responses | |||
|
244 | ExcClass = httpexceptions.status_map[response.status_int] | |||
|
245 | return error_handler(ExcClass(response.status), request) | |||
|
246 | except HTTPError as e: # pyramid type exceptions | |||
|
247 | return error_handler(e, request) | |||
|
248 | ||||
|
249 | return response | |||
|
250 | ||||
210 | # This is the glue which allows us to migrate in chunks. By registering the |
|
251 | # This is the glue which allows us to migrate in chunks. By registering the | |
211 | # pylons based application as the "Not Found" view in Pyramid, we will |
|
252 | # pylons based application as the "Not Found" view in Pyramid, we will | |
212 | # fallback to the old application each time the new one does not yet know |
|
253 | # fallback to the old application each time the new one does not yet know | |
213 | # how to handle a request. |
|
254 | # how to handle a request. | |
214 | pylons_app = make_app( |
|
255 | config.add_notfound_view(pylons_app_with_error_handler) | |
215 | config.registry._pylons_compat_global_config, |
|
|||
216 | **config.registry._pylons_compat_settings) |
|
|||
217 | config.registry._pylons_compat_config = pylons_app.config |
|
|||
218 | pylons_app_as_view = wsgiapp(pylons_app) |
|
|||
219 | config.add_notfound_view(pylons_app_as_view) |
|
|||
220 |
|
256 | |||
|
257 | config.add_view(error_handler, context=HTTPError) # exceptions in rc pyramid | |||
221 |
|
258 | |||
222 | def includeme_last(config): |
|
259 | def includeme_last(config): | |
223 | """ |
|
260 | """ | |
@@ -253,8 +290,7 b' def wrap_app_in_wsgi_middlewares(pyramid' | |||||
253 | """ |
|
290 | """ | |
254 | settings = config.registry.settings |
|
291 | settings = config.registry.settings | |
255 |
|
292 | |||
256 | # Add RoutesMiddleware. Currently we have two instances in the stack. This |
|
293 | # Add RoutesMiddleware to support the pylons compatibility tween during | |
257 | # is the upper one to support the pylons compatibility tween during |
|
|||
258 | # migration to pyramid. |
|
294 | # migration to pyramid. | |
259 | pyramid_app = RoutesMiddleware( |
|
295 | pyramid_app = RoutesMiddleware( | |
260 | pyramid_app, config.registry._pylons_compat_config['routes.map']) |
|
296 | pyramid_app, config.registry._pylons_compat_config['routes.map']) |
@@ -166,10 +166,6 b' def make_map(config):' | |||||
166 | def check_int(environ, match_dict): |
|
166 | def check_int(environ, match_dict): | |
167 | return match_dict.get('id').isdigit() |
|
167 | return match_dict.get('id').isdigit() | |
168 |
|
168 | |||
169 | # The ErrorController route (handles 404/500 error pages); it should |
|
|||
170 | # likely stay at the top, ensuring it can always be resolved |
|
|||
171 | rmap.connect('/error/{action}', controller='error') |
|
|||
172 | rmap.connect('/error/{action}/{id}', controller='error') |
|
|||
173 |
|
169 | |||
174 | #========================================================================== |
|
170 | #========================================================================== | |
175 | # CUSTOM ROUTES HERE |
|
171 | # CUSTOM ROUTES HERE |
@@ -24,15 +24,21 b' Disable VCS pages when VCS Server is not' | |||||
24 |
|
24 | |||
25 | import logging |
|
25 | import logging | |
26 | import re |
|
26 | import re | |
27 |
|
27 | from pyramid.httpexceptions import HTTPBadGateway | ||
28 |
|
28 | |||
29 | log = logging.getLogger(__name__) |
|
29 | log = logging.getLogger(__name__) | |
30 |
|
30 | |||
31 |
|
31 | |||
|
32 | class VCSServerUnavailable(HTTPBadGateway): | |||
|
33 | """ HTTP Exception class for when VCS Server is unavailable """ | |||
|
34 | code = 502 | |||
|
35 | title = 'VCS Server Required' | |||
|
36 | explanation = 'A VCS Server is required for this action. There is currently no VCS Server configured.' | |||
|
37 | ||||
32 | class DisableVCSPagesWrapper(object): |
|
38 | class DisableVCSPagesWrapper(object): | |
33 | """ |
|
39 | """ | |
34 |
|
|
40 | Pyramid view wrapper to disable all pages that require VCS Server to be | |
35 | avoiding that errors explode to the user. |
|
41 | running, avoiding that errors explode to the user. | |
36 |
|
42 | |||
37 | This Wrapper should be enabled only in case VCS Server is not available |
|
43 | This Wrapper should be enabled only in case VCS Server is not available | |
38 | for the instance. |
|
44 | for the instance. | |
@@ -60,11 +66,11 b' class DisableVCSPagesWrapper(object):' | |||||
60 | log.debug('accessing: `%s` with VCS Server disabled', path_info) |
|
66 | log.debug('accessing: `%s` with VCS Server disabled', path_info) | |
61 | return False |
|
67 | return False | |
62 |
|
68 | |||
63 |
def __init__(self, |
|
69 | def __init__(self, handler): | |
64 |
self. |
|
70 | self.handler = handler | |
65 |
|
71 | |||
66 |
def __call__(self, |
|
72 | def __call__(self, context, request): | |
67 | if not self._check_vcs_requirement(environ['PATH_INFO']): |
|
73 | if not self._check_vcs_requirement(request.environ['PATH_INFO']): | |
68 | environ['PATH_INFO'] = '/error/vcs_unavailable' |
|
74 | raise VCSServerUnavailable('VCS Server is not available') | |
69 |
|
75 | |||
70 |
return self. |
|
76 | return self.handler(context, request) |
@@ -26,6 +26,7 b' import rhodecode' | |||||
26 | from pylons.i18n.translation import _get_translator |
|
26 | from pylons.i18n.translation import _get_translator | |
27 | from pylons.util import ContextObj |
|
27 | from pylons.util import ContextObj | |
28 | from routes.util import URLGenerator |
|
28 | from routes.util import URLGenerator | |
|
29 | from pyramid.httpexceptions import HTTPInternalServerError, HTTPError, HTTPServiceUnavailable | |||
29 |
|
30 | |||
30 | from rhodecode.lib.base import attach_context_attributes, get_auth_user |
|
31 | from rhodecode.lib.base import attach_context_attributes, get_auth_user | |
31 | from rhodecode.model import meta |
|
32 | from rhodecode.model import meta | |
@@ -69,8 +70,8 b' def pylons_compatibility_tween_factory(h' | |||||
69 | context.rhodecode_user = auth_user |
|
70 | context.rhodecode_user = auth_user | |
70 | attach_context_attributes(context) |
|
71 | attach_context_attributes(context) | |
71 | pylons.tmpl_context._push_object(context) |
|
72 | pylons.tmpl_context._push_object(context) | |
72 |
|
73 | response = handler(request) | ||
73 |
return |
|
74 | return response | |
74 | finally: |
|
75 | finally: | |
75 | # Dispose current database session and rollback uncommitted |
|
76 | # Dispose current database session and rollback uncommitted | |
76 | # transactions. |
|
77 | # transactions. |
General Comments 0
You need to be logged in to leave comments.
Login now