##// END OF EJS Templates
ops: added healthcheck view
super-admin -
r4736:d501e9ec stable
parent child Browse files
Show More
@@ -1,56 +1,64 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2020 RhodeCode GmbH
3 # Copyright (C) 2016-2020 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 from rhodecode.apps._base import ADMIN_PREFIX
21 from rhodecode.apps._base import ADMIN_PREFIX
22
22
23
23
24 def admin_routes(config):
24 def admin_routes(config):
25 from rhodecode.apps.ops.views import OpsView
25 from rhodecode.apps.ops.views import OpsView
26
26
27 config.add_route(
27 config.add_route(
28 name='ops_ping',
28 name='ops_ping',
29 pattern='/ping')
29 pattern='/ping')
30 config.add_view(
30 config.add_view(
31 OpsView,
31 OpsView,
32 attr='ops_ping',
32 attr='ops_ping',
33 route_name='ops_ping', request_method='GET',
33 route_name='ops_ping', request_method='GET',
34 renderer='json_ext')
34 renderer='json_ext')
35
35
36 config.add_route(
36 config.add_route(
37 name='ops_error_test',
37 name='ops_error_test',
38 pattern='/error')
38 pattern='/error')
39 config.add_view(
39 config.add_view(
40 OpsView,
40 OpsView,
41 attr='ops_error_test',
41 attr='ops_error_test',
42 route_name='ops_error_test', request_method='GET',
42 route_name='ops_error_test', request_method='GET',
43 renderer='json_ext')
43 renderer='json_ext')
44
44
45 config.add_route(
45 config.add_route(
46 name='ops_redirect_test',
46 name='ops_redirect_test',
47 pattern='/redirect')
47 pattern='/redirect')
48 config.add_view(
48 config.add_view(
49 OpsView,
49 OpsView,
50 attr='ops_redirect_test',
50 attr='ops_redirect_test',
51 route_name='ops_redirect_test', request_method='GET',
51 route_name='ops_redirect_test', request_method='GET',
52 renderer='json_ext')
52 renderer='json_ext')
53
53
54 config.add_route(
55 name='ops_healthcheck',
56 pattern='/status')
57 config.add_view(
58 OpsView,
59 attr='ops_healthcheck',
60 route_name='ops_healthcheck', request_method='GET',
61 renderer='json_ext')
54
62
55 def includeme(config):
63 def includeme(config):
56 config.include(admin_routes, route_prefix=ADMIN_PREFIX + '/ops')
64 config.include(admin_routes, route_prefix=ADMIN_PREFIX + '/ops')
@@ -1,74 +1,94 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2020 RhodeCode GmbH
3 # Copyright (C) 2016-2020 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 import time
21 import time
22 import logging
22 import logging
23
23
24
24
25 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
26
26
27 from rhodecode.apps._base import BaseAppView
27 from rhodecode.apps._base import BaseAppView
28 from rhodecode.lib import helpers as h
28 from rhodecode.lib import helpers as h
29
29
30 log = logging.getLogger(__name__)
30 log = logging.getLogger(__name__)
31
31
32
32
33 class OpsView(BaseAppView):
33 class OpsView(BaseAppView):
34
34
35 def load_default_context(self):
35 def load_default_context(self):
36 c = self._get_local_tmpl_context()
36 c = self._get_local_tmpl_context()
37 c.user = c.auth_user.get_instance()
37 c.user = c.auth_user.get_instance()
38
38
39 return c
39 return c
40
40
41 def ops_ping(self):
41 def ops_ping(self):
42 data = {
42 data = {
43 'instance': self.request.registry.settings.get('instance_id'),
43 'instance': self.request.registry.settings.get('instance_id'),
44 }
44 }
45 if getattr(self.request, 'user'):
45 if getattr(self.request, 'user'):
46 caller_name = 'anonymous'
46 caller_name = 'anonymous'
47 if self.request.user.user_id:
47 if self.request.user.user_id:
48 caller_name = self.request.user.username
48 caller_name = self.request.user.username
49
49
50 data.update({
50 data.update({
51 'caller_ip': self.request.user.ip_addr,
51 'caller_ip': self.request.user.ip_addr,
52 'caller_name': caller_name,
52 'caller_name': caller_name,
53 })
53 })
54 return {'ok': data}
54 return {'ok': data}
55
55
56 def ops_error_test(self):
56 def ops_error_test(self):
57 """
57 """
58 Test exception handling and emails on errors
58 Test exception handling and emails on errors
59 """
59 """
60
60
61 class TestException(Exception):
61 class TestException(Exception):
62 pass
62 pass
63 # add timeout so we add some sort of rate limiter
63 # add timeout so we add some sort of rate limiter
64 time.sleep(2)
64 time.sleep(2)
65 msg = ('RhodeCode Enterprise test exception. '
65 msg = ('RhodeCode Enterprise test exception. '
66 'Client:{}. Generation time: {}.'.format(self.request.user, time.time()))
66 'Client:{}. Generation time: {}.'.format(self.request.user, time.time()))
67 raise TestException(msg)
67 raise TestException(msg)
68
68
69 def ops_redirect_test(self):
69 def ops_redirect_test(self):
70 """
70 """
71 Test redirect handling
71 Test redirect handling
72 """
72 """
73 redirect_to = self.request.GET.get('to') or h.route_path('home')
73 redirect_to = self.request.GET.get('to') or h.route_path('home')
74 raise HTTPFound(redirect_to)
74 raise HTTPFound(redirect_to)
75
76 def ops_healthcheck(self):
77 from rhodecode.lib.system_info import load_system_info
78
79 vcsserver_info = load_system_info('vcs_server')
80 if vcsserver_info:
81 vcsserver_info = vcsserver_info['human_value']
82
83 db_info = load_system_info('database_info')
84 if db_info:
85 db_info = db_info['human_value']
86
87 health_spec = {
88 'caller_ip': self.request.user.ip_addr,
89 'vcsserver': vcsserver_info,
90 'db': db_info,
91 }
92
93 return {'healthcheck': health_spec}
94
@@ -1,283 +1,284 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 import gzip
21 import gzip
22 import shutil
22 import shutil
23 import logging
23 import logging
24 import tempfile
24 import tempfile
25 import urlparse
25 import urlparse
26
26
27 from webob.exc import HTTPNotFound
27 from webob.exc import HTTPNotFound
28
28
29 import rhodecode
29 import rhodecode
30 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
30 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
31 from rhodecode.lib.middleware.simplegit import SimpleGit, GIT_PROTO_PAT
31 from rhodecode.lib.middleware.simplegit import SimpleGit, GIT_PROTO_PAT
32 from rhodecode.lib.middleware.simplehg import SimpleHg
32 from rhodecode.lib.middleware.simplehg import SimpleHg
33 from rhodecode.lib.middleware.simplesvn import SimpleSvn
33 from rhodecode.lib.middleware.simplesvn import SimpleSvn
34 from rhodecode.model.settings import VcsSettingsModel
34 from rhodecode.model.settings import VcsSettingsModel
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38 VCS_TYPE_KEY = '_rc_vcs_type'
38 VCS_TYPE_KEY = '_rc_vcs_type'
39 VCS_TYPE_SKIP = '_rc_vcs_skip'
39 VCS_TYPE_SKIP = '_rc_vcs_skip'
40
40
41
41
42 def is_git(environ):
42 def is_git(environ):
43 """
43 """
44 Returns True if requests should be handled by GIT wsgi middleware
44 Returns True if requests should be handled by GIT wsgi middleware
45 """
45 """
46 is_git_path = GIT_PROTO_PAT.match(environ['PATH_INFO'])
46 is_git_path = GIT_PROTO_PAT.match(environ['PATH_INFO'])
47 log.debug(
47 log.debug(
48 'request path: `%s` detected as GIT PROTOCOL %s', environ['PATH_INFO'],
48 'request path: `%s` detected as GIT PROTOCOL %s', environ['PATH_INFO'],
49 is_git_path is not None)
49 is_git_path is not None)
50
50
51 return is_git_path
51 return is_git_path
52
52
53
53
54 def is_hg(environ):
54 def is_hg(environ):
55 """
55 """
56 Returns True if requests target is mercurial server - header
56 Returns True if requests target is mercurial server - header
57 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
57 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
58 """
58 """
59 is_hg_path = False
59 is_hg_path = False
60
60
61 http_accept = environ.get('HTTP_ACCEPT')
61 http_accept = environ.get('HTTP_ACCEPT')
62
62
63 if http_accept and http_accept.startswith('application/mercurial'):
63 if http_accept and http_accept.startswith('application/mercurial'):
64 query = urlparse.parse_qs(environ['QUERY_STRING'])
64 query = urlparse.parse_qs(environ['QUERY_STRING'])
65 if 'cmd' in query:
65 if 'cmd' in query:
66 is_hg_path = True
66 is_hg_path = True
67
67
68 log.debug(
68 log.debug(
69 'request path: `%s` detected as HG PROTOCOL %s', environ['PATH_INFO'],
69 'request path: `%s` detected as HG PROTOCOL %s', environ['PATH_INFO'],
70 is_hg_path)
70 is_hg_path)
71
71
72 return is_hg_path
72 return is_hg_path
73
73
74
74
75 def is_svn(environ):
75 def is_svn(environ):
76 """
76 """
77 Returns True if requests target is Subversion server
77 Returns True if requests target is Subversion server
78 """
78 """
79
79
80 http_dav = environ.get('HTTP_DAV', '')
80 http_dav = environ.get('HTTP_DAV', '')
81 magic_path_segment = rhodecode.CONFIG.get(
81 magic_path_segment = rhodecode.CONFIG.get(
82 'rhodecode_subversion_magic_path', '/!svn')
82 'rhodecode_subversion_magic_path', '/!svn')
83 is_svn_path = (
83 is_svn_path = (
84 'subversion' in http_dav or
84 'subversion' in http_dav or
85 magic_path_segment in environ['PATH_INFO']
85 magic_path_segment in environ['PATH_INFO']
86 or environ['REQUEST_METHOD'] in ['PROPFIND', 'PROPPATCH']
86 or environ['REQUEST_METHOD'] in ['PROPFIND', 'PROPPATCH']
87 )
87 )
88 log.debug(
88 log.debug(
89 'request path: `%s` detected as SVN PROTOCOL %s', environ['PATH_INFO'],
89 'request path: `%s` detected as SVN PROTOCOL %s', environ['PATH_INFO'],
90 is_svn_path)
90 is_svn_path)
91
91
92 return is_svn_path
92 return is_svn_path
93
93
94
94
95 class GunzipMiddleware(object):
95 class GunzipMiddleware(object):
96 """
96 """
97 WSGI middleware that unzips gzip-encoded requests before
97 WSGI middleware that unzips gzip-encoded requests before
98 passing on to the underlying application.
98 passing on to the underlying application.
99 """
99 """
100
100
101 def __init__(self, application):
101 def __init__(self, application):
102 self.app = application
102 self.app = application
103
103
104 def __call__(self, environ, start_response):
104 def __call__(self, environ, start_response):
105 accepts_encoding_header = environ.get('HTTP_CONTENT_ENCODING', b'')
105 accepts_encoding_header = environ.get('HTTP_CONTENT_ENCODING', b'')
106
106
107 if b'gzip' in accepts_encoding_header:
107 if b'gzip' in accepts_encoding_header:
108 log.debug('gzip detected, now running gunzip wrapper')
108 log.debug('gzip detected, now running gunzip wrapper')
109 wsgi_input = environ['wsgi.input']
109 wsgi_input = environ['wsgi.input']
110
110
111 if not hasattr(environ['wsgi.input'], 'seek'):
111 if not hasattr(environ['wsgi.input'], 'seek'):
112 # The gzip implementation in the standard library of Python 2.x
112 # The gzip implementation in the standard library of Python 2.x
113 # requires the '.seek()' and '.tell()' methods to be available
113 # requires the '.seek()' and '.tell()' methods to be available
114 # on the input stream. Read the data into a temporary file to
114 # on the input stream. Read the data into a temporary file to
115 # work around this limitation.
115 # work around this limitation.
116
116
117 wsgi_input = tempfile.SpooledTemporaryFile(64 * 1024 * 1024)
117 wsgi_input = tempfile.SpooledTemporaryFile(64 * 1024 * 1024)
118 shutil.copyfileobj(environ['wsgi.input'], wsgi_input)
118 shutil.copyfileobj(environ['wsgi.input'], wsgi_input)
119 wsgi_input.seek(0)
119 wsgi_input.seek(0)
120
120
121 environ['wsgi.input'] = gzip.GzipFile(fileobj=wsgi_input, mode='r')
121 environ['wsgi.input'] = gzip.GzipFile(fileobj=wsgi_input, mode='r')
122 # since we "Ungzipped" the content we say now it's no longer gzip
122 # since we "Ungzipped" the content we say now it's no longer gzip
123 # content encoding
123 # content encoding
124 del environ['HTTP_CONTENT_ENCODING']
124 del environ['HTTP_CONTENT_ENCODING']
125
125
126 # content length has changes ? or i'm not sure
126 # content length has changes ? or i'm not sure
127 if 'CONTENT_LENGTH' in environ:
127 if 'CONTENT_LENGTH' in environ:
128 del environ['CONTENT_LENGTH']
128 del environ['CONTENT_LENGTH']
129 else:
129 else:
130 log.debug('content not gzipped, gzipMiddleware passing '
130 log.debug('content not gzipped, gzipMiddleware passing '
131 'request further')
131 'request further')
132 return self.app(environ, start_response)
132 return self.app(environ, start_response)
133
133
134
134
135 def is_vcs_call(environ):
135 def is_vcs_call(environ):
136 if VCS_TYPE_KEY in environ:
136 if VCS_TYPE_KEY in environ:
137 raw_type = environ[VCS_TYPE_KEY]
137 raw_type = environ[VCS_TYPE_KEY]
138 return raw_type and raw_type != VCS_TYPE_SKIP
138 return raw_type and raw_type != VCS_TYPE_SKIP
139 return False
139 return False
140
140
141
141
142 def get_path_elem(route_path):
142 def get_path_elem(route_path):
143 if not route_path:
143 if not route_path:
144 return None
144 return None
145
145
146 cleaned_route_path = route_path.lstrip('/')
146 cleaned_route_path = route_path.lstrip('/')
147 if cleaned_route_path:
147 if cleaned_route_path:
148 cleaned_route_path_elems = cleaned_route_path.split('/')
148 cleaned_route_path_elems = cleaned_route_path.split('/')
149 if cleaned_route_path_elems:
149 if cleaned_route_path_elems:
150 return cleaned_route_path_elems[0]
150 return cleaned_route_path_elems[0]
151 return None
151 return None
152
152
153
153
154 def detect_vcs_request(environ, backends):
154 def detect_vcs_request(environ, backends):
155 checks = {
155 checks = {
156 'hg': (is_hg, SimpleHg),
156 'hg': (is_hg, SimpleHg),
157 'git': (is_git, SimpleGit),
157 'git': (is_git, SimpleGit),
158 'svn': (is_svn, SimpleSvn),
158 'svn': (is_svn, SimpleSvn),
159 }
159 }
160 handler = None
160 handler = None
161 # List of path views first chunk we don't do any checks
161 # List of path views first chunk we don't do any checks
162 white_list = [
162 white_list = [
163 # e.g /_file_store/download
163 # e.g /_file_store/download
164 '_file_store',
164 '_file_store',
165
165
166 # static files no detection
166 # static files no detection
167 '_static',
167 '_static',
168
168
169 # skip ops ping
169 # skip ops ping, status
170 '_admin/ops/ping',
170 '_admin/ops/ping',
171 '_admin/ops/status',
171
172
172 # full channelstream connect should be VCS skipped
173 # full channelstream connect should be VCS skipped
173 '_admin/channelstream/connect',
174 '_admin/channelstream/connect',
174 ]
175 ]
175
176
176 path_info = environ['PATH_INFO']
177 path_info = environ['PATH_INFO']
177
178
178 path_elem = get_path_elem(path_info)
179 path_elem = get_path_elem(path_info)
179
180
180 if path_elem in white_list:
181 if path_elem in white_list:
181 log.debug('path `%s` in whitelist, skipping...', path_info)
182 log.debug('path `%s` in whitelist, skipping...', path_info)
182 return handler
183 return handler
183
184
184 path_url = path_info.lstrip('/')
185 path_url = path_info.lstrip('/')
185 if path_url in white_list:
186 if path_url in white_list:
186 log.debug('full url path `%s` in whitelist, skipping...', path_url)
187 log.debug('full url path `%s` in whitelist, skipping...', path_url)
187 return handler
188 return handler
188
189
189 if VCS_TYPE_KEY in environ:
190 if VCS_TYPE_KEY in environ:
190 raw_type = environ[VCS_TYPE_KEY]
191 raw_type = environ[VCS_TYPE_KEY]
191 if raw_type == VCS_TYPE_SKIP:
192 if raw_type == VCS_TYPE_SKIP:
192 log.debug('got `skip` marker for vcs detection, skipping...')
193 log.debug('got `skip` marker for vcs detection, skipping...')
193 return handler
194 return handler
194
195
195 _check, handler = checks.get(raw_type) or [None, None]
196 _check, handler = checks.get(raw_type) or [None, None]
196 if handler:
197 if handler:
197 log.debug('got handler:%s from environ', handler)
198 log.debug('got handler:%s from environ', handler)
198
199
199 if not handler:
200 if not handler:
200 log.debug('request start: checking if request for `%s` is of VCS type in order: %s', path_elem, backends)
201 log.debug('request start: checking if request for `%s` is of VCS type in order: %s', path_elem, backends)
201 for vcs_type in backends:
202 for vcs_type in backends:
202 vcs_check, _handler = checks[vcs_type]
203 vcs_check, _handler = checks[vcs_type]
203 if vcs_check(environ):
204 if vcs_check(environ):
204 log.debug('vcs handler found %s', _handler)
205 log.debug('vcs handler found %s', _handler)
205 handler = _handler
206 handler = _handler
206 break
207 break
207
208
208 return handler
209 return handler
209
210
210
211
211 class VCSMiddleware(object):
212 class VCSMiddleware(object):
212
213
213 def __init__(self, app, registry, config, appenlight_client):
214 def __init__(self, app, registry, config, appenlight_client):
214 self.application = app
215 self.application = app
215 self.registry = registry
216 self.registry = registry
216 self.config = config
217 self.config = config
217 self.appenlight_client = appenlight_client
218 self.appenlight_client = appenlight_client
218 self.use_gzip = True
219 self.use_gzip = True
219 # order in which we check the middlewares, based on vcs.backends config
220 # order in which we check the middlewares, based on vcs.backends config
220 self.check_middlewares = config['vcs.backends']
221 self.check_middlewares = config['vcs.backends']
221
222
222 def vcs_config(self, repo_name=None):
223 def vcs_config(self, repo_name=None):
223 """
224 """
224 returns serialized VcsSettings
225 returns serialized VcsSettings
225 """
226 """
226 try:
227 try:
227 return VcsSettingsModel(
228 return VcsSettingsModel(
228 repo=repo_name).get_ui_settings_as_config_obj()
229 repo=repo_name).get_ui_settings_as_config_obj()
229 except Exception:
230 except Exception:
230 pass
231 pass
231
232
232 def wrap_in_gzip_if_enabled(self, app, config):
233 def wrap_in_gzip_if_enabled(self, app, config):
233 if self.use_gzip:
234 if self.use_gzip:
234 app = GunzipMiddleware(app)
235 app = GunzipMiddleware(app)
235 return app
236 return app
236
237
237 def _get_handler_app(self, environ):
238 def _get_handler_app(self, environ):
238 app = None
239 app = None
239 log.debug('VCSMiddleware: detecting vcs type.')
240 log.debug('VCSMiddleware: detecting vcs type.')
240 handler = detect_vcs_request(environ, self.check_middlewares)
241 handler = detect_vcs_request(environ, self.check_middlewares)
241 if handler:
242 if handler:
242 app = handler(self.config, self.registry)
243 app = handler(self.config, self.registry)
243
244
244 return app
245 return app
245
246
246 def __call__(self, environ, start_response):
247 def __call__(self, environ, start_response):
247 # check if we handle one of interesting protocols, optionally extract
248 # check if we handle one of interesting protocols, optionally extract
248 # specific vcsSettings and allow changes of how things are wrapped
249 # specific vcsSettings and allow changes of how things are wrapped
249 vcs_handler = self._get_handler_app(environ)
250 vcs_handler = self._get_handler_app(environ)
250 if vcs_handler:
251 if vcs_handler:
251 # translate the _REPO_ID into real repo NAME for usage
252 # translate the _REPO_ID into real repo NAME for usage
252 # in middleware
253 # in middleware
253 environ['PATH_INFO'] = vcs_handler._get_by_id(environ['PATH_INFO'])
254 environ['PATH_INFO'] = vcs_handler._get_by_id(environ['PATH_INFO'])
254
255
255 # Set acl, url and vcs repo names.
256 # Set acl, url and vcs repo names.
256 vcs_handler.set_repo_names(environ)
257 vcs_handler.set_repo_names(environ)
257
258
258 # register repo config back to the handler
259 # register repo config back to the handler
259 vcs_conf = self.vcs_config(vcs_handler.acl_repo_name)
260 vcs_conf = self.vcs_config(vcs_handler.acl_repo_name)
260 # maybe damaged/non existent settings. We still want to
261 # maybe damaged/non existent settings. We still want to
261 # pass that point to validate on is_valid_and_existing_repo
262 # pass that point to validate on is_valid_and_existing_repo
262 # and return proper HTTP Code back to client
263 # and return proper HTTP Code back to client
263 if vcs_conf:
264 if vcs_conf:
264 vcs_handler.repo_vcs_config = vcs_conf
265 vcs_handler.repo_vcs_config = vcs_conf
265
266
266 # check for type, presence in database and on filesystem
267 # check for type, presence in database and on filesystem
267 if not vcs_handler.is_valid_and_existing_repo(
268 if not vcs_handler.is_valid_and_existing_repo(
268 vcs_handler.acl_repo_name,
269 vcs_handler.acl_repo_name,
269 vcs_handler.base_path,
270 vcs_handler.base_path,
270 vcs_handler.SCM):
271 vcs_handler.SCM):
271 return HTTPNotFound()(environ, start_response)
272 return HTTPNotFound()(environ, start_response)
272
273
273 environ['REPO_NAME'] = vcs_handler.url_repo_name
274 environ['REPO_NAME'] = vcs_handler.url_repo_name
274
275
275 # Wrap handler in middlewares if they are enabled.
276 # Wrap handler in middlewares if they are enabled.
276 vcs_handler = self.wrap_in_gzip_if_enabled(
277 vcs_handler = self.wrap_in_gzip_if_enabled(
277 vcs_handler, self.config)
278 vcs_handler, self.config)
278 vcs_handler, _ = wrap_in_appenlight_if_enabled(
279 vcs_handler, _ = wrap_in_appenlight_if_enabled(
279 vcs_handler, self.config, self.appenlight_client)
280 vcs_handler, self.config, self.appenlight_client)
280
281
281 return vcs_handler(environ, start_response)
282 return vcs_handler(environ, start_response)
282
283
283 return self.application(environ, start_response)
284 return self.application(environ, start_response)
General Comments 0
You need to be logged in to leave comments. Login now