1 # -*- Mode: Python; tab-width: 4 -*-
  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 
  8 import http_server
  9 import xmlrpclib
 10 
 11 import regex
 12 import string
 13 import sys
 14 
 15 class xmlrpc_handler:
 16 
 17    def match (self, request):
 18       # Note: /RPC2 is not required by the spec, so you may override this method.
 19       if request.uri[:5] == '/RPC2':
 20          return 1
 21       else:
 22          return 0
 23 
 24    def handle_request (self, request):
 25       [path, params, query, fragment] = request.split_uri()
 26       
 27       if request.command in ('post', 'put'):
 28          request.collector = collector (self, request)
 29       else:
 30          request.error (400)
 31 
 32    def continue_request (self, data, request):
 33       params, method = xmlrpclib.loads (data)
 34       try:
 35          # generate response
 36          try:
 37             response = self.call (method, params)
 38             if type(response) != type(()):
 39                response = (response,)
 40          except:
 41             # report exception back to server
 42             response = xmlrpclib.dumps (
 43                xmlrpclib.Fault (1, "%s:%s" % (sys.exc_type, sys.exc_value))
 44                )
 45          else:
 46             response = xmlrpclib.dumps (response, methodresponse=1)
 47       except:
 48          # internal error, report as HTTP server error
 49          request.error (500)
 50       else:
 51          # got a valid XML RPC response
 52          request['Content-Type'] = 'text/xml'
 53          request.push (response)
 54          request.done()
 55 
 56    def call (self, method, params):
 57       # override this method to implement RPC methods
 58       raise "NotYetImplemented"
 59 
 60 class collector:
 61 
 62    "gathers input for POST and PUT requests"
 63 
 64    def __init__ (self, handler, request):
 65 
 66       self.handler = handler
 67       self.request = request
 68       self.data = ''
 69 
 70       # make sure there's a content-length header
 71       cl = request.get_header ('content-length')
 72 
 73       if not cl:
 74          request.error (411)
 75       else:
 76          cl = string.atoi (cl)
 77          # using a 'numeric' terminator
 78          self.request.channel.set_terminator (cl)
 79 
 80    def collect_incoming_data (self, data):
 81       self.data = self.data + data
 82 
 83    def found_terminator (self):
 84       # set the terminator back to the default
 85       self.request.channel.set_terminator ('\r\n\r\n')
 86       self.handler.continue_request (self.data, self.request)
 87 
 88 if __name__ == '__main__':
 89 
 90    class rpc_demo (xmlrpc_handler):
 91       
 92       def call (self, method, params):
 93          print 'method="%s" params=%s' % (method, params)
 94          return "Sure, that works"
 95 
 96    import asyncore
 97    import http_server
 98 
 99    hs = http_server.http_server ('', 8000)
100    rpc = rpc_demo()
101    hs.install_handler (rpc)
102    
103    asyncore.loop()


syntax highlighted by Code2HTML, v. 0.9.1