Skip to content

Commit ddf98d1

Browse files
committed
Make RPC tests cope with server-side timeout between requests
Python's httplib does not graciously handle disconnections from the http server, resulting in BadStatusLine errors. See https://bugs.python.org/issue3566 "httplib persistent connections violate MUST in RFC2616 sec 8.1.4." This was fixed in Python 3.5. Work around it for now.
1 parent 2190ea6 commit ddf98d1

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

qa/rpc-tests/test_framework/authproxy.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,26 @@ def __getattr__(self, name):
106106
name = "%s.%s" % (self.__service_name, name)
107107
return AuthServiceProxy(self.__service_url, name, connection=self.__conn)
108108

109+
def _request(self, method, path, postdata):
110+
'''
111+
Do a HTTP request, with retry if we get disconnected (e.g. due to a timeout).
112+
This is a workaround for https://bugs.python.org/issue3566 which is fixed in Python 3.5.
113+
'''
114+
headers = {'Host': self.__url.hostname,
115+
'User-Agent': USER_AGENT,
116+
'Authorization': self.__auth_header,
117+
'Content-type': 'application/json'}
118+
try:
119+
self.__conn.request(method, path, postdata, headers)
120+
return self._get_response()
121+
except httplib.BadStatusLine as e:
122+
if e.line == "''": # if connection was closed, try again
123+
self.__conn.close()
124+
self.__conn.request(method, path, postdata, headers)
125+
return self._get_response()
126+
else:
127+
raise
128+
109129
def __call__(self, *args):
110130
AuthServiceProxy.__id_count += 1
111131

@@ -115,13 +135,7 @@ def __call__(self, *args):
115135
'method': self.__service_name,
116136
'params': args,
117137
'id': AuthServiceProxy.__id_count}, default=EncodeDecimal)
118-
self.__conn.request('POST', self.__url.path, postdata,
119-
{'Host': self.__url.hostname,
120-
'User-Agent': USER_AGENT,
121-
'Authorization': self.__auth_header,
122-
'Content-type': 'application/json'})
123-
124-
response = self._get_response()
138+
response = self._request('POST', self.__url.path, postdata)
125139
if response['error'] is not None:
126140
raise JSONRPCException(response['error'])
127141
elif 'result' not in response:
@@ -133,13 +147,7 @@ def __call__(self, *args):
133147
def _batch(self, rpc_call_list):
134148
postdata = json.dumps(list(rpc_call_list), default=EncodeDecimal)
135149
log.debug("--> "+postdata)
136-
self.__conn.request('POST', self.__url.path, postdata,
137-
{'Host': self.__url.hostname,
138-
'User-Agent': USER_AGENT,
139-
'Authorization': self.__auth_header,
140-
'Content-type': 'application/json'})
141-
142-
return self._get_response()
150+
return self._request('POST', self.__url.path, postdata)
143151

144152
def _get_response(self):
145153
http_response = self.__conn.getresponse()

0 commit comments

Comments
 (0)