Welcome, guest | Sign In | My Account | Store | Cart

This extension to xmlrpclib allows us to maintain a session with a JSP server, so that there appears to be a stateful session. It tries to maintain the JSESSIONID call between calls to the server.

Python, 95 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
"""A little Transport layer to maintain the JSESSIONID cookie that
Javaserver pages use to maintain a session.  I'd like to use this
to make xmlrpclib session aware.

Sample usage:

    server = Server("http://foobar.com/baz/servlet/xmlrpc.class")
    print server.get_jsession_id();
    print server.test.sayHello()
    print server.get_jsession_id();
    print server.test.sayGoodbye()
    print server.get_jsession_id();

"""

import xmlrpclib
import Cookie

class JspAuthTransport(xmlrpclib.Transport):
    def __init__(self):
        self.__cookies = Cookie.SmartCookie()

    def request(self, host, handler, request_body, verbose=0):
        # issue XML-RPC request

        h = self.make_connection(host)
        if verbose:
            h.set_debuglevel(1)

        self.send_request(h, handler, request_body)
        self.__sendJsessionCookie(h)
        self.send_host(h, host)
        self.send_user_agent(h)
        self.send_content(h, request_body)

        errcode, errmsg, headers = h.getreply()

        if errcode != 200:
            raise xmlrpclib.ProtocolError(
                host + handler,
                errcode, errmsg,
                headers
                )
        self.verbose = verbose
        self.__processCookies(headers)
        return self.parse_response(h.getfile())


    def get_jsession_id(self):
        if self.__cookies.has_key('JSESSIONID'):
            return self.__cookies['JSESSIONID'].value
        return None


    def __sendJsessionCookie(self, connection):
        if self.__cookies.has_key('JSESSIONID'):
            connection.putheader('Cookie', '$Version="1"; JSESSIONID=%s'
                                 % self.get_jsession_id())


    def __processCookies(self, headers):
        if headers.getheader('Set-Cookie'):
            self.__cookies.load(headers.getheader('Set-Cookie'))


    def send_content(self, connection, request_body):
        connection.putheader("Content-Type", "text/xml")
        connection.putheader("Content-Length", str(len(request_body)))

        connection.endheaders()
        if request_body:
            connection.send(request_body)


class Server:
    """A little wrapper to keep the transport and serverproxy together."""
    def __init__(self, uri):
        self.transport = JspAuthTransport()
	self.serverproxy = xmlrpclib.ServerProxy(uri, self.transport)

    def __getattr__(self, attr):
        return getattr(self.serverproxy, attr)

    def get_jsession_id(self):
        return self.transport.get_jsession_id()



def _test2():
    server = Server("http://www.oreillynet.com/meerkat/xml-rpc/server.php")
    print server.system.listMethods()


if __name__ == '__main__':
    _test2()

This code is not original. grin It's very similar to Amos's code that hacks Zope authentication into xmlrpc at:

http://www.zope.org/Members/Amos/XML-RPC

1 comment

Danny Yoo (author) 21 years, 4 months ago  # | flag

there's some dead code in there. Ooops. I just noticed that I left some dead code: the send_content() function of that transport subclass should be omitted. Sorry about that!