# HG changeset patch # User Marcin Kuzminski # Date 2017-01-12 00:20:31 # Node ID de699d5ea155e93b4d267a6feaa45e61b8cc4634 # Parent 067bb0fcf7964c28479c66f4eb04126fb5571e61 vcs: do an early detection of vcs-type request. We we to know to detect vcs type request as early as possible. IF we know we're handling an VCS request, we can skip some of the pylons stack initialization. - This fixes issues with leaking sessions and other object from pylons into a purely VCS type request. diff --git a/rhodecode/lib/middleware/simplevcs.py b/rhodecode/lib/middleware/simplevcs.py --- a/rhodecode/lib/middleware/simplevcs.py +++ b/rhodecode/lib/middleware/simplevcs.py @@ -165,7 +165,7 @@ class SimpleVCS(object): self.acl_repo_name = acl_repo_name self.is_shadow_repo = True - log.debug('Repository names: %s', { + log.debug('Setting all VCS repository names: %s', { 'acl_repo_name': self.acl_repo_name, 'url_repo_name': self.url_repo_name, 'vcs_repo_name': self.vcs_repo_name, diff --git a/rhodecode/lib/middleware/vcs.py b/rhodecode/lib/middleware/vcs.py --- a/rhodecode/lib/middleware/vcs.py +++ b/rhodecode/lib/middleware/vcs.py @@ -35,6 +35,9 @@ from rhodecode.model.settings import Vcs log = logging.getLogger(__name__) +VCS_TYPE_KEY = '_rc_vcs_type' +VCS_TYPE_SKIP = '_rc_vcs_skip' + def is_git(environ): """ @@ -126,6 +129,43 @@ class GunzipMiddleware(object): return self.app(environ, start_response) +def is_vcs_call(environ): + if VCS_TYPE_KEY in environ: + raw_type = environ[VCS_TYPE_KEY] + return raw_type and raw_type != VCS_TYPE_SKIP + return False + + +def detect_vcs_request(environ, backends): + checks = { + 'hg': (is_hg, SimpleHg), + 'git': (is_git, SimpleGit), + 'svn': (is_svn, SimpleSvn), + } + handler = None + + if VCS_TYPE_KEY in environ: + raw_type = environ[VCS_TYPE_KEY] + if raw_type == VCS_TYPE_SKIP: + log.debug('got `skip` marker for vcs detection, skipping...') + return handler + + _check, handler = checks.get(raw_type) or [None, None] + if handler: + log.debug('got handler:%s from environ', handler) + + if not handler: + log.debug('checking if request is of VCS type in order: %s', backends) + for vcs_type in backends: + vcs_check, _handler = checks[vcs_type] + if vcs_check(environ): + log.debug('vcs handler found %s', _handler) + handler = _handler + break + + return handler + + class VCSMiddleware(object): def __init__(self, app, config, appenlight_client, registry): @@ -136,11 +176,6 @@ class VCSMiddleware(object): self.use_gzip = True # order in which we check the middlewares, based on vcs.backends config self.check_middlewares = config['vcs.backends'] - self.checks = { - 'hg': (is_hg, SimpleHg), - 'git': (is_git, SimpleGit), - 'svn': (is_svn, SimpleSvn), - } def vcs_config(self, repo_name=None): """ @@ -155,14 +190,10 @@ class VCSMiddleware(object): def _get_handler_app(self, environ): app = None - log.debug('Checking vcs types in order: %r', self.check_middlewares) - for vcs_type in self.check_middlewares: - vcs_check, handler = self.checks[vcs_type] - if vcs_check(environ): - log.debug( - 'Found VCS Middleware to handle the request %s', handler) - app = handler(self.application, self.config, self.registry) - break + log.debug('VCSMiddleware: detecting vcs type.') + handler = detect_vcs_request(environ, self.check_middlewares) + if handler: + app = handler(self.application, self.config, self.registry) return app diff --git a/rhodecode/tweens.py b/rhodecode/tweens.py --- a/rhodecode/tweens.py +++ b/rhodecode/tweens.py @@ -28,12 +28,16 @@ from pylons.util import ContextObj from routes.util import URLGenerator from rhodecode.lib.base import attach_context_attributes, get_auth_user +from rhodecode.lib.middleware.vcs import ( + detect_vcs_request, VCS_TYPE_KEY, VCS_TYPE_SKIP) from rhodecode.model import meta + log = logging.getLogger(__name__) def pylons_compatibility_tween_factory(handler, registry): + def pylons_compatibility_tween(request): """ While migrating from pylons to pyramid we need to call some pylons code @@ -43,13 +47,23 @@ def pylons_compatibility_tween_factory(h config = rhodecode.CONFIG environ = request.environ session = request.session - session_key = (config['pylons.environ_config'] - .get('session', 'beaker.session')) + + vcs_handler = detect_vcs_request( + request.environ, request.registry.settings.get('vcs.backends')) + + if vcs_handler: + request.environ[VCS_TYPE_KEY] = vcs_handler.SCM + return handler(request) + + request.environ[VCS_TYPE_KEY] = VCS_TYPE_SKIP # Setup pylons globals. pylons.config._push_object(config) pylons.request._push_object(request) pylons.session._push_object(session) + + session_key = ( + config['pylons.environ_config'].get('session', 'beaker.session')) environ[session_key] = session pylons.url._push_object(URLGenerator(config['routes.map'], environ))