Beispiel #1
0
def make_soap_envelope(message, tns=None, header_elements=None):
    '''
    This method takes the results from a soap method call, and wraps them
    in the appropriate soap envelope with any specified headers

    @param the message of the soap envelope, either an element or list of elements
    @param any header elements to be included in the soap response
    @returns the envelope element
    '''
    
    envelope = ElementTree.Element('SOAP-ENV:Envelope')
    if tns:
        envelope.set('xmlns:tns',tns)
        envelope.set('xmlns',tns)

    envelope.set('xmlns:SOAP-ENV','http://schemas.xmlsoap.org/soap/envelope/')
    envelope.set('xmlns:xsi','http://www.w3.org/1999/XMLSchema-instance')
    envelope.set('xmlns:xs','http://www.w3.org/2001/XMLSchema')
    
    if header_elements:
        headerElement = ElementTree.SubElement(envelope,'SOAP-ENV:Header')
        
        for h in header_elements:
            headerElement.append(h)
   
    body = ElementTree.SubElement(envelope,'SOAP-ENV:Body')

    if type(message) == list:
        for m in message:
            body.append(m)
    elif message != None:
        body.append(message)

    return envelope
Beispiel #2
0
    def _add_messages_for_methods(self, root, methods):
        '''
        A private method for adding message elements to the wsdl
        @param the the root element of the wsdl
        @param the list of methods.        
        '''
        messages = []
        #make messages
        for method in methods:
            methodName = method.name
            # making in part
            inMessage  = ElementTree.Element('message')
            inMessage.set('name',method.inMessage.typ)

            if len(method.inMessage.params) > 0:
                inPart = ElementTree.SubElement(inMessage,'part')
                inPart.set('name',method.inMessage.name)
                inPart.set('element','tns:'+method.inMessage.typ)

            messages.append(inMessage)

            # making out part                
            outMessage = ElementTree.Element('message')
            outMessage.set('name',method.outMessage.typ)
            if len(method.outMessage.params) > 0:
                outPart = ElementTree.SubElement(outMessage,'part')
                outPart.set('name', method.outMessage.name)
                outPart.set('element', 'tns:'+method.outMessage.typ)
            messages.append(outMessage)
            
        for message in messages:
            root.append(message)
Beispiel #3
0
    def to_xml(cls, value, name='SOAP-ENV:Fault'):

        fault = ElementTree.Element(name)
        ElementTree.SubElement(fault, 'faultcode').text = value.faultcode
        ElementTree.SubElement(fault, 'faultstring').text = value.faultstring
        detail = ElementTree.SubElement(fault, 'detail').text = value.detail
        return fault
Beispiel #4
0
    def __call__(self, data, raw=False):
        e = data.to_xml(data, data.__class__.__name__)
        envelope = make_soap_envelope(e)
        body = et.tostring(envelope)
        methodName = '\"%s\"' % self.method
        httpHeaders = {
            "Content-Length": len(body),
            "Content-type": 'text/xml; charset="UTF-8"',
            "Accept":
            "application/soap+xml, application/dime, multipart/related, text/*",
            'User-Agent': 'Soaplib/1.0',
            'SOAPAction': methodName
        }
        scheme, host, path = split_url(self.host)
        if scheme == "http":
            conn = httplib.HTTPConnection(host)
        elif scheme == "https":
            conn = httplib.HTTPSConnection(host)
        else:
            raise RuntimeError("Unsupported URI connection scheme: %s" %
                               scheme)

        conn.request("POST", path, body=body, headers=httpHeaders)
        response = conn.getresponse()
        raw_data = response.read()

        retval = et.fromstring(raw_data)
        d = retval.find(
            '{http://schemas.xmlsoap.org/soap/envelope/}Body').getchildren()[0]

        if raw:
            return d
        return objectify(d)
Beispiel #5
0
 def to_xml(cls, value, name='retval'):
     if type(value) == str:
         value = ElementTree.fromstring(value)
     e = ElementTree.Element(name)
     e.set('xmlns', '')
     e.append(value)
     return e
Beispiel #6
0
 def __call__(self, data, raw=False):
     e = data.to_xml(data, data.__class__.__name__)
     envelope = make_soap_envelope(e)
     body = et.tostring(envelope)
     methodName = '\"%s\"' % self.method
     httpHeaders = {
         'Content-Length': len(body),
         'Content-type': 'text/xml; charset="UTF-8"',
         'Accept': ('application/soap+xml, application/dime, '
                    'multipart/related, text/*'),
         'User-Agent': 'Soaplib/1.0',
         'SOAPAction': methodName,
     }
     scheme, host, path = split_url(self.host)
     if scheme == "http":
         conn = httplib.HTTPConnection(host)
     elif scheme == "https":
         conn = httplib.HTTPSConnection(host)
     else:
         raise RuntimeError("Unsupported URI connection scheme: %s" %
             scheme)
     conn.request("POST", path, body=body, headers=httpHeaders)
     response = conn.getresponse()
     raw_data = response.read()
     retval = et.fromstring(raw_data)
     pattern = '{http://schemas.xmlsoap.org/soap/envelope/}Body'
     node = retval.find(pattern).getchildren()[0]
     if raw:
         return node
     return objectify(node)
Beispiel #7
0
 def to_xml(self, data, name='xsd:retval'):
     element = ElementTree.Element(name)
     for k, v in data.items():
         item = ElementTree.SubElement(element,
                                       '%sItem' % self.get_datatype())
         key = ElementTree.SubElement(item, 'key')
         key.text = k
         ser = self.serializer
         if v == None:
             ser = Null
         item.append(ser.to_xml(v, 'value'))
     return element
Beispiel #8
0
def create_callback_info_headers(messageId, replyTo):
    '''Creates MessageId and ReplyTo headers for initiating an async function'''
    messageIdElement = ElementTree.Element(
        '{http://schemas.xmlsoap.org/ws/2003/03/addressing}MessageID')
    messageIdElement.text = messageId

    replyToElement = ElementTree.Element(
        '{http://schemas.xmlsoap.org/ws/2003/03/addressing}ReplyTo')
    addressElement = ElementTree.SubElement(
        replyToElement,
        '{http://schemas.xmlsoap.org/ws/2003/03/addressing}Address')
    addressElement.text = replyTo
    return messageIdElement, replyToElement
Beispiel #9
0
    def test_soap_envelope(self):
        m = Message('myMessage',[('p',Person)])
        env = make_soap_envelope(m.to_xml(Person()))
        
        self.assertTrue(env.tag.endswith('Envelope'))
        self.assertTrue(env.getchildren()[0].tag.endswith('Body'))

        m = Message('myMessage',[('p',Person)])
        env = make_soap_envelope(m.to_xml(Person()), header_elements=[et.Element('header1'),et.Element('header2')])

        env = et.fromstring(et.tostring(env))
        
        self.assertTrue(env.getchildren()[0].tag.endswith('Header'))
        self.assertEquals(len(env.getchildren()[0].getchildren()),2)
        self.assertTrue(env.getchildren()[1].tag.endswith('Body'))
Beispiel #10
0
def create_xml_subelement(parent, name):
    '''
    Factory method to create a new XML subelement
    '''
    if not name.startswith("{") and None in parent.nsmap:
        name = qualify(name, parent.nsmap[None])
    return ElementTree.SubElement(parent, name)
