##// END OF EJS Templates
svn: Ignore the content length header from response, fixes #4112...
Martin Bornhold -
r473:7e153d56 default
parent child Browse files
Show More
@@ -1,130 +1,130 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 from urlparse import urljoin
22 22
23 23 import requests
24 24
25 25 import rhodecode
26 26 from rhodecode.lib.middleware import simplevcs
27 27 from rhodecode.lib.utils import is_valid_repo
28 28
29 29
30 30 class SimpleSvnApp(object):
31 31 IGNORED_HEADERS = [
32 32 'connection', 'keep-alive', 'content-encoding',
33 'transfer-encoding']
33 'transfer-encoding', 'content-length']
34 34
35 35 def __init__(self, config):
36 36 self.config = config
37 37
38 38 def __call__(self, environ, start_response):
39 39 request_headers = self._get_request_headers(environ)
40 40
41 41 data = environ['wsgi.input']
42 42 # johbo: Avoid that we end up with sending the request in chunked
43 43 # transfer encoding (mainly on Gunicorn). If we know the content
44 44 # length, then we should transfer the payload in one request.
45 45 if environ['REQUEST_METHOD'] == 'MKCOL' or 'CONTENT_LENGTH' in environ:
46 46 data = data.read()
47 47
48 48 response = requests.request(
49 49 environ['REQUEST_METHOD'], self._get_url(environ['PATH_INFO']),
50 50 data=data, headers=request_headers)
51 51
52 52 response_headers = self._get_response_headers(response.headers)
53 53 start_response(
54 54 '{} {}'.format(response.status_code, response.reason),
55 55 response_headers)
56 56 return response.iter_content(chunk_size=1024)
57 57
58 58 def _get_url(self, path):
59 59 return urljoin(
60 60 self.config.get('subversion_http_server_url', ''), path)
61 61
62 62 def _get_request_headers(self, environ):
63 63 headers = {}
64 64
65 65 for key in environ:
66 66 if not key.startswith('HTTP_'):
67 67 continue
68 68 new_key = key.split('_')
69 69 new_key = [k.capitalize() for k in new_key[1:]]
70 70 new_key = '-'.join(new_key)
71 71 headers[new_key] = environ[key]
72 72
73 73 if 'CONTENT_TYPE' in environ:
74 74 headers['Content-Type'] = environ['CONTENT_TYPE']
75 75
76 76 if 'CONTENT_LENGTH' in environ:
77 77 headers['Content-Length'] = environ['CONTENT_LENGTH']
78 78
79 79 return headers
80 80
81 81 def _get_response_headers(self, headers):
82 82 return [
83 83 (h, headers[h])
84 84 for h in headers
85 85 if h.lower() not in self.IGNORED_HEADERS
86 86 ]
87 87
88 88
89 89 class SimpleSvn(simplevcs.SimpleVCS):
90 90
91 91 SCM = 'svn'
92 92 READ_ONLY_COMMANDS = ('OPTIONS', 'PROPFIND', 'GET', 'REPORT')
93 93
94 94 def _get_repository_name(self, environ):
95 95 """
96 96 Gets repository name out of PATH_INFO header
97 97
98 98 :param environ: environ where PATH_INFO is stored
99 99 """
100 100 path = environ['PATH_INFO'].split('!')
101 101 repo_name = path[0].strip('/')
102 102
103 103 # SVN includes the whole path in it's requests, including
104 104 # subdirectories inside the repo. Therefore we have to search for
105 105 # the repo root directory.
106 106 if not is_valid_repo(repo_name, self.basepath, self.SCM):
107 107 current_path = ''
108 108 for component in repo_name.split('/'):
109 109 current_path += component
110 110 if is_valid_repo(current_path, self.basepath, self.SCM):
111 111 return current_path
112 112 current_path += '/'
113 113
114 114 return repo_name
115 115
116 116 def _get_action(self, environ):
117 117 return (
118 118 'pull'
119 119 if environ['REQUEST_METHOD'] in self.READ_ONLY_COMMANDS
120 120 else 'push')
121 121
122 122 def _create_wsgi_app(self, repo_path, repo_name, config):
123 123 return SimpleSvnApp(config)
124 124
125 125 def _create_config(self, extras, repo_name):
126 126 server_url = rhodecode.CONFIG.get(
127 127 'rhodecode_subversion_http_server_url', '')
128 128 extras['subversion_http_server_url'] = (
129 129 server_url or 'http://localhost/')
130 130 return extras
General Comments 0
You need to be logged in to leave comments. Login now