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