##// END OF EJS Templates
http-app: prevent httplib3 logs to spawn our rhodecode logs....
marcink -
r1550:d8292ad9 default
parent child Browse files
Show More
@@ -1,143 +1,147 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2014-2017 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 """
22 22 Implementation of the scm_app interface using raw HTTP communication.
23 23 """
24 24
25 25 import base64
26 26 import logging
27 27 import urlparse
28 28 import wsgiref.util
29 29
30 30 import msgpack
31 31 import requests
32 32 import webob.request
33 33
34 34 import rhodecode
35 35
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 def create_git_wsgi_app(repo_path, repo_name, config):
41 41 url = _vcs_streaming_url() + 'git/'
42 42 return VcsHttpProxy(url, repo_path, repo_name, config)
43 43
44 44
45 45 def create_hg_wsgi_app(repo_path, repo_name, config):
46 46 url = _vcs_streaming_url() + 'hg/'
47 47 return VcsHttpProxy(url, repo_path, repo_name, config)
48 48
49 49
50 50 def _vcs_streaming_url():
51 51 template = 'http://{}/stream/'
52 52 return template.format(rhodecode.CONFIG['vcs.server'])
53 53
54 54
55 55 # TODO: johbo: Avoid the global.
56 56 session = requests.Session()
57 57 # Requests speedup, avoid reading .netrc and similar
58 58 session.trust_env = False
59 59
60 # prevent urllib3 spawning our logs.
61 logging.getLogger("requests.packages.urllib3.connectionpool").setLevel(
62 logging.WARNING)
63
60 64
61 65 class VcsHttpProxy(object):
62 66 """
63 67 A WSGI application which proxies vcs requests.
64 68
65 69 The goal is to shuffle the data around without touching it. The only
66 70 exception is the extra data from the config object which we send to the
67 71 server as well.
68 72 """
69 73
70 74 def __init__(self, url, repo_path, repo_name, config):
71 75 """
72 76 :param str url: The URL of the VCSServer to call.
73 77 """
74 78 self._url = url
75 79 self._repo_name = repo_name
76 80 self._repo_path = repo_path
77 81 self._config = config
78 82 log.debug(
79 83 "Creating VcsHttpProxy for repo %s, url %s",
80 84 repo_name, url)
81 85
82 86 def __call__(self, environ, start_response):
83 87 config = msgpack.packb(self._config)
84 88 request = webob.request.Request(environ)
85 89 request_headers = request.headers
86 90 request_headers.update({
87 91 # TODO: johbo: Remove this, rely on URL path only
88 92 'X-RC-Repo-Name': self._repo_name,
89 93 'X-RC-Repo-Path': self._repo_path,
90 94 'X-RC-Path-Info': environ['PATH_INFO'],
91 95 # TODO: johbo: Avoid encoding and put this into payload?
92 96 'X-RC-Repo-Config': base64.b64encode(config),
93 97 'X-RC-Locked-Status-Code': rhodecode.CONFIG.get('lock_ret_code')
94 98 })
95 99
96 100 method = environ['REQUEST_METHOD']
97 101
98 102 # Preserve the query string
99 103 url = self._url
100 104 url = urlparse.urljoin(url, self._repo_name)
101 105 if environ.get('QUERY_STRING'):
102 106 url += '?' + environ['QUERY_STRING']
103 107
104 108 response = session.request(
105 109 method, url,
106 110 data=_maybe_stream_request(environ),
107 111 headers=request_headers,
108 112 stream=True)
109 113
110 114 # Preserve the headers of the response, except hop_by_hop ones
111 115 response_headers = [
112 116 (h, v) for h, v in response.headers.items()
113 117 if not wsgiref.util.is_hop_by_hop(h)
114 118 ]
115 119
116 120 # Build status argument for start_reponse callable.
117 121 status = '{status_code} {reason_phrase}'.format(
118 122 status_code=response.status_code,
119 123 reason_phrase=response.reason)
120 124
121 125 start_response(status, response_headers)
122 126 return _maybe_stream_response(response)
123 127
124 128
125 129 def _maybe_stream_request(environ):
126 130 if environ.get('HTTP_TRANSFER_ENCODING', '') == 'chunked':
127 131 return environ['wsgi.input']
128 132 else:
129 133 return environ['wsgi.input'].read()
130 134
131 135
132 136 def _maybe_stream_response(response):
133 137 """
134 138 Try to generate chunks from the response if it is chunked.
135 139 """
136 140 if _is_chunked(response):
137 141 return response.raw.read_chunked()
138 142 else:
139 143 return [response.content]
140 144
141 145
142 146 def _is_chunked(response):
143 147 return response.headers.get('Transfer-Encoding', '') == 'chunked'
General Comments 0
You need to be logged in to leave comments. Login now