1# -*- Mode: Python -*- 2 3# See http://www.xml-rpc.com/ 4# http://www.pythonware.com/products/xmlrpc/ 5 6# Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com) 7 8VERSION = "$Id: xmlrpc_handler.py,v 1.6 2004/04/21 14:09:24 akuchling Exp $" 9 10from supervisor.compat import as_string 11 12import supervisor.medusa.http_server as http_server 13try: 14 import xmlrpclib 15except: 16 import xmlrpc.client as xmlrpclib 17 18import sys 19 20class xmlrpc_handler: 21 22 def match (self, request): 23 # Note: /RPC2 is not required by the spec, so you may override this method. 24 if request.uri[:5] == '/RPC2': 25 return 1 26 else: 27 return 0 28 29 def handle_request (self, request): 30 if request.command == 'POST': 31 request.collector = collector (self, request) 32 else: 33 request.error (400) 34 35 def continue_request (self, data, request): 36 params, method = xmlrpclib.loads (data) 37 try: 38 # generate response 39 try: 40 response = self.call (method, params) 41 if type(response) != type(()): 42 response = (response,) 43 except: 44 # report exception back to server 45 response = xmlrpclib.dumps ( 46 xmlrpclib.Fault (1, "%s:%s" % (sys.exc_info()[0], sys.exc_info()[1])) 47 ) 48 else: 49 response = xmlrpclib.dumps (response, methodresponse=1) 50 except: 51 # internal error, report as HTTP server error 52 request.error (500) 53 else: 54 # got a valid XML RPC response 55 request['Content-Type'] = 'text/xml' 56 request.push (response) 57 request.done() 58 59 def call (self, method, params): 60 # override this method to implement RPC methods 61 raise Exception("NotYetImplemented") 62 63class collector: 64 65 """gathers input for POST and PUT requests""" 66 67 def __init__ (self, handler, request): 68 69 self.handler = handler 70 self.request = request 71 self.data = [] 72 73 # make sure there's a content-length header 74 cl = request.get_header ('content-length') 75 76 if not cl: 77 request.error (411) 78 else: 79 cl = int(cl) 80 # using a 'numeric' terminator 81 self.request.channel.set_terminator (cl) 82 83 def collect_incoming_data (self, data): 84 self.data.append(data) 85 86 def found_terminator (self): 87 # set the terminator back to the default 88 self.request.channel.set_terminator (b'\r\n\r\n') 89 # convert the data back to text for processing 90 data = as_string(b''.join(self.data)) 91 self.handler.continue_request (data, self.request) 92 93if __name__ == '__main__': 94 95 class rpc_demo (xmlrpc_handler): 96 97 def call (self, method, params): 98 print('method="%s" params=%s' % (method, params)) 99 return "Sure, that works" 100 101 import supervisor.medusa.asyncore_25 as asyncore 102 103 hs = http_server.http_server ('', 8000) 104 rpc = rpc_demo() 105 hs.install_handler (rpc) 106 107 asyncore.loop() 108