source: TI12-security/trunk/python/ndg_security_common/ndg/security/common/soap/client.py @ 5681

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg_security_common/ndg/security/common/soap/client.py@5681
Revision 5681, 6.7 KB checked in by pjkersha, 11 years ago (diff)

Integrated SOAP SAML Attribute Query interface into Attribute Authority Client unit tests.

Line 
1"""SOAP client module for NDG Security - initially for use with SAML SOAP
2binding based Attribute Authority interface
3
4NERC DataGrid Project
5"""
6__author__ = "P J Kershaw"
7__date__ = "27/07/09"
8__copyright__ = ""
9__license__ = "BSD - see LICENSE file in top-level directory"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = '$Id:$'
12
13from ndg.security.common.soap import SOAPEnvelopeBase
14
15class SOAPClientError(Exception):
16    """Base class for SOAP Client exceptions"""
17   
18class HTTPException(SOAPClientError):
19    """Server returned HTTP code error code"""
20    def __init__(self, *arg, **kw):
21        Exception.__init__(self, *arg, **kw)
22        self.urllib2Response = None
23
24class SOAPParseError(SOAPClientError):
25    """Error parsing SOAP response"""
26   
27           
28class SOAPClientBase(object):
29    """Handle client request to a SOAP Service"""
30    def __init__(self):
31        self.__responseEnvelopeClass = None
32
33    def _getResponseEnvelopeClass(self):
34        return self.__responseEnvelopeClass
35
36    def _setResponseEnvelopeClass(self, value):
37        if not issubclass(value, SOAPEnvelopeBase):
38            raise TypeError("Setting SOAP envelope class: expecting %r, got "
39                            "%r" % (SOAPEnvelopeBase, type(value)))
40        self.__responseEnvelopeClass = value
41
42    responseEnvelopeClass = property(fget=_getResponseEnvelopeClass, 
43                                     fset=_setResponseEnvelopeClass, 
44                                     doc="Set the class for handling "
45                                         "the SOAP envelope responses")
46     
47    def send(self, soapRequest):
48        raise NotImplementedError()
49
50
51class _SoapIOBase(object):
52    """Base class for request and response classes"""
53   
54    def __init__(self):
55        self.__envelope = None
56
57    def _getEnvelope(self):
58        return self.__envelope
59
60    def _setEnvelope(self, value):
61        if not isinstance(value, SOAPEnvelopeBase):
62            raise TypeError('Setting SOAP envelope object: expecting %r; got '
63                            '%r' % (SOAPEnvelopeBase, type(value)))
64                           
65        self.__envelope = value
66
67    envelope = property(fget=_getEnvelope, 
68                        fset=_setEnvelope, 
69                        doc="SOAP Envelope object used in request/response")
70
71       
72class SOAPRequestBase(object):
73    """Interface for SOAP requests"""
74    def __init__(self):
75        self.__url = None
76        self.__envelope = None
77
78    def _getUrl(self):
79        return self.__url
80
81    def _setUrl(self, value):
82        if not isinstance(value, basestring):
83            raise TypeError('Setting request URL: expecting %r; got '
84                            '%r' % (basestring, type(value)))
85        self.__url = value
86
87    url = property(fget=_getUrl, fset=_setUrl, doc="URL of SOAP endpoint")
88
89   
90class SOAPResponseBase(_SoapIOBase):
91    """Interface for SOAP responses"""
92
93
94import urllib2
95
96class UrlLib2SOAPRequest(SOAPRequestBase): 
97    """Interface for UrlLib2 based SOAP Requests"""
98   
99   
100class UrlLib2SOAPResponse(SOAPResponseBase):
101    """Interface for UrlLib2 based SOAP Responses"""
102    def __init__(self):
103        self.__fileobject = None
104
105    def _getFileobject(self):
106        return self.__fileobject
107
108    fileobject = property(fget=_getFileobject,
109                          doc="urllib2 file object returned from request")
110
111   
112class UrlLib2SOAPClient(SOAPClientBase):
113    """urllib2 based SOAP Client"""
114   
115    def __init__(self):
116        super(UrlLib2SOAPClient, self).__init__()
117        self.__openerDirector = urllib2.OpenerDirector()
118        self.__openerDirector.add_handler(urllib2.UnknownHandler())
119        self.__openerDirector.add_handler(urllib2.HTTPHandler())
120        self.__timeout = None
121
122    def _getTimeout(self):
123        return self.__timeout
124
125    def _setTimeout(self, value):
126        if not isinstance(value, (int, float)):
127            raise TypeError("Setting request timeout: got %r, expecting int "
128                            "float type" % type(value))
129        self.__timeout = value
130
131    timeout = property(fget=_getTimeout, 
132                       fset=_setTimeout, 
133                       doc="Timeout (seconds) for requests")
134
135    def _getOpenerDirector(self):
136        return self.__openerDirector
137
138    def _setOpenerDirector(self, value):
139        """This shouldn't need to be used much in practice because __init__
140        creates one"""
141        if not isinstance(value, urllib2.OpenerDirector):
142            raise TypeError("Setting opener: expecting %r; got %r" % 
143                            (urllib2.OpenerDirector, value.__class__))
144        self.__openerDirector = value
145
146    openerDirector = property(fget=_getOpenerDirector, 
147                              fset=_setOpenerDirector, 
148                              doc="urllib2.OpenerDirector defines the "
149                                  "opener(s) for handling requests")
150   
151    def send(self, soapRequest):
152        """Make a request to the given URL with a SOAP Request object"""
153       
154        if not isinstance(soapRequest, UrlLib2SOAPRequest):
155            raise TypeError('UrlLib2SOAPClient.makeRequest: expecting %r '
156                            'derived type for SOAP request, got %r' % 
157                            (self.responseEnvelopeClass,soapRequest.__class__))
158           
159        if not isinstance(soapRequest.envelope, self.responseEnvelopeClass):
160            raise TypeError('UrlLib2SOAPClient.makeRequest: expecting %r '
161                            'derived type for SOAP envelope, got %r' % 
162                            (self.responseEnvelopeClass,soapRequest.__class__))
163                           
164        if self.timeout is not None:
165            arg = (self.timeout,)
166        else:
167            arg = ()
168           
169        soapRequestStr = soapRequest.envelope.serialize()
170        soapResponse = UrlLib2SOAPResponse()
171        response = self.openerDirector.open(soapRequest.url, 
172                                            soapRequestStr, 
173                                            *arg)
174        if response.code != 200:
175            output = response.read()
176            excep = HTTPException("Response is: %d %s" % (response.code, 
177                                                          response.msg))
178            excep.urllib2Response = response
179            raise excep
180       
181       
182        soapResponse.fileObject = response
183        soapResponse.envelope = self.responseEnvelopeClass() 
184       
185        try:
186            soapResponse.envelope.parse(soapResponse.fileObject)
187        except Exception, e:
188            raise SOAPParseError("Error parsing response for request to [%s]: "
189                                 "%s"
190                                 % (soapRequest.url, e))
191           
192        return soapResponse
193
194       
195   
196   
Note: See TracBrowser for help on using the repository browser.