Beispiel #11
0
 def to_xml(cls, value, name="retval"):
     if type(value) == str:
         value = ElementTree.fromstring(value)
     e = ElementTree.Element(name)
     e.set("xmlns", "")
     e.append(value)
     return e
Beispiel #12
0
    def _add_schema(self, types, methods):
        '''A private method for adding the appropriate entries
        to the schema for the types in the specified methods
        @param the schema node to add the schema elements to
        @param the list of methods.
        '''
        schema_entries = {}
        for method in methods:
            params = method.inMessage.params 
            returns = method.outMessage.params

            for name,param in params:
                param.add_to_schema(schema_entries)

            if returns:
                returns[0][1].add_to_schema(schema_entries)

            method.inMessage.add_to_schema(schema_entries)
            method.outMessage.add_to_schema(schema_entries)


        schemaNode = ElementTree.SubElement(types, "schema")
        schemaNode.set("targetNamespace", self.__tns__)
        schemaNode.set("xmlns", "http://www.w3.org/2001/XMLSchema")
        
        for xxx, node in schema_entries.items():
            schemaNode.append(node)
                        
        return schemaNode
Beispiel #13
0
 def importtypes(self, document):
     """ 
         Processes any imported xmlschema in a wsdl:types element
         within document, returns a soaplib.parsers.typeparse.TypeParser
         containing the parsed schema. 
         
     """
     for t in document.findall(wsdlqname+"types"):
         url = None            
         for s in t.findall(schqname+"schema"):
             for i in s.findall(schqname+"import"):
                 url = i.get('schemaLocation')
         if url is not None:
             #work out if relative or absolute url
             if '://' not in url:
                 #relative
                 url = path.join(path.dirname(self.url), url)
             f = ulib.urlopen(url)
             d = f.read()
             f.close()
             element = ElementTree.fromstring(d)
         else:
             #inline schema
             for element in t.findall(schqname+"schema"):
                 self._add_tp(TypeParser(element, global_ctypes=self.ctypes, global_elements=self.elements))
             return
         self._add_tp(TypeParser(element, global_ctypes=self.ctypes, global_elements=self.elements))
     return
Beispiel #14
0
 def importwsdl(self, document):
     """ 
         Processes any wsdl documents imported by document 
         (messages are sometimes held in a seperate document, for example).
         Recusively calls WsdlParser to descend through imports
     """
     reimport = 0
     for imp in document.findall('%simport' % wsdlqname):
         url = str(imp.get('location'))
         #work out if relative or absolute url
         if '://' not in url:
             #relative
             url = path.join(path.dirname(self.url), url)
         f = ulib.urlopen(url)
         d = f.read()
         f.close()
         root = ElementTree.fromstring(d)
         wp = WSDLParser(root, url)
         for cats in ['ctypes', 'elements', 'messagecat', 'portcat', 'bindingcat']:
             getattr(self, cats).update(getattr(wp, cats))
         document.remove(imp)
         if self.tp is None:
             self.tp = wp.tp
         elif wp.tp is not None:
             self.tp.ctypes.update(wp.tp.ctypes)
             self.tp.elements.update(wp.tp.elements)
Beispiel #15
0
 def to_xml(cls,value,name='retval'):
     if type(value) == str:
         value = ElementTree.fromstring(value)
     e = ElementTree.Element(name)
     e.set('xmlns','')
     e.append(value) 
     return e 
Beispiel #16
0
    def to_xml(cls,value,name='retval'):
        '''This class method takes the data from the attachment and 
        base64 encodes it as the text of an Element.  An attachment can
        specify a filename and if no data is given, it will read the data 
        from the file
        '''
        if value.__class__ is not Attachment:
            raise Exception("Do not know how to serialize class %s"%type(value))
            
        element = ElementTree.Element(name)
        element.set('xmlns','')
        if value.data:
            # the data has already been loaded, just encode
            # and return the element
            element.text = base64.encodestring(value.data)
        elif value.fileName:
            # the data hasn't been loaded, but a file has been
            # specified
            data_string = cStringIO.StringIO()

            fileName = value.fileName
            file = open(fileName,'rb')
            base64.encode(file, data_string)
            file.close()

            # go back to the begining of the data
            data_string.seek(0)
            element.text = str(data_string.read())
        else:
            raise Exception("Neither data nor a filename has been specified")
        
        return element    
Beispiel #17
0
 def importtypes(self, document):
     """ 
         Processes any imported xmlschema in a wsdl:types element
         within document, returns a soaplib.parsers.typeparse.TypeParser
         containing the parsed schema. 
         
     """
     location = None
     for t in document.findall(wsdlqname + "types"):
         url = None
         for s in t.findall(schqname + "schema"):
             for i in s.findall(schqname + "import"):
                 url = i.get('schemaLocation')
         if url is not None:
             #work out if relative or absolute url
             if '://' not in url:
                 #relative
                 url = path.join(path.dirname(self.url), url)
             f = ulib.urlopen(url)
             d = f.read()
             f.close()
             element = ElementTree.fromstring(d)
         else:
             #inline schema
             for element in t.findall(schqname + "schema"):
                 self._add_tp(
                     TypeParser(element,
                                global_ctypes=self.ctypes,
                                global_elements=self.elements))
             return
         self._add_tp(
             TypeParser(element,
                        global_ctypes=self.ctypes,
                        global_elements=self.elements))
     return
Beispiel #18
0
 def importwsdl(self, document):
     """ 
         Processes any wsdl documents imported by document 
         (messages are sometimes held in a seperate document, for example).
         Recusively calls WsdlParser to descend through imports
     """
     reimport = 0
     for imp in document.findall('%simport' % wsdlqname):
         url = str(imp.get('location'))
         #work out if relative or absolute url
         if '://' not in url:
             #relative
             url = path.join(path.dirname(self.url), url)
         f = ulib.urlopen(url)
         d = f.read()
         f.close()
         root = ElementTree.fromstring(d)
         wp = WSDLParser(root, url)
         for cats in [
                 'ctypes', 'elements', 'messagecat', 'portcat', 'bindingcat'
         ]:
             getattr(self, cats).update(getattr(wp, cats))
         document.remove(imp)
         for tp in wp.tps:
             self._add_tp(tp)
Beispiel #19
0
def element2dict(element):
    deprecate('element2dict')
    if type(element) == str:
        element = ElementTree.fromstring(element)

    children = element.getchildren()
    tag = element.tag.split('}')[-1]
    return {tag: _element2dict(children)}
Beispiel #20
0
    def add_to_schema(cls, schema_dict):
        complexTypeNode = ElementTree.Element('complexType')
        complexTypeNode.set('name', cls.get_datatype())
        sequenceNode = ElementTree.SubElement(complexTypeNode, 'sequence')
        faultTypeElem = ElementTree.SubElement(sequenceNode, 'element')
        faultTypeElem.set('name', 'detail')
        faultTypeElem.set('type', 'xs:string')
        faultTypeElem = ElementTree.SubElement(sequenceNode, 'element')
        faultTypeElem.set('name', 'message')
        faultTypeElem.set('type', 'xs:string')

        schema_dict[cls.get_datatype()] = complexTypeNode

        typeElementItem = ElementTree.Element('element')
        typeElementItem.set('name', 'ExceptionFaultType')
        typeElementItem.set('type', cls.get_datatype(True))
        schema_dict['%sElement' % (cls.get_datatype(True))] = typeElementItem
