35
35
36
36
import base64
37
37
import decimal
38
+ from http import HTTPStatus
38
39
import http .client
39
40
import json
40
41
import logging
49
50
log = logging .getLogger ("BitcoinRPC" )
50
51
51
52
class JSONRPCException (Exception ):
52
- def __init__ (self , rpc_error ):
53
+ def __init__ (self , rpc_error , http_status = None ):
53
54
try :
54
55
errmsg = '%(message)s (%(code)i)' % rpc_error
55
56
except (KeyError , TypeError ):
56
57
errmsg = ''
57
58
super ().__init__ (errmsg )
58
59
self .error = rpc_error
60
+ self .http_status = http_status
59
61
60
62
61
63
def EncodeDecimal (o ):
@@ -131,19 +133,26 @@ def get_request(self, *args, **argsn):
131
133
132
134
def __call__ (self , * args , ** argsn ):
133
135
postdata = json .dumps (self .get_request (* args , ** argsn ), default = EncodeDecimal , ensure_ascii = self .ensure_ascii )
134
- response = self ._request ('POST' , self .__url .path , postdata .encode ('utf-8' ))
136
+ response , status = self ._request ('POST' , self .__url .path , postdata .encode ('utf-8' ))
135
137
if response ['error' ] is not None :
136
- raise JSONRPCException (response ['error' ])
138
+ raise JSONRPCException (response ['error' ], status )
137
139
elif 'result' not in response :
138
140
raise JSONRPCException ({
139
- 'code' : - 343 , 'message' : 'missing JSON-RPC result' })
141
+ 'code' : - 343 , 'message' : 'missing JSON-RPC result' }, status )
142
+ elif status != HTTPStatus .OK :
143
+ raise JSONRPCException ({
144
+ 'code' : - 342 , 'message' : 'non-200 HTTP status code but no JSON-RPC error' }, status )
140
145
else :
141
146
return response ['result' ]
142
147
143
148
def batch (self , rpc_call_list ):
144
149
postdata = json .dumps (list (rpc_call_list ), default = EncodeDecimal , ensure_ascii = self .ensure_ascii )
145
150
log .debug ("--> " + postdata )
146
- return self ._request ('POST' , self .__url .path , postdata .encode ('utf-8' ))
151
+ response , status = self ._request ('POST' , self .__url .path , postdata .encode ('utf-8' ))
152
+ if status != HTTPStatus .OK :
153
+ raise JSONRPCException ({
154
+ 'code' : - 342 , 'message' : 'non-200 HTTP status code but no JSON-RPC error' }, status )
155
+ return response
147
156
148
157
def _get_response (self ):
149
158
req_start_time = time .time ()
@@ -162,8 +171,9 @@ def _get_response(self):
162
171
163
172
content_type = http_response .getheader ('Content-Type' )
164
173
if content_type != 'application/json' :
165
- raise JSONRPCException ({
166
- 'code' : - 342 , 'message' : 'non-JSON HTTP response with \' %i %s\' from server' % (http_response .status , http_response .reason )})
174
+ raise JSONRPCException (
175
+ {'code' : - 342 , 'message' : 'non-JSON HTTP response with \' %i %s\' from server' % (http_response .status , http_response .reason )},
176
+ http_response .status )
167
177
168
178
responsedata = http_response .read ().decode ('utf8' )
169
179
response = json .loads (responsedata , parse_float = decimal .Decimal )
@@ -172,7 +182,7 @@ def _get_response(self):
172
182
log .debug ("<-%s- [%.6f] %s" % (response ["id" ], elapsed , json .dumps (response ["result" ], default = EncodeDecimal , ensure_ascii = self .ensure_ascii )))
173
183
else :
174
184
log .debug ("<-- [%.6f] %s" % (elapsed , responsedata ))
175
- return response
185
+ return response , http_response . status
176
186
177
187
def __truediv__ (self , relative_uri ):
178
188
return AuthServiceProxy ("{}/{}" .format (self .__service_url , relative_uri ), self ._service_name , connection = self .__conn )
0 commit comments