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