##// END OF EJS Templates
vcs: Move logging from vcs to simplevcs
Martin Bornhold -
r903:ca0f37f5 default
parent child Browse files
Show More
@@ -1,211 +1,204 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import gzip
22 import re
23 22 import shutil
24 23 import logging
25 24 import tempfile
26 25 import urlparse
27 26
28 27 from webob.exc import HTTPNotFound
29 28
30 29 import rhodecode
31 30 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
32 31 from rhodecode.lib.middleware.simplegit import SimpleGit, GIT_PROTO_PAT
33 32 from rhodecode.lib.middleware.simplehg import SimpleHg
34 33 from rhodecode.lib.middleware.simplesvn import SimpleSvn
35 34 from rhodecode.model.settings import VcsSettingsModel
36 35
37 36 log = logging.getLogger(__name__)
38 37
39 38
40 39 def is_git(environ):
41 40 """
42 41 Returns True if requests should be handled by GIT wsgi middleware
43 42 """
44 43 is_git_path = GIT_PROTO_PAT.match(environ['PATH_INFO'])
45 44 log.debug(
46 45 'request path: `%s` detected as GIT PROTOCOL %s', environ['PATH_INFO'],
47 46 is_git_path is not None)
48 47
49 48 return is_git_path
50 49
51 50
52 51 def is_hg(environ):
53 52 """
54 53 Returns True if requests target is mercurial server - header
55 54 ``HTTP_ACCEPT`` of such request would start with ``application/mercurial``.
56 55 """
57 56 is_hg_path = False
58 57
59 58 http_accept = environ.get('HTTP_ACCEPT')
60 59
61 60 if http_accept and http_accept.startswith('application/mercurial'):
62 61 query = urlparse.parse_qs(environ['QUERY_STRING'])
63 62 if 'cmd' in query:
64 63 is_hg_path = True
65 64
66 65 log.debug(
67 66 'request path: `%s` detected as HG PROTOCOL %s', environ['PATH_INFO'],
68 67 is_hg_path)
69 68
70 69 return is_hg_path
71 70
72 71
73 72 def is_svn(environ):
74 73 """
75 74 Returns True if requests target is Subversion server
76 75 """
77 76 http_dav = environ.get('HTTP_DAV', '')
78 77 magic_path_segment = rhodecode.CONFIG.get(
79 78 'rhodecode_subversion_magic_path', '/!svn')
80 79 is_svn_path = (
81 80 'subversion' in http_dav or
82 81 magic_path_segment in environ['PATH_INFO'])
83 82 log.debug(
84 83 'request path: `%s` detected as SVN PROTOCOL %s', environ['PATH_INFO'],
85 84 is_svn_path)
86 85
87 86 return is_svn_path
88 87
89 88
90 89 class GunzipMiddleware(object):
91 90 """
92 91 WSGI middleware that unzips gzip-encoded requests before
93 92 passing on to the underlying application.
94 93 """
95 94
96 95 def __init__(self, application):
97 96 self.app = application
98 97
99 98 def __call__(self, environ, start_response):
100 99 accepts_encoding_header = environ.get('HTTP_CONTENT_ENCODING', b'')
101 100
102 101 if b'gzip' in accepts_encoding_header:
103 102 log.debug('gzip detected, now running gunzip wrapper')
104 103 wsgi_input = environ['wsgi.input']
105 104
106 105 if not hasattr(environ['wsgi.input'], 'seek'):
107 106 # The gzip implementation in the standard library of Python 2.x
108 107 # requires the '.seek()' and '.tell()' methods to be available
109 108 # on the input stream. Read the data into a temporary file to
110 109 # work around this limitation.
111 110
112 111 wsgi_input = tempfile.SpooledTemporaryFile(64 * 1024 * 1024)
113 112 shutil.copyfileobj(environ['wsgi.input'], wsgi_input)
114 113 wsgi_input.seek(0)
115 114
116 115 environ['wsgi.input'] = gzip.GzipFile(fileobj=wsgi_input, mode='r')
117 116 # since we "Ungzipped" the content we say now it's no longer gzip
118 117 # content encoding
119 118 del environ['HTTP_CONTENT_ENCODING']
120 119
121 120 # content length has changes ? or i'm not sure
122 121 if 'CONTENT_LENGTH' in environ:
123 122 del environ['CONTENT_LENGTH']
124 123 else:
125 124 log.debug('content not gzipped, gzipMiddleware passing '
126 125 'request further')
127 126 return self.app(environ, start_response)
128 127
129 128
130 129 class VCSMiddleware(object):
131 130
132 131 def __init__(self, app, config, appenlight_client, registry):
133 132 self.application = app
134 133 self.config = config
135 134 self.appenlight_client = appenlight_client
136 135 self.registry = registry
137 136 self.use_gzip = True
138 137 # order in which we check the middlewares, based on vcs.backends config
139 138 self.check_middlewares = config['vcs.backends']
140 139 self.checks = {
141 140 'hg': (is_hg, SimpleHg),
142 141 'git': (is_git, SimpleGit),
143 142 'svn': (is_svn, SimpleSvn),
144 143 }
145 144
146 145 def vcs_config(self, repo_name=None):
147 146 """
148 147 returns serialized VcsSettings
149 148 """
150 149 return VcsSettingsModel(repo=repo_name).get_ui_settings_as_config_obj()
151 150
152 151 def wrap_in_gzip_if_enabled(self, app, config):
153 152 if self.use_gzip:
154 153 app = GunzipMiddleware(app)
155 154 return app
156 155
157 156 def _get_handler_app(self, environ):
158 157 app = None
159 158 log.debug('Checking vcs types in order: %r', self.check_middlewares)
160 159 for vcs_type in self.check_middlewares:
161 160 vcs_check, handler = self.checks[vcs_type]
162 161 if vcs_check(environ):
163 162 log.debug(
164 163 'Found VCS Middleware to handle the request %s', handler)
165 164 app = handler(self.application, self.config, self.registry)
166 165 break
167 166
168 167 return app
169 168
170 169 def __call__(self, environ, start_response):
171 170 # check if we handle one of interesting protocols, optionally extract
172 171 # specific vcsSettings and allow changes of how things are wrapped
173 172 vcs_handler = self._get_handler_app(environ)
174 173 if vcs_handler:
175 174 # translate the _REPO_ID into real repo NAME for usage
176 175 # in middleware
177 176 environ['PATH_INFO'] = vcs_handler._get_by_id(environ['PATH_INFO'])
178 177
179 178 # Set repo names for permission checks, vcs and web interaction.
180 179 vcs_handler.set_repo_names(environ)
181 log.debug('repo_names %s', {
182 'acl_repo_name': vcs_handler.acl_repo_name,
183 'vcs_repo_name': vcs_handler.vcs_repo_name,
184 'url_repo_name': vcs_handler.url_repo_name,
185 })
186 log.debug('pull_request %s', vcs_handler.pr_id)
187 180
188 181 # check for type, presence in database and on filesystem
189 182 if not vcs_handler.is_valid_and_existing_repo(
190 183 vcs_handler.acl_repo_name,
191 184 vcs_handler.basepath,
192 185 vcs_handler.SCM):
193 186 return HTTPNotFound()(environ, start_response)
194 187
195 188 # TODO: johbo: Needed for the Pyro4 backend and Mercurial only.
196 189 # Remove once we fully switched to the HTTP backend.
197 190 environ['REPO_NAME'] = vcs_handler.url_repo_name
198 191
199 192 # register repo config back to the handler
200 193 vcs_handler.repo_vcs_config = self.vcs_config(
201 194 vcs_handler.acl_repo_name)
202 195
203 196 # Wrap handler in middlewares if they are enabled.
204 197 vcs_handler = self.wrap_in_gzip_if_enabled(
205 198 vcs_handler, self.config)
206 199 vcs_handler, _ = wrap_in_appenlight_if_enabled(
207 200 vcs_handler, self.config, self.appenlight_client)
208 201
209 202 return vcs_handler(environ, start_response)
210 203
211 204 return self.application(environ, start_response)
General Comments 0
You need to be logged in to leave comments. Login now