Beispiel #21
0
 def from_string(cls, xml, url):
     """ 
         return a new WSDLParser with WSDL parsed from the supplied xml,
         the url is required incase of additional wsdl or schema files
         need to be fetched.
     """
     element = ElementTree.fromstring(xml)
     return WSDLParser(element, url)   
Beispiel #22
0
def create_relates_to_header(relatesTo, attrs={}):
    '''Creates a 'relatesTo' header for async callbacks'''
    relatesToElement = ElementTree.Element(
        '{http://schemas.xmlsoap.org/ws/2003/03/addressing}RelatesTo')
    for k, v in attrs.items():
        relatesToElement.set(k, v)
    relatesToElement.text = relatesTo
    return relatesToElement
Beispiel #23
0
def element2dict(element):
    deprecate('element2dict')
    if type(element) == str:
        element = ElementTree.fromstring(element)

    children = element.getchildren()
    tag = element.tag.split('}')[-1]
    return {tag: _element2dict(children)}
Beispiel #24
0
 def from_string(cls, xml, url):
     """ 
         return a new WSDLParser with WSDL parsed from the supplied xml,
         the url is required incase of additional wsdl or schema files
         need to be fetched.
     """
     element = ElementTree.fromstring(xml)
     return WSDLParser(element, url)
Beispiel #25
0
 def add_to_schema(self,schemaDict):
     complexType = ElementTree.Element('xs:complexType')
     complexType.set('name',self.typ)
     
     sequence = ElementTree.SubElement(complexType,'xs:sequence')
     if self.params:
         for name,serializer in self.params:
             e = ElementTree.SubElement(sequence,'xs:element')
             e.set('name',name)
             e.set('type',serializer.get_datatype(True))
             
     element = ElementTree.Element('xs:element')
     element.set('name',self.typ)
     element.set('type','%s:%s'%('tns',self.typ))
     
     schemaDict[self.typ] = complexType
     schemaDict[self.typ+'Element'] = element
Beispiel #26
0
def make_soap_fault(faultString, faultCode='Server', detail=None):
    '''
    This method populates a soap fault message with the provided fault string and 
    details.  
    @param faultString the short description of the error
    @param detail the details of the exception, such as a stack trace
    @param faultCode defaults to 'Server', but can be overridden
    @returns the element corresponding to the fault message
    '''
    envelope = ElementTree.Element('SOAP-ENV:Envelope')
    envelope.set('xmlns:SOAP-ENV','http://schemas.xmlsoap.org/soap/envelope/')

    body = ElementTree.SubElement(envelope,'SOAP-ENV:Body')
    
    f = Fault(faultCode,faultString,detail)
    body.append(Fault.to_xml(f))

    return envelope
Beispiel #27
0
    def test_soap_envelope(self):
        m = Message('myMessage', [('p', Person)])
        env = make_soap_envelope(m.to_xml(Person()))

        self.assertTrue(env.tag.endswith('Envelope'))
        self.assertTrue(env.getchildren()[0].tag.endswith('Body'))

        m = Message('myMessage', [('p', Person)])
        env = make_soap_envelope(
            m.to_xml(Person()),
            header_elements=[et.Element('header1'),
                             et.Element('header2')])

        env = et.fromstring(et.tostring(env))

        self.assertTrue(env.getchildren()[0].tag.endswith('Header'))
        self.assertEquals(len(env.getchildren()[0].getchildren()), 2)
        self.assertTrue(env.getchildren()[1].tag.endswith('Body'))
Beispiel #28
0
def _unicode_to_xml(value, name, typ):
    retval = ElementTree.Element(name)
    if value == None:
        return Null.to_xml(value, name)
    if type(value) == unicode:
        retval.text = value
    else:
        retval.text = unicode(value, string_encoding)
    retval.set('xsi:type', typ)
    return retval
Beispiel #29
0
def join_attachment(id, envelope, payload, prefix=True):
    '''
    Helper function for swa_to_soap.
    
    Places the data from an attachment back into a SOAP message, replacing
    its xop:Include element or href.
    
    @param  id          content-id or content-location of attachment
    @param  prefix      Set this to true if id is content-id or false if 
                        it is content-location.  It prefixes a "cid:" to
                        the href value.
    @param  envelope    soap envelope string to be operated on
    @param  payload     attachment data
    @return             tuple of length 2 with the new message and the
                        number of replacements made
    '''
    
    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns,):
            message = child
            break
    
    numreplaces = 0
    idprefix = ''
    if prefix == True: idprefix = "cid:"
    id = "%s%s" % (idprefix, id, )
    
    # Make replacement.
    for param in message:
        # Look for Include subelement.
        for sub in param:
            if sub.tag.split('}')[-1] == 'Include' and \
               sub.attrib.get('href') == id:
                param.remove(sub)
                param.text = payload
                numreplaces += 1
        if numreplaces < 1 and param.attrib.get('href') == id:
            del(param.attrib['href'])
            param.text = payload
            numreplaces += 1
            
    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    joinedmsg = soapmsg.getvalue()
    soapmsg.close()
    
    return (joinedmsg, numreplaces)
Beispiel #30
0
 def test_soap_fault(self):
     fault = make_soap_fault('something happened')
     fault = et.fromstring(et.tostring(fault))
     
     self.assertTrue(fault.getchildren()[0].tag.endswith,'Body')
     self.assertTrue(fault.getchildren()[0].getchildren()[0].tag.endswith('Fault'))
     f = fault.getchildren()[0].getchildren()[0]
     
     self.assertEquals(f.find('faultstring').text,'something happened')
     self.assertEquals(f.find('faultcode').text,'Server')
     self.assertEquals(f.find('detail').text,None)
     
     fault = make_soap_fault('something happened','DatabaseError','error on line 12')
     
     fault = et.fromstring(et.tostring(fault))
     
     f = fault.getchildren()[0].getchildren()[0]
     self.assertEquals(f.find('faultstring').text,'something happened')
     self.assertEquals(f.find('faultcode').text,'DatabaseError')
     self.assertEquals(f.find('detail').text,'error on line 12')
Beispiel #31
0
def create_xml_element(name, nslookup, default_ns=None):
    '''
    Factory method to create a new XML element
    @param default_ns The default namespace to use for the element.
    @param extended_map A mapping of any additional namespaces to add.
    '''
    namespace_map = {None: default_ns} if default_ns is not None else {}
    for key, value in nslookup.get_all().iteritems():
        if value != default_ns:
            namespace_map[key] = value
    return ElementTree.Element(name, nsmap=namespace_map)
Beispiel #32
0
    def test_utcdatetime(self):
        datestring = '2007-05-15T13:40:44Z'
        e = ElementTree.Element('test')
        e.text = datestring
        
        dt = DateTime.from_xml(e)    

        self.assertEquals(dt.year,2007)
        self.assertEquals(dt.month,5)
        self.assertEquals(dt.day,15)
        
        datestring = '2007-05-15T13:40:44.003Z'
        e = ElementTree.Element('test')
        e.text = datestring
        
        dt = DateTime.from_xml(e)    

        self.assertEquals(dt.year,2007)
        self.assertEquals(dt.month,5)
        self.assertEquals(dt.day,15)
