##// END OF EJS Templates
http-backend: catch errors from HTTP calls that are not raising exceptions, but...
marcink -
r1410:a4133cfc default
parent child Browse files
Show More
@@ -216,7 +216,9 b' class CurlSession(object):'
216 curl.setopt(curl.WRITEDATA, response_buffer)
216 curl.setopt(curl.WRITEDATA, response_buffer)
217 curl.perform()
217 curl.perform()
218
218
219 return CurlResponse(response_buffer)
219 status_code = curl.getinfo(pycurl.HTTP_CODE)
220
221 return CurlResponse(response_buffer, status_code)
220
222
221
223
222 class CurlResponse(object):
224 class CurlResponse(object):
@@ -228,13 +230,18 b' class CurlResponse(object):'
228 `requests` as a drop in replacement for benchmarking purposes.
230 `requests` as a drop in replacement for benchmarking purposes.
229 """
231 """
230
232
231 def __init__(self, response_buffer):
233 def __init__(self, response_buffer, status_code):
232 self._response_buffer = response_buffer
234 self._response_buffer = response_buffer
235 self._status_code = status_code
233
236
234 @property
237 @property
235 def content(self):
238 def content(self):
236 return self._response_buffer.getvalue()
239 return self._response_buffer.getvalue()
237
240
241 @property
242 def status_code(self):
243 return self._status_code
244
238
245
239 def _create_http_rpc_session():
246 def _create_http_rpc_session():
240 session = CurlSession()
247 session = CurlSession()
@@ -196,10 +196,15 b' def _remote_call(url, payload, exception'
196 except pycurl.error as e:
196 except pycurl.error as e:
197 raise exceptions.HttpVCSCommunicationError(e)
197 raise exceptions.HttpVCSCommunicationError(e)
198
198
199 if response.status_code >= 400:
200 log.error('Call to %s returned non 200 HTTP code: %s',
201 url, response.status_code)
202 raise exceptions.HttpVCSCommunicationError(repr(response.content))
203
199 try:
204 try:
200 response = msgpack.unpackb(response.content)
205 response = msgpack.unpackb(response.content)
201 except Exception:
206 except Exception:
202 log.exception('Failed to decode repsponse %r', response.content)
207 log.exception('Failed to decode response %r', response.content)
203 raise
208 raise
204
209
205 error = response.get('error')
210 error = response.get('error')
@@ -25,20 +25,7 b' import msgpack'
25 import pytest
25 import pytest
26
26
27 from rhodecode.lib import vcs
27 from rhodecode.lib import vcs
28 from rhodecode.lib.vcs import client_http
28 from rhodecode.lib.vcs import client_http, exceptions
29
30
31 def test_uses_persistent_http_connections(caplog, vcsbackend_hg):
32 repo = vcsbackend_hg.repo
33 remote_call = repo._remote.branches
34
35 with caplog.at_level(logging.INFO):
36 for x in range(5):
37 remote_call(normal=True, closed=False)
38
39 new_connections = [
40 r for r in caplog.record_tuples if is_new_connection(*r)]
41 assert len(new_connections) <= 1
42
29
43
30
44 def is_new_connection(logger, level, message):
31 def is_new_connection(logger, level, message):
@@ -53,7 +40,24 b' def stub_session():'
53 Stub of `requests.Session()`.
40 Stub of `requests.Session()`.
54 """
41 """
55 session = mock.Mock()
42 session = mock.Mock()
56 session.post().content = msgpack.packb({})
43 post = session.post()
44 post.content = msgpack.packb({})
45 post.status_code = 200
46
47 session.reset_mock()
48 return session
49
50
51 @pytest.fixture
52 def stub_fail_session():
53 """
54 Stub of `requests.Session()`.
55 """
56 session = mock.Mock()
57 post = session.post()
58 post.content = msgpack.packb({'error': '500'})
59 post.status_code = 500
60
57 session.reset_mock()
61 session.reset_mock()
58 return session
62 return session
59
63
@@ -68,6 +72,29 b' def stub_session_factory(stub_session):'
68 return session_factory
72 return session_factory
69
73
70
74
75 @pytest.fixture
76 def stub_session_failing_factory(stub_fail_session):
77 """
78 Stub of `rhodecode.lib.vcs.client_http.ThreadlocalSessionFactory`.
79 """
80 session_factory = mock.Mock()
81 session_factory.return_value = stub_fail_session
82 return session_factory
83
84
85 def test_uses_persistent_http_connections(caplog, vcsbackend_hg):
86 repo = vcsbackend_hg.repo
87 remote_call = repo._remote.branches
88
89 with caplog.at_level(logging.INFO):
90 for x in range(5):
91 remote_call(normal=True, closed=False)
92
93 new_connections = [
94 r for r in caplog.record_tuples if is_new_connection(*r)]
95 assert len(new_connections) <= 1
96
97
71 def test_repo_maker_uses_session_for_classmethods(stub_session_factory):
98 def test_repo_maker_uses_session_for_classmethods(stub_session_factory):
72 repo_maker = client_http.RepoMaker(
99 repo_maker = client_http.RepoMaker(
73 'server_and_port', 'endpoint', 'test_dummy_scm', stub_session_factory)
100 'server_and_port', 'endpoint', 'test_dummy_scm', stub_session_factory)
@@ -94,3 +121,13 b' def test_connect_passes_in_the_same_sess'
94 session_factory.return_value = stub_session
121 session_factory.return_value = stub_session
95
122
96 vcs.connect_http('server_and_port')
123 vcs.connect_http('server_and_port')
124
125
126 def test_repo_maker_uses_session_that_throws_error(
127 stub_session_failing_factory, config):
128 repo_maker = client_http.RepoMaker(
129 'server_and_port', 'endpoint', 'test_dummy_scm', stub_session_failing_factory)
130 repo = repo_maker('stub_path', config)
131
132 with pytest.raises(exceptions.HttpVCSCommunicationError):
133 repo.example_call()
General Comments 0
You need to be logged in to leave comments. Login now