blob: 9fa17667c3b7ceaf23a90e3f9be1a1bb7291f5a1 [file] [log] [blame]
Fredrik Lundhb9056332001-07-11 17:42:21 +00001#
2# XML-RPC SERVER
3# $Id$
4#
5# an asynchronous XML-RPC server for Medusa
6#
7# written by Sam Rushing
8#
9# Based on "xmlrpcserver.py" by Fredrik Lundh (fredrik@pythonware.com)
10#
11
12import http_server
13import xmlrpclib
14
15import regex
16import string
17import sys
18
19class xmlrpc_handler:
20
21 def match (self, request):
22 # Note: /RPC2 is not required by the spec, so you may override this method.
23 if request.uri[:5] == '/RPC2':
24 return 1
25 else:
26 return 0
27
28 def handle_request (self, request):
29 [path, params, query, fragment] = request.split_uri()
30
31 if request.command in ('post', 'put'):
32 request.collector = collector (self, request)
33 else:
34 request.error (400)
35
36 def continue_request (self, data, request):
37 params, method = xmlrpclib.loads (data)
38 try:
39 # generate response
40 try:
41 response = self.call (method, params)
42 response = (response,)
43 except:
44 # report exception back to server
45 response = xmlrpclib.dumps (
46 xmlrpclib.Fault (1, "%s:%s" % (sys.exc_type, sys.exc_value))
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 "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 = string.atoi (cl)
80 # using a 'numeric' terminator
81 self.request.channel.set_terminator (cl)
82
83 def collect_incoming_data (self, data):
84 self.data = self.data + data
85
86 def found_terminator (self):
87 # set the terminator back to the default
88 self.request.channel.set_terminator ('\r\n\r\n')
89 self.handler.continue_request (self.data, self.request)
90
91if __name__ == '__main__':
92
93 class rpc_demo (xmlrpc_handler):
94
95 def call (self, method, params):
96 print 'method="%s" params=%s' % (method, params)
97 return "Sure, that works"
98
99 import asyncore
100 import http_server
101
102 hs = http_server.http_server ('', 8000)
103 rpc = rpc_demo()
104 hs.install_handler (rpc)
105
106 asyncore.loop()