Beispiel #33
0
def join_attachment(id, envelope, payload, prefix=True):
    '''
    Helper function for swa_to_soap.
    
    Places the data from an attachment back into a SOAP message, replacing
    its xop:Include element or href.
    
    @param  id          content-id or content-location of attachment
    @param  prefix      Set this to true if id is content-id or false if 
                        it is content-location.  It prefixes a "cid:" to
                        the href value.
    @param  envelope    soap envelope string to be operated on
    @param  payload     attachment data
    @return             tuple of length 2 with the new message and the
                        number of replacements made
    '''
    
    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns,):
            message = child
            break
    
    numreplaces = 0
    idprefix = ''
    if prefix == True: idprefix = "cid:"
    id = "%s%s" % (idprefix, id, )
    
    # Make replacement.
    for param in message:
        # Look for Include subelement.
        for sub in param:
            if sub.tag.split('}')[-1] == 'Include' and \
               sub.attrib.get('href') == id:
                param.remove(sub)
                param.text = payload
                numreplaces += 1
        if numreplaces < 1 and param.attrib.get('href') == id:
            del(param.attrib['href'])
            param.text = payload
            numreplaces += 1
            
    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    joinedmsg = soapmsg.getvalue()
    soapmsg.close()
    
    return (joinedmsg, numreplaces)
Beispiel #34
0
 def from_xml(cls, element):
     code = _element_to_string(element.find('faultcode'))
     string = _element_to_string(element.find('faultstring'))
     detail_element = element.find('detail')
     if detail_element is not None:
         if len(detail_element.getchildren()):
             detail = ElementTree.tostring(detail_element)
         else:
             detail = _element_to_string(element.find('detail'))
     else:
         detail = ''
     return Fault(faultcode=code, faultstring=string, detail=detail)
Beispiel #35
0
 def from_xml(cls, element):
     code = _element_to_string(element.find('faultcode'))
     string = _element_to_string(element.find('faultstring'))
     detail_element = element.find('detail')
     if detail_element:
         if len(detail_element.getchildren()):
             detail = ElementTree.tostring(detail_element)
         else:
             detail = _element_to_string(element.find('detail'))
     else:
         detail = ''
     return Fault(faultcode = code, faultstring = string, detail = detail)
Beispiel #36
0
def dict2element(*args, **kwargs):
    deprecate('dict2element')
    if len(kwargs) == 1:
        dictionary = kwargs
    else:
        dictionary = args[0]
    if not len(dictionary.keys()):
        return ElementTree.Element('none')
    root = dictionary.keys()[0]
    element = _dict2element(dictionary[root], root)
    element.set('xmlns:optio', 'http://www.optio.com/schemas')
    return element
Beispiel #37
0
    def add_to_schema(self, schema_dict):
        typ = self.get_datatype()
        self.serializer.add_to_schema(schema_dict)

        if not schema_dict.has_key(typ):

            # items
            itemNode = ElementTree.Element('complexType')
            itemNode.set('name', '%sItem' % typ)

            sequence = ElementTree.SubElement(itemNode, 'sequence')

            key_node = ElementTree.SubElement(sequence, 'element')
            key_node.set('name', 'key')
            key_node.set('minOccurs', '1')
            key_node.set('type', 'xs:string')

            value_node = ElementTree.SubElement(sequence, 'element')
            value_node.set('name', 'value')
            value_node.set('minOccurs', '1')
            value_node.set('type', self.serializer.get_datatype(True))

            complexTypeNode = ElementTree.Element("complexType")
            complexTypeNode.set('name', typ)

            sequenceNode = ElementTree.SubElement(complexTypeNode, 'sequence')
            elementNode = ElementTree.SubElement(sequenceNode, 'element')
            elementNode.set('minOccurs', '0')
            elementNode.set('maxOccurs', 'unbounded')
            elementNode.set('name', '%sItem' % typ)
            elementNode.set('type', 'tns:%sItem' % typ)

            schema_dict[self.get_datatype(True)] = complexTypeNode
            schema_dict['tns:%sItem' % typ] = itemNode

            typeElement = ElementTree.Element("element")
            typeElement.set('name', typ)
            typeElement.set('type', self.get_datatype(True))
            schema_dict['%sElement' % (self.get_datatype(True))] = typeElement

            typeElementItem = ElementTree.Element("element")
            typeElementItem.set('name', '%sItem' % typ)
            typeElementItem.set('type', '%sItem' % self.get_datatype(True))
            schema_dict['%sElementItem' %
                        (self.get_datatype(True))] = typeElementItem
Beispiel #38
0
    def add_to_schema(cls, schemaDict):

        if not schemaDict.has_key(cls.get_datatype(True)):
            for k, v in cls.soap_members.items():
                v.add_to_schema(schemaDict)

            schema_node = ElementTree.Element('xs:complexType')
            schema_node.set('name', cls.__name__)

            sequence_node = ElementTree.SubElement(schema_node, 'xs:sequence')
            for k, v in cls.soap_members.items():
                member_node = ElementTree.SubElement(sequence_node,
                                                     'xs:element')
                member_node.set('name', k)
                member_node.set('minOccurs', '0')
                member_node.set('type', v.get_datatype(True))

            typeElement = ElementTree.Element("xs:element")
            typeElement.set('name', cls.__name__)
            typeElement.set('type', 'tns:' + cls.__name__)
            schemaDict[cls.get_datatype(True) + 'Complex'] = schema_node
            schemaDict[cls.get_datatype(True)] = typeElement
Beispiel #39
0
    def test_soap_fault(self):
        fault = make_soap_fault('something happened')
        fault = et.fromstring(et.tostring(fault))

        self.assertTrue(fault.getchildren()[0].tag.endswith, 'Body')
        self.assertTrue(
            fault.getchildren()[0].getchildren()[0].tag.endswith('Fault'))
        f = fault.getchildren()[0].getchildren()[0]

        self.assertEquals(f.find('faultstring').text, 'something happened')
        self.assertEquals(f.find('faultcode').text, 'Server')
        self.assertEquals(f.find('detail').text, None)

        fault = make_soap_fault('something happened', 'DatabaseError',
                                'error on line 12')

        fault = et.fromstring(et.tostring(fault))

        f = fault.getchildren()[0].getchildren()[0]
        self.assertEquals(f.find('faultstring').text, 'something happened')
        self.assertEquals(f.find('faultcode').text, 'DatabaseError')
        self.assertEquals(f.find('detail').text, 'error on line 12')
Beispiel #40
0
 def to_xml(self, values, name='retval'):
     res = ElementTree.Element(name)
     typ = self.get_datatype(True)
     res.set('xmlns', '')
     if values == None:
         values = []
     res.set('xsi:type', self.get_datatype(True))
     for value in values:
         serializer = self.serializer
         if value == None:
             serializer = Null
         res.append(
             serializer.to_xml(value, name=serializer.get_datatype(False)))
     return res
