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