source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/soap.py @ 4020

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/soap.py@4020
Revision 4020, 4.1 KB checked in by pjkersha, 11 years ago (diff)

More work on WSGI SOAPMiddleware

  • Moved soap and wssecurity middleware modules to ndg.security.server.wsgi
  • ... and ZSI Attribute Service Binding to ndg.security.server.zsi
  • test harness - pylons ndgsecurity in Test/ now works with Paste pipeline in ini to enable dynamic config for WS-Security handlers
Line 
1"""NDG Security SOAP Service Middleware
2
3NERC Data Grid Project
4
5This software may be distributed under the terms of the Q Public License,
6version 1.0 or later.
7"""
8__author__ = "P J Kershaw"
9__date__ = "27/05/08"
10__copyright__ = "(C) 2008 STFC & NERC"
11__contact__ = "P.J.Kershaw@rl.ac.uk"
12__revision__ = "$Id$"
13import logging
14log = logging.getLogger(__name__)
15
16from ZSI import EvaluateException, ParseException
17from ZSI.parse import ParsedSoap
18from ZSI.writer import SoapWriter
19from ZSI import fault
20
21from ZSI.ServiceContainer import ServiceSOAPBinding
22       
23class SOAPMiddleware(object):
24    '''Middleware configurable to a given ZSI SOAP binding''' 
25   
26    def __init__(self, app, app_conf, **kw):
27        log.debug("SOAPMiddleware.__init__ ...")
28        self.app = app
29        self.app_conf = app_conf
30        self.app_conf.update(kw)
31           
32        if 'pathInfo' not in self.app_conf:
33            self.app_conf['pathInfo'] = '/'
34       
35        if 'ServiceSOAPBindingClass' in self.app_conf:
36            modName, dot, className = \
37                self.app_conf['ServiceSOAPBindingClass'].rpartition('.')
38           
39            module = __import__(modName, globals(), locals(), [className])
40            serviceSOAPBindingClass = eval('module.' + className)
41           
42            # Check class inherits from ServiceSOAPBinding
43            if not issubclass(serviceSOAPBindingClass, ServiceSOAPBinding):
44                raise TypeError(
45                    "%s class must be derived from ServiceSOAPBinding" % \
46                    self.app_conf['ServiceSOAPBindingClass'])
47        else: 
48            serviceSOAPBindingClass = ServiceSOAPBinding
49                 
50        self.serviceSOAPBinding = serviceSOAPBindingClass()
51
52       
53    def __call__(self, environ, start_response):
54        log.debug("SOAPMiddleware.__call__")
55       
56        # Apply filter for calls
57        if not environ['PATH_INFO'].startswith(self.app_conf['pathInfo']):
58            return self.app(environ, start_response)
59
60        def start_response_wrapper(status, response_headers, exc_info=None):
61            '''Ensure text/xml content type and set content length'''
62            response_headers_alt=[(name,val) for name, val in response_headers\
63                    if name.lower() not in ('content-type', 'content-length')]
64           
65            response_headers_alt += [('content-type', 'text/xml'),
66                                ('content-length', "%d" % len(self.soapOut))]
67                           
68            return start_response(status, 
69                                  response_headers_alt,
70                                  exc_info)
71
72        if 'ZSI.parse.ParsedSoap' in environ:
73            ps = environ['ZSI.parse.ParsedSoap']
74        else:
75            # TODO: allow for chunked data
76            soapIn = environ['wsgi.input'].read(environ['CONTENT_LENGTH'])
77            log.debug("SOAP Request")
78            log.debug("_"*80)
79            log.debug(soapIn)
80            log.debug("_"*80)
81           
82            ps = ParsedSoap(soapIn)
83           
84        method = getattr(self.serviceSOAPBinding, 
85                         'soap_%s' % environ['HTTP_SOAPACTION'].strip('"'))
86       
87        try:
88            req, resp = method(ps)
89        except Exception, e:
90            self._writeFault(req, resp)
91       
92        sw = SoapWriter()
93        sw.serialize(resp)
94       
95        # Make SoapWriter object available to any SOAP filters that follow
96        environ['ZSI.writer.SoapWriter'] = sw
97        self.soapOut = str(sw)
98       
99        log.debug("SOAP Response")
100        log.debug("_"*80)
101        log.debug(self.soapOut)
102        log.debug("_"*80)
103#               
104#        if soap is not None:
105#            return self._writeResponse(request, soap)
106       
107        app = self.app(environ, start_response_wrapper)
108        #start_response("200 OK", [('Content-type', 'text/xml')])
109        return [self.soapOut]
110
111
112def makeFilter(app, app_conf): 
113    from ndgsecurity.config.attributeauthority import AttributeAuthorityWS
114   
115    return SOAPMiddleware(app, app_conf,
116                          ServiceSOAPBinding=AttributeAuthorityWS(),
117                          pathInfo='/AttributeAuthority')
Note: See TracBrowser for help on using the repository browser.