Beispiel #41
0
    def add_to_schema(self, schema_dict):
        typ = self.get_datatype()

        self.serializer.add_to_schema(schema_dict)

        if not schema_dict.has_key(typ):

            complexTypeNode = ElementTree.Element("xs:complexType")
            complexTypeNode.set('name', self.get_datatype(False))

            sequenceNode = ElementTree.SubElement(complexTypeNode,
                                                  'xs:sequence')
            elementNode = ElementTree.SubElement(sequenceNode, 'xs:element')
            elementNode.set('minOccurs', '0')
            elementNode.set('maxOccurs', 'unbounded')
            elementNode.set('type', self.serializer.get_datatype(True))
            elementNode.set('name', self.serializer.get_datatype(False))

            typeElement = ElementTree.Element("xs:element")
            typeElement.set('name', typ)
            typeElement.set('type', self.get_datatype(True))

            schema_dict['%sElement' % (self.get_datatype(True))] = typeElement
            schema_dict[self.get_datatype(True)] = complexTypeNode
 def importwsdl(self, document):
     """ 
         Processes any wsdl documents imported by document 
         (messages are sometimes held in a seperate document, for example).
         Recusively calls WsdlParser to descend through imports
     """
     reimport = 0
     for imp in document.findall("%simport" % wsdlqname):
         url = str(imp.get("location"))
         # work out if relative or absolute url
         if "://" not in url:
             # relative
             url = path.join(path.dirname(self.url), url)
         f = ulib.urlopen(url)
         d = f.read()
         f.close()
         root = ElementTree.fromstring(d)
         wp = WSDLParser(root, url)
         for cats in ["ctypes", "elements", "messagecat", "portcat", "bindingcat"]:
             getattr(self, cats).update(getattr(wp, cats))
         document.remove(imp)
         for tp in wp.tps:
             self._add_tp(tp)
Beispiel #43
0
    def wsdl(self, url):
        '''
        This method generates and caches the wsdl for this object based
        on the soap methods designated by the soapmethod or soapdocument
        descriptors
        @param url the url that this service can be found at.  This must be 
        passed in by the caller because this object has no notion of the
        server environment in which it runs.
        @returns the string of the wsdl
        '''
        if not self.__wsdl__ == None:
            # return the cached __wsdl__
            return self.__wsdl__
        url = url.replace('.wsdl','')
        # otherwise build it
        serviceName = self.__class__.__name__.split('.')[-1]

        tns = self.__tns__

        root = ElementTree.Element("definitions")

        root.set('targetNamespace',tns)

        root.set('xmlns:tns',tns)
        root.set('xmlns:typens',tns)

        root.set('xmlns','http://schemas.xmlsoap.org/wsdl/')
        root.set('xmlns:soap','http://schemas.xmlsoap.org/wsdl/soap/')
        root.set('xmlns:xs','http://www.w3.org/2001/XMLSchema')
        root.set('xmlns:plnk','http://schemas.xmlsoap.org/ws/2003/05/partner-link/')
        root.set('xmlns:SOAP-ENC',"http://schemas.xmlsoap.org/soap/encoding/")
        root.set('xmlns:wsdl',"http://schemas.xmlsoap.org/wsdl/")
        root.set('name',serviceName)
        
        types = ElementTree.SubElement(root,"types")

        methods = self.methods()
        hasCallbacks = self._hasCallbacks()

        self._add_schema(types,methods)
        self._add_messages_for_methods(root,methods)

        # add necessary async headers
        # WS-Addressing -> RelatesTo ReplyTo MessageID
        # callback porttype
        if hasCallbacks:
            root.set('xmlns:wsa','http://schemas.xmlsoap.org/ws/2003/03/addressing')

            wsaSchemaNode = ElementTree.SubElement(types, "schema")
            wsaSchemaNode.set("targetNamespace", tns+'Callback')
            wsaSchemaNode.set("xmlns", "http://www.w3.org/2001/XMLSchema")

            importNode = ElementTree.SubElement(wsaSchemaNode, "import")
            importNode.set("namespace", "http://schemas.xmlsoap.org/ws/2003/03/addressing")
            importNode.set("schemaLocation", "http://schemas.xmlsoap.org/ws/2003/03/addressing/")

        
            reltMessage = ElementTree.SubElement(root,'message')
            reltMessage.set('name','RelatesToHeader')
            reltPart = ElementTree.SubElement(reltMessage,'part')
            reltPart.set('name','RelatesTo')
            reltPart.set('element','wsa:RelatesTo')

            replyMessage = ElementTree.SubElement(root,'message')
            replyMessage.set('name','ReplyToHeader')
            replyPart = ElementTree.SubElement(replyMessage,'part')
            replyPart.set('name','ReplyTo')
            replyPart.set('element','wsa:ReplyTo')

            idHeader = ElementTree.SubElement(root,'message')
            idHeader.set('name','MessageIDHeader')
            idPart = ElementTree.SubElement(idHeader,'part')
            idPart.set('name','MessageID')
            idPart.set('element','wsa:MessageID')

            # make portTypes
            callbackPortType = ElementTree.SubElement(root,'portType')
            callbackPortType.set('name','%sCallback'%serviceName)
            
            cbServiceName = '%sCallback'%serviceName
            cbService = ElementTree.SubElement(root,'service')
            cbService.set('name',cbServiceName)
            cbWsdlPort = ElementTree.SubElement(cbService,'port')
            cbWsdlPort.set('name',cbServiceName)
            cbWsdlPort.set('binding','tns:%s'%cbServiceName)
            cbAddr = ElementTree.SubElement(cbWsdlPort,'soap:address')
            cbAddr.set('location',url)
            
            
        serviceName = self.__class__.__name__.split('.')[-1] 
        portType = ElementTree.SubElement(root,'portType')
        portType.set('name',serviceName)
        for method in methods:
            if method.isCallback:
                operation = ElementTree.SubElement(callbackPortType,'operation')
            else:
                operation = ElementTree.SubElement(portType,'operation')
                
            operation.set('name',method.name)
            params = []
            for name,param in method.inMessage.params:
                params.append(name)

            documentation = ElementTree.SubElement(operation,'documentation')
            documentation.text = method.doc
            operation.set('parameterOrder',method.inMessage.typ)
            opInput = ElementTree.SubElement(operation,'input')
            opInput.set('name',method.inMessage.typ)
            opInput.set('message','tns:%s'%method.inMessage.typ)

            if method.outMessage.params != None and not method.isCallback and not method.isAsync:
                opOutput = ElementTree.SubElement(operation,'output')
                opOutput.set('name',method.outMessage.typ)
                opOutput.set('message','tns:%s'%method.outMessage.typ)
        
        # make partner link
        plink = ElementTree.SubElement(root,'plnk:partnerLinkType')
        plink.set('name',serviceName)
        role = ElementTree.SubElement(plink,'plnk:role')
        role.set('name', serviceName)
        plinkPortType = ElementTree.SubElement(role,'plnk:portType')
        plinkPortType.set('name','tns:%s'%serviceName) 

        if hasCallbacks:
            role = ElementTree.SubElement(plink,'plnk:role')
            role.set('name', '%sCallback'%serviceName)
            plinkPortType = ElementTree.SubElement(role,'plnk:portType')
            plinkPortType.set('name','tns:%sCallback'%serviceName) 

        self._add_bindings_for_methods(root,serviceName,methods)

        service = ElementTree.SubElement(root,'service')
        service.set('name',serviceName)
        wsdlPort = ElementTree.SubElement(service,'port')
        wsdlPort.set('name',serviceName)
        wsdlPort.set('binding','tns:%s'%serviceName)
        addr = ElementTree.SubElement(wsdlPort,'soap:address')
        addr.set('location',url)

        wsdl = ElementTree.tostring(root)
        wsdl = "<?xml version='1.0' encoding='utf-8' ?>%s"%(wsdl)

        #cache the wsdl for next time
        self.__wsdl__ = wsdl 
        return self.__wsdl__
Beispiel #44
0
    def __call__(self, environ, start_response, address_url=None):
        '''
        This method conforms to the WSGI spec for callable wsgi applications
        (PEP 333). It looks in environ['wsgi.input'] for a fully formed soap
        request envelope, will deserialize the request parameters and call the
        method on the object returned by the getHandler() method.
        @param the http environment
        @param a callable that begins the response message
        @returns the string representation of the soap call
        '''
        methodname = ''
        try:
            reset_request()
            request.environ = environ

            # implementation hook
            self.onCall(environ)

            serviceName = environ['PATH_INFO'].split('/')[-1]
            service = self.getHandler(environ)
            if ((environ['QUERY_STRING'].endswith('wsdl') or
                 environ['PATH_INFO'].endswith('wsdl')) and
                environ['REQUEST_METHOD'].lower() == 'get'):
                # get the wsdl for the service
                #
                # Assume path_info matches pattern
                # /stuff/stuff/stuff/serviceName.wsdl or ?WSDL
                #
                serviceName = serviceName.split('.')[0]
                if address_url:
                    url = address_url
                else:
                    url = reconstruct_url(environ).split('.wsdl')[0]

                start_response('200 OK', [('Content-type', 'text/xml')])
                try:
                    wsdl_content = service.wsdl(url)

                    # implementation hook
                    self.onWsdl(environ, wsdl_content)
                except Exception, e:

                    # implementation hook
                    buffer = cStringIO.StringIO()
                    traceback.print_exc(file=buffer)
                    buffer.seek(0)
                    stacktrace = str(buffer.read())
                    faultStr = ElementTree.tostring(make_soap_fault(str(e),
                        detail=stacktrace), encoding=string_encoding)
                    exceptions(faultStr)
                    self.onWsdlException(environ, e, faultStr)
                    # initiate the response
                    start_response('500 Internal Server Error',
                                   [('Content-type', 'text/xml'),
                                    ('Content-length', str(len(faultStr)))])
                    return [faultStr]

                reset_request()
                return [wsdl_content]

            if environ['REQUEST_METHOD'].lower() != 'post':
                start_response('405 Method Not Allowed', [('Allow', 'POST')])
                return ''

            input = environ.get('wsgi.input')
            length = environ.get("CONTENT_LENGTH")
            body = input.read(int(length))

            methodname = environ.get("HTTP_SOAPACTION")

            debug('\033[92m'+ methodname +'\033[0m')
            debug(body)

            body = collapse_swa(environ.get("CONTENT_TYPE"), body)

            # deserialize the body of the message
            try:
                payload, header = from_soap(body)
            except SyntaxError, e:
                payload = None
                header = None
Beispiel #45
0
            return [resp]

        except Fault, e:
            # grab any headers that were included in the request
            response_headers = None
            if hasattr(request, 'response_headers'):
                response_headers = request.response_headers

            # The user issued a Fault, so handle it just like an exception!
            fault = make_soap_fault(
                e.faultstring,
                e.faultcode,
                e.detail,
                header_elements=response_headers)

            faultStr = ElementTree.tostring(fault, encoding=string_encoding)

            exceptions(faultStr)

            self.onException(environ, e, faultStr)
            reset_request()

            # initiate the response
            start_response('500 Internal Server Error',
                [('Content-type', 'text/xml')])
            return [faultStr]

        except Exception, e:
            # Dump the stack trace to a buffer to be sent
            # back to the caller
Beispiel #46
0
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
#

from soaplib.etimport import ElementTree

ElementTree.set_default_parser(ElementTree.ETCompatXMLParser())

class NamespaceLookup(object):
    '''
    Class to manage XML namespaces
    '''

    def __init__(self, tns = None, wsdl_map = False):
        self.nsmap = {
            'xs': 'http://www.w3.org/2001/XMLSchema',
            'xsi': 'http://www.w3.org/1999/XMLSchema-instance',
            'plnk': 'http://schemas.xmlsoap.org/ws/2003/05/partner-link/',
        }
        if wsdl_map:
            self.nsmap['soap'] = 'http://schemas.xmlsoap.org/wsdl/soap/'
            self.nsmap['wsdl'] = 'http://schemas.xmlsoap.org/wsdl/'
Beispiel #47
0
 def test_override_default_names(self):
     wsdl = ElementTree.fromstring(OverrideNamespaceService().wsdl(''))
     self.assertEquals(wsdl.get('targetNamespace'),
         "http://someservice.com/override")
Beispiel #48
0
 def setUp(self):
     self.service = TestService()
     self._wsdl = self.service.wsdl('')
     self.wsdl = ElementTree.fromstring(self._wsdl)
Beispiel #49
0
 def from_string(cls, xml):
     """ return a new TypeParser with XSD parsed from the supplied xml """
     element = ElementTree.fromstring(xml)
     return TypeParser(element)
