feat(svn): improvements to handle SVN protocol 1.4 features
- added support to actually allow HEAD type calls - support HEAD / DELETE calls properly with new requets - use request session for performance optimization on making a lot of calls.
This commit is contained in:
parent
2bbbdccd2a
commit
25c079d921
3 changed files with 23 additions and 10 deletions
|
|
@ -48,6 +48,7 @@ class SimpleSvnApp(object):
|
|||
|
||||
def __init__(self, config):
|
||||
self.config = config
|
||||
self.session = requests.Session()
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
request_headers = self._get_request_headers(environ)
|
||||
|
|
@ -94,10 +95,17 @@ class SimpleSvnApp(object):
|
|||
log.debug('Calling SVN PROXY at `%s`, using method:%s. Stream: %s',
|
||||
path_info, req_method, stream)
|
||||
|
||||
call_kwargs = dict(
|
||||
data=data_io,
|
||||
headers=request_headers,
|
||||
stream=stream
|
||||
)
|
||||
if req_method in ['HEAD', 'DELETE']:
|
||||
del call_kwargs['data']
|
||||
|
||||
try:
|
||||
response = requests.request(
|
||||
req_method, path_info,
|
||||
data=data_io, headers=request_headers, stream=stream)
|
||||
response = self.session.request(
|
||||
req_method, path_info, **call_kwargs)
|
||||
except requests.ConnectionError:
|
||||
log.exception('ConnectionError occurred for endpoint %s', path_info)
|
||||
raise
|
||||
|
|
|
|||
|
|
@ -63,11 +63,12 @@ from rhodecode.model.settings import SettingsModel, VcsSettingsModel
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def extract_svn_txn_id(acl_repo_name, data):
|
||||
def extract_svn_txn_id(acl_repo_name, data: bytes):
|
||||
"""
|
||||
Helper method for extraction of svn txn_id from submitted XML data during
|
||||
POST operations
|
||||
"""
|
||||
|
||||
try:
|
||||
root = etree.fromstring(data)
|
||||
pat = re.compile(r'/txn/(?P<txn_id>.*)')
|
||||
|
|
@ -609,13 +610,13 @@ class SimpleVCS(object):
|
|||
stream = environ['wsgi.input']
|
||||
|
||||
if isinstance(stream, io.BytesIO):
|
||||
data: str = safe_str(stream.getvalue())
|
||||
data: bytes = stream.getvalue()
|
||||
elif hasattr(stream, 'buf'): # most likely gunicorn.http.body.Body
|
||||
data: str = safe_str(stream.buf.getvalue())
|
||||
data: bytes = stream.buf.getvalue()
|
||||
else:
|
||||
# fallback to the crudest way, copy the iterator
|
||||
data = safe_str(stream.read())
|
||||
environ['wsgi.input'] = io.BytesIO(safe_bytes(data))
|
||||
data = safe_bytes(stream.read())
|
||||
environ['wsgi.input'] = io.BytesIO(data)
|
||||
|
||||
txn_id = extract_svn_txn_id(self.acl_repo_name, data)
|
||||
|
||||
|
|
|
|||
|
|
@ -84,10 +84,12 @@ def is_svn(environ):
|
|||
magic_path_segment = rhodecode.CONFIG.get(
|
||||
'rhodecode_subversion_magic_path', '/!svn')
|
||||
path_info = get_path_info(environ)
|
||||
req_method = environ['REQUEST_METHOD']
|
||||
|
||||
is_svn_path = (
|
||||
'subversion' in http_dav or
|
||||
magic_path_segment in path_info
|
||||
or environ['REQUEST_METHOD'] in ['PROPFIND', 'PROPPATCH']
|
||||
or req_method in ['PROPFIND', 'PROPPATCH', 'HEAD']
|
||||
)
|
||||
log.debug(
|
||||
'request path: `%s` detected as SVN PROTOCOL %s', path_info,
|
||||
|
|
@ -187,6 +189,7 @@ def detect_vcs_request(environ, backends):
|
|||
]
|
||||
path_info = get_path_info(environ)
|
||||
path_url = path_info.lstrip('/')
|
||||
req_method = environ.get('REQUEST_METHOD')
|
||||
|
||||
for item in white_list:
|
||||
if item.endswith('++') and path_url.startswith(item[:-2]):
|
||||
|
|
@ -210,7 +213,8 @@ def detect_vcs_request(environ, backends):
|
|||
log.debug('got handler:%s from environ', handler)
|
||||
|
||||
if not handler:
|
||||
log.debug('request start: checking if request for `%s` is of VCS type in order: %s', path_url, backends)
|
||||
log.debug('request start: checking if request for `%s:%s` is of VCS type in order: %s',
|
||||
req_method, path_url, backends)
|
||||
for vcs_type in backends:
|
||||
vcs_check, _handler = checks[vcs_type]
|
||||
if vcs_check(environ):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue