Decoupled SimpleXMLRPCRequestHandler subclass

and added simple introspection
This commit is contained in:
Dmitri Bogomolov 2018-10-25 17:52:19 +03:00
parent f4bf3bac2a
commit 6a089e0f88
Signed by untrusted user: g1itch
GPG Key ID: 720A756F18DEED13
1 changed files with 37 additions and 23 deletions

View File

@ -68,9 +68,8 @@ class StoppableXMLRPCServer(SimpleXMLRPCServer):
"""A SimpleXMLRPCServer that honours state.shutdown""" """A SimpleXMLRPCServer that honours state.shutdown"""
allow_reuse_address = True allow_reuse_address = True
def serve_forever(self): def serve_forever(self, poll_interval=None):
"""Start the SimpleXMLRPCServer""" """Start the SimpleXMLRPCServer"""
# pylint: disable=arguments-differ
while state.shutdown == 0: while state.shutdown == 0:
self.handle_request() self.handle_request()
@ -121,6 +120,7 @@ class singleAPI(StoppableThread):
'bitmessagesettings', 'apiport', str(port)) 'bitmessagesettings', 'apiport', str(port))
BMConfigParser().save() BMConfigParser().save()
break break
se.register_instance(BMXMLRPCDispatcher())
se.register_introspection_functions() se.register_introspection_functions()
apiNotifyPath = BMConfigParser().safeGet( apiNotifyPath = BMConfigParser().safeGet(
@ -185,9 +185,8 @@ class command(object):
# Modified by Jonathan Warren (Atheros). # Modified by Jonathan Warren (Atheros).
# Further modified by the Bitmessage developers # Further modified by the Bitmessage developers
# http://code.activestate.com/recipes/501148 # http://code.activestate.com/recipes/501148
class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler, object): class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
"""The main API handler""" """The main API handler"""
__metaclass__ = CommandHandler
def do_POST(self): def do_POST(self):
""" """
@ -219,6 +218,18 @@ class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler, object):
size_remaining -= len(L[-1]) size_remaining -= len(L[-1])
data = ''.join(L) data = ''.join(L)
# pylint: disable=attribute-defined-outside-init
self.cookies = []
validuser = self.APIAuthenticateClient()
if not validuser:
time.sleep(2)
# ProtocolError?
response = (
"RPC Username or password incorrect or HTTP header"
" lacks authentication at all."
)
else:
# In previous versions of SimpleXMLRPCServer, _dispatch # In previous versions of SimpleXMLRPCServer, _dispatch
# could be overridden in this class, instead of in # could be overridden in this class, instead of in
# SimpleXMLRPCDispatcher. To maintain backwards compatibility, # SimpleXMLRPCDispatcher. To maintain backwards compatibility,
@ -228,7 +239,7 @@ class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler, object):
response = self.server._marshaled_dispatch( response = self.server._marshaled_dispatch(
data, getattr(self, '_dispatch', None) data, getattr(self, '_dispatch', None)
) )
except BaseException: # This should only happen if the module is buggy except Exception: # This should only happen if the module is buggy
# internal error, report as HTTP server error # internal error, report as HTTP server error
self.send_response(500) self.send_response(500)
self.end_headers() self.end_headers()
@ -276,6 +287,11 @@ class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler, object):
return False return False
class BMXMLRPCDispatcher(object):
"""This class is used to dispatch API commands"""
__metaclass__ = CommandHandler
def _decode(self, text, decode_type): def _decode(self, text, decode_type):
try: try:
if decode_type == 'hex': if decode_type == 'hex':
@ -1216,15 +1232,6 @@ class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler, object):
state.last_api_response = time.time() state.last_api_response = time.time()
def _dispatch(self, method, params): def _dispatch(self, method, params):
# pylint: disable=attribute-defined-outside-init
self.cookies = []
validuser = self.APIAuthenticateClient()
if not validuser:
time.sleep(2)
# ProtocolError?
return "RPC Username or password incorrect or HTTP header lacks authentication at all."
_fault = None _fault = None
try: try:
@ -1246,3 +1253,10 @@ class BMXMLRPCRequestHandler(SimpleXMLRPCRequestHandler, object):
return str(_fault) return str(_fault)
else: else:
raise _fault # pylint: disable=raising-bad-type raise _fault # pylint: disable=raising-bad-type
def _listMethods(self):
"""List all API commands"""
return self._handlers.keys()
def _methodHelp(self, method):
return self._handlers[method].__doc__