Beispiel #50
0
def apply_mtom(headers, envelope, params, paramvals):
    '''
    Apply MTOM to a SOAP envelope, separating attachments into a
    MIME multipart message.
    
    References:
    XOP     http://www.w3.org/TR/xop10/
    MTOM    http://www.w3.org/TR/soap12-mtom/
            http://www.w3.org/Submission/soap11mtom10/
    
    @param headers   Headers dictionary of the SOAP message that would 
                     originally be sent.
    @param envelope  SOAP envelope string that would have originally been sent.
    @param params    params attribute from the Message object used for the SOAP
    @param paramvals values of the params, passed to Message.to_xml
    @return          tuple of length 2 with dictionary of headers and 
                     string of body that can be sent with HTTPConnection
    '''
    
    # grab the XML element of the message in the SOAP body
    soapmsg = StringIO(envelope)
    soaptree = ElementTree.parse(soapmsg)
    soapns = soaptree.getroot().tag.split('}')[0].strip('{')
    soapbody = soaptree.getroot().find("{%s}Body" % soapns)
    message = None
    for child in list(soapbody):
        if child.tag != "%sFault" % (soapns,):
            message = child
            break
    
    # Get additional parameters from original Content-Type
    ctarray = []
    for n, v in headers.items():
        if n.lower() == 'content-type':
            ctarray = v.split(';')
            break
    roottype = ctarray[0].strip()
    rootparams = {}
    for ctparam in ctarray[1:]:
        n, v = ctparam.strip().split('=')
        rootparams[n] = v.strip("\"'")
    
    # Set up initial MIME parts
    mtompkg = MIMEMultipart('related',boundary='?//<><>soaplib_MIME_boundary<>')
    rootpkg = None
    try:
        rootpkg = MIMEApplication(envelope,'xop+xml', encode_7or8bit)
    except NameError:
        rootpkg = MIMENonMultipart("application", "xop+xml")
        rootpkg.set_payload(envelope)
        encode_7or8bit(rootpkg)
    
    # Set up multipart headers.
    del(mtompkg['mime-version'])
    mtompkg.set_param('start-info',roottype)
    mtompkg.set_param('start','<soaplibEnvelope>')
    if headers.has_key('SOAPAction'):
        mtompkg.add_header('SOAPAction', headers.get('SOAPAction'))
    
    # Set up root SOAP part headers
    del(rootpkg['mime-version'])
    rootpkg.add_header('Content-ID','<soaplibEnvelope>')
    for n, v in rootparams.items():
        rootpkg.set_param(n,v)
    rootpkg.set_param('type',roottype)
    
    mtompkg.attach(rootpkg)
    
    # Extract attachments from SOAP envelope.
    for i in range(len(params)):
        name, typ = params[i]
        if typ == Attachment:
            id = "soaplibAttachment_%s" % (len(mtompkg.get_payload()),)
            param = message[i]
            param.text = ""
            incl = ElementTree.SubElement(
                       param, 
                       "{http://www.w3.org/2004/08/xop/include}Include"
                   )
            incl.attrib["href"] = "cid:%s" % id
            if paramvals[i].fileName and not paramvals[i].data:
                paramvals[i].load_from_file()
            data = paramvals[i].data
            attachment = None
            try:
                attachment = MIMEApplication(data, _encoder=encode_7or8bit)
            except NameError:
                attachment = MIMENonMultipart("application", "octet-stream")
                attachment.set_payload(data)
                encode_7or8bit(attachment)
            del(attachment['mime-version'])
            attachment.add_header('Content-ID','<%s>'%(id,))
            mtompkg.attach(attachment)
    
    # Update SOAP envelope.
    soapmsg.close()
    soapmsg = StringIO()
    soaptree.write(soapmsg)
    rootpkg.set_payload(soapmsg.getvalue())
    soapmsg.close()
    
    # extract body string from MIMEMultipart message
    bound = '--%s' % (mtompkg.get_boundary(),)
    marray = mtompkg.as_string().split(bound)
    mtombody = bound
    mtombody += bound.join(marray[1:])
    
    # set Content-Length
    mtompkg.add_header("Content-Length", str(len(mtombody)))
    
    # extract dictionary of headers from MIMEMultipart message
    mtomheaders = {}
    for name, value in mtompkg.items():
        mtomheaders[name] = value
    
    if len(mtompkg.get_payload()) <= 1:
        return (headers, envelope)
    
    return (mtomheaders, mtombody)
Beispiel #51
0
    def __call__(self, *args, **kwargs):
        '''
        This method executes the http request to the remote web service.  With
        the exception of 'headers', 'msgid', and 'mtom'; all keyword arguments
        to this method are put in the http header.  The 'headers' keyword is to
        denote a list of elements to be included in the soap header, 'msgid'
        is a convenience keyword used in async web services which creates a
        WS-Addressing messageid header to be included in the soap headers, and
        'mtom' enables the Message Transmission Optimization Mechanism.

        @param the arguments to the remote method
        @param the keyword arguments
        '''
        if len(args) != len(self.descriptor.inMessage.params):
            argstring = '\r\n'.join(['    ' + str(arg) for arg in args])
            paramstring = '\r\n'.join(['    ' + str(p[0])
                for p in self.descriptor.inMessage.params])
            err_msg = _err_format % (argstring, paramstring)
            raise Exception(err_msg)

        msg = self.descriptor.inMessage.to_xml(*args)

        # grab the soap headers passed into this call
        headers = kwargs.get('headers', [])
        mtom = kwargs.get('mtom', False)
        msgid = kwargs.get('msgid')
        if msgid:
            # special case for the msgid field as a convenience
            # when dealing with async callback methods
            headers.append(create_relates_to_header(msgid))

        tns = self.descriptor.inMessage.ns
        envelope = make_soap_envelope(msg, tns, header_elements=headers)

        body = ElementTree.tostring(envelope)
        methodName = '\"%s\"' % self.descriptor.soapAction
        httpHeaders = {'Content-Length': len(body),
                      'Content-type': 'text/xml; charset="UTF-8"',
                      'Accept': ('application/soap+xml, application/dime, '
                                'multipart/related, text/*'),
                      'User-Agent': 'Soaplib/1.0',
                      'SOAPAction': methodName,
                      }

        for k, v in kwargs.items():
            # add all the other keywords to the http headers
            if k not in ('headers', 'msgid', 'mtom'):
                httpHeaders[k] = v

        if mtom:
            httpHeaders, body = apply_mtom(httpHeaders, body,
                self.descriptor.inMessage.params, args)

        dump(self.host, self.path, httpHeaders, body)

        if self.scheme == "http":
            conn = httplib.HTTPConnection(self.host)
        elif self.scheme == "https":
            conn = httplib.HTTPSConnection(self.host)
        else:
            raise RuntimeError("Unsupported URI connection scheme: %s" %
                self.scheme)

        conn.request("POST", self.path, body=body, headers=httpHeaders)
        response = conn.getresponse()
        data = response.read()

        dump(self.host, self.path, dict(response.getheaders()), data)

        contenttype = response.getheader('Content-Type')
        data = collapse_swa(contenttype, data)

        conn.close()
        if str(response.status) not in['200', '202']:
            # consider everything NOT 200 or 202 as an error response

            if str(response.status) == '500':
                fault = None
                try:
                    payload, headers = from_soap(data)
                    fault = Fault.from_xml(payload)
                except:
                    trace = StringIO()
                    import traceback
                    traceback.print_exc(file=trace)

                    fault = Exception("Unable to read response \n"
                        "%s %s \n %s \n %s" %
                        (response.status, response.reason, trace.getvalue(),
                         data))
                raise fault
            else:
                raise Exception("%s %s" % (response.status, response.reason))

        if not self.descriptor.outMessage.params:
            return

        payload, headers = from_soap(data)
        results = self.descriptor.outMessage.from_xml(payload)
        return results[0]
Beispiel #52
0
def run(url):
    content = urllib2.urlopen(url).read()
    wsdl = et.fromstring(content)
    handle_wsdl(wsdl)
    return make_clients()
Beispiel #53
0
 def to_xml(cls,value,name='retval',nsmap=ns):
     if type(value) == str:
         value = ElementTree.fromstring(value)
     e = create_xml_element(name, nsmap)
     e.append(value) 
     return e 
Beispiel #54
0
    serializer = new.classobj(__type_name, (ClassSerializer, ), {})
    namespace = None

    setattr(serializer, 'soap_members', {})
    setattr(serializer, 'namespace', namespace)
    for k, v in kwargs.items():
        serializer.soap_members[k] = get_serializer(v)
    o = serializer()
    for k, v in kwargs.items():
        setattr(o, k, v)
    return o


if __name__ == '__main__':
    echoInteger = make('echoInteger', i=34)
    print et.tostring(echoInteger.to_xml(echoInteger, 'echoInteger'))

    c = DocumentClient('http://localhost:9753/',
        ['echoInteger', 'echoSimpleClass', 'echoSimpleClassArray'])
    print c.echoInteger(make('echoInteger', i=3)).retval

    print c.echoSimpleClass(make('echoSimpleClass',
        sc=make('SimpleClass', i=34, s='bobo'))).retval.s

    d = c.echoSimpleClassArray(make('echoSimpleClassArray',
        sca=[
            make('SimpleClass', i=34, s='jasdf'),
            make('SimpleClass', i=34, s='bobo'),
            make('SimpleClass', i=34, s='poo'),
        ]))
    print '*' * 80
Beispiel #55
0
    def __call__(self, environ, start_response):
        '''
        This method conforms to the WSGI spec for callable wsgi applications (PEP 333).
        This method looks in environ['wsgi.input'] for a fully formed soap request envelope,
        will deserialize the request parameters and call the method on the object returned
        by the getHandler() method.
        @param the http environment
        @param a callable that begins the response message
        @returns the string representation of the soap call
        '''
        methodname = ''
        try:
            reset_request()
            request.environ = environ
            
            # implementation hook
            self.onCall(environ)
            
            serviceName = environ['PATH_INFO'].split('/')[-1]
            service = self.getHandler(environ)
            if serviceName.lower().endswith('wsdl'):
                # get the wsdl for the service
                #
                # Assume path_info matches pattern
                # /stuff/stuff/stuff/serviceName.wsdl or ?WSDL
                #
                serviceName = serviceName.split('.')[0]
                url = reconstruct_url(environ).split('.wsdl')[0]
                
                start_response('200 OK',[('Content-type','text/xml')])
                try:
                    wsdl_content = service.wsdl(url)
                    
                    # implementation hook
                    self.onWsdl(environ,wsdl_content)
                except Exception, e:
                    
                    # implementation hook
                    buffer = cStringIO.StringIO()
                    traceback.print_exc(file=buffer)
                    buffer.seek(0)
                    stacktrace = str(buffer.read())
                    faultStr = ElementTree.tostring(make_soap_fault( str(e), detail=stacktrace), encoding=string_encoding)
                    
                    exceptions(faultStr)
                    
                    self.onWsdlException(environ,e,faultStr)
                    
                    # initiate the response
                    start_response('500',[('Content-type','text/xml'),('Content-length',str(len(faultStr)))])
                    return [faultStr]
                
                reset_request()
                return [wsdl_content]
            
            if environ['REQUEST_METHOD'].lower() != 'post':
                start_response('405 Method Not Allowed',[('Allow','POST')])
                return ''
                
            input = environ.get('wsgi.input')
            length = environ.get("CONTENT_LENGTH")
            body = input.read(int(length))
            debug(body)
            body = collapse_swa( environ.get("CONTENT_TYPE"), body)
            
            # deserialize the body of the message
            payload, header = from_soap(body)
            if payload:
                methodname = payload.tag.split('}')[-1]
            else:
                # check HTTP_SOAPACTION
                methodname = environ.get("HTTP_SOAPACTION")
                if methodname.startswith('"') and methodname.endswith('"'):
                    methodname = methodname[1:-1]
            request.header = header
            
            # call the method
            func = getattr(service, methodname)
            
            # retrieve the method descriptor
            descriptor = func(_soap_descriptor=True)
            if payload:
                params = descriptor.inMessage.from_xml(*[payload])
            else:
                params = ()
            # implementation hook
            self.onMethodExec(environ,body,params,descriptor.inMessage.params)
            
            # call the method
            retval = func(*params)
            
            # transform the results into an element
            # only expect a single element
            results = None
            if not (descriptor.isAsync or descriptor.isCallback):
                
                results = descriptor.outMessage.to_xml(*[retval])

            # implementation hook
            self.onResults(environ,results,retval)
            
            # grab any headers that were included in the request
            response_headers = None
            if hasattr(request,'response_headers'):
                response_headers = request.response_headers
            
            # construct the soap response, and serialize it
            envelope = make_soap_envelope(results,tns=service.__tns__,header_elements=response_headers) 
            resp = ElementTree.tostring(envelope, encoding=string_encoding)
            headers = {'Content-Type': 'text/xml'}

            if descriptor.mtom:
                headers, resp = apply_mtom( headers, resp,
                                            descriptor.outMessage.params,
                                            (retval,) )

            
            if environ.has_key('CONTENT_LENGTH'):
                del(environ['CONTENT_LENGTH'])
                
            # initiate the response
            start_response('200 OK',headers.items())
            
            self.onReturn(environ,resp)
            
            debug(resp)
            
            # return the serialized results
            reset_request()
            return [resp]
Beispiel #56
0
 def post(self):
     '''
     This method conforms to the WSGI spec for callable wsgi applications (PEP 333).
     This method looks in environ['wsgi.input'] for a fully formed soap request envelope,
     will deserialize the request parameters and call the method on the object returned
     by the getHandler() method.
     @param the http environment
     @param a callable that begins the response message
     @returns the string representation of the soap call
     '''
     methodname = ''
     container = tornado.wsgi.WSGIContainer(self.application)
     environ = container.environ(self.request)
     try:
         # implementation hook
         self.onCall(environ)
         
         serviceName = environ['PATH_INFO'].split('/')[-1]
         service = self.getHandler(environ)
         if (environ['QUERY_STRING'].endswith('wsdl') or environ['PATH_INFO'].endswith('wsdl')) and environ['REQUEST_METHOD'].lower() == 'get':
             # get the wsdl for the service
             #
             # Assume path_info matches pattern
             # /stuff/stuff/stuff/serviceName.wsdl or ?WSDL
             #
             serviceName = serviceName.split('.')[0]
             url = reconstruct_url(environ).split('.wsdl')[0]
             
             try:
                 wsdl_content = service.wsdl(url)
                 
                 # implementation hook
                 self.onWsdl(environ,wsdl_content)
             except Exception, e:
                 
                 # implementation hook
                 buffer = cStringIO.StringIO()
                 traceback.print_exc(file=buffer)
                 buffer.seek(0)
                 stacktrace = str(buffer.read())
                 faultStr = ElementTree.tostring(make_soap_fault( str(e), detail=stacktrace), encoding=string_encoding)
                 
                 exceptions(faultStr)
                 
                 self.onWsdlException(environ,e,faultStr)
                 
                 # initiate the response
                 #return Response(faultStr, '500 Internal Server Error', [('Content-type','text/xml;charset=utf-8')])
                 self.set_header('Content-Type', 'text/xml;charset=utf-8')
                 return self.write(faultStr)
             
             #return Response(wsdl_content, '200 OK', [('Content-type','text/xml;charset=utf-8')])
             self.set_header('Content-Type', 'text/xml;charset=utf-8')
             return self.write(wsdl_content)
         if environ['REQUEST_METHOD'].lower() != 'post':
             #return Response('', '405 Method Not Allowed',[('Allow','POST')])
             self.set_header('Content-Type', 'text/html;charset=utf-8')
             return self.write_error(status_code=405)
             
         input = environ.get('wsgi.input')
         length = environ.get("CONTENT_LENGTH")
         body = input.read(int(length))
         debug(body)
         # body, _unmentioned_attachs = collapse_swa( environ.get("CONTENT_TYPE"), body)
         # collapse_swa has some problem
         try:
             body, _unmentioned_attachs = collapse_swa( environ.get("CONTENT_TYPE"), body)
         except:
             body = collapse_swa( environ.get("CONTENT_TYPE"), body)
             _unmentioned_attachs = []
             pass
         # deserialize the body of the message
         try:
             payload, header = from_soap(body)
         except SyntaxError,e:
             payload = None
             header = None