Beispiel #1
0
    def process_reply(self, client, operation, response):
        """Process the XML reply from the server.

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param response: The response object returned by the remote server
        :type response: requests.Response

        """
        if response.status_code != 200 and not response.content:
            raise TransportError(
                u'Server returned HTTP status %d (no content available)'
                % response.status_code)

        content_type = response.headers.get('Content-Type', 'text/xml')
        media_type = get_media_type(content_type)
        message_pack = None

        if media_type == 'multipart/related':
            decoder = MultipartDecoder(
                response.content, content_type, response.encoding or 'utf-8')

            content = decoder.parts[0].content
            if len(decoder.parts) > 1:
                message_pack = MessagePack(parts=decoder.parts[1:])
        else:
            content = response.content

        try:
            doc = parse_xml(
                content, self.transport,
                strict=client.wsdl.strict,
                xml_huge_tree=client.xml_huge_tree)
        except XMLSyntaxError:
            raise TransportError(
                u'Server returned HTTP status %d (%s)'
                % (response.status_code, response.content))

        if client.wsse:
            client.wsse.verify(doc)

        doc, http_headers = plugins.apply_ingress(
            client, doc, response.headers, operation)

        # If the response code is not 200 or if there is a Fault node available
        # then assume that an error occured.
        fault_node = doc.find(
            'soap-env:Body/soap-env:Fault', namespaces=self.nsmap)
        if response.status_code != 200 or fault_node is not None:
            return self.process_error(doc, operation)

        result = operation.process_reply(doc)

        if message_pack:
            message_pack._set_root(result)
            return message_pack
        return result
Beispiel #2
0
def test_html_inside_xml():
    s = b'<env:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><env:Header><ns0:sessionID xmlns:ns0="http://xmlns.org" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">sid</ns0:sessionID></env:Header><env:Body><m:a xmlns:m="http://xmlns.org"><b xmlns="http://xmlns.org"><c><d>Text <a target="_blank" href="https://google.com">https://google.com</a> more text</d><e>Text<br/> more text</e></c></b></m:a></env:Body></env:Envelope>'

    tree = parse_xml(s, DummyTransport(), content_preprocessor=response_preprocessor)

    content = elem2dict(tree)['Body']['a']['b']['c']
    assert (content['d'] == "Text https://google.com more text")
    assert (content['e'] == "Text more text")
Beispiel #3
0
def test_huge_text():
    # libxml2>=2.7.3 has XML_MAX_TEXT_LENGTH 10000000 without XML_PARSE_HUGE
    tree = parse_xml(u"""
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
         <s:Body>
          <HugeText xmlns="http://hugetext">%s</HugeText>
         </s:Body>
        </s:Envelope>
    """ % (u'\u00e5' * 10000001), DummyTransport(), xml_huge_tree=True)

    assert tree[0][0].text == u'\u00e5' * 10000001
Beispiel #4
0
def test_huge_text():
    # libxml2>=2.7.3 has XML_MAX_TEXT_LENGTH 10000000 without XML_PARSE_HUGE
    settings = Settings(xml_huge_tree=True)
    tree = parse_xml(u"""
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
         <s:Body>
          <HugeText xmlns="http://hugetext">%s</HugeText>
         </s:Body>
        </s:Envelope>
    """ % (u'\u00e5' * 10000001), DummyTransport(), settings=settings)

    assert tree[0][0].text == u'\u00e5' * 10000001
def test_allow_entities_and_dtd():
    xml = u"""
        <!DOCTYPE Author [
          <!ENTITY writer "Donald Duck.">
        ]>
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
         <s:Body>
            <Author>&writer;</Author>
         </s:Body>
        </s:Envelope>
    """
    # DTD is allowed by default in defusexml so we follow this behaviour
    with pytest.raises(DTDForbidden):
        parse_xml(xml, DummyTransport(), settings=Settings(forbid_dtd=True))

    with pytest.raises(EntitiesForbidden):
        parse_xml(xml, DummyTransport())

    tree = parse_xml(xml, DummyTransport(), settings=Settings(forbid_entities=False))

    assert tree[0][0].tag == "Author"
Beispiel #6
0
def test_allow_entities_and_dtd():
    xml = u"""
        <!DOCTYPE Author [
          <!ENTITY writer "Donald Duck.">
        ]>
        <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
         <s:Body>
            <Author>&writer;</Author>
         </s:Body>
        </s:Envelope>
    """
    # DTD is allowed by default in defusexml so we follow this behaviour
    with pytest.raises(DTDForbidden):
        parse_xml(xml, DummyTransport(), settings=Settings(forbid_dtd=True))

    with pytest.raises(EntitiesForbidden):
        parse_xml(xml, DummyTransport())

    tree = parse_xml(
        xml, DummyTransport(), settings=Settings(forbid_entities=False))

    assert tree[0][0].tag == 'Author'
Beispiel #7
0
    def process_reply(self, client, operation, response):
        """Process the XML reply from the server.

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param response: The response object returned by the remote server
        :type response: requests.Response

        """
        if response.status_code in (201, 202) and not response.content:
            return None

        elif response.status_code != 200 and not response.content:
            raise TransportError(
                u"Server returned HTTP status %d (no content available)"
                % response.status_code,
                status_code=response.status_code,
            )

        content_type = response.headers.get("Content-Type", "text/xml")
        media_type = get_media_type(content_type)
        message_pack = None

        # If the reply is a multipart/related then we need to retrieve all the
        # parts
        if media_type == "multipart/related":
            decoder = MultipartDecoder(
                response.content, content_type, response.encoding or "utf-8"
            )
            content = decoder.parts[0].content
            if len(decoder.parts) > 1:
                message_pack = MessagePack(parts=decoder.parts[1:])
        else:
            content = response.content

        try:
            doc = parse_xml(content, self.transport, settings=client.settings)
        except XMLSyntaxError as exc:
            raise TransportError(
                "Server returned response (%s) with invalid XML: %s.\nContent: %r"
                % (response.status_code, exc, response.content),
                status_code=response.status_code,
                content=response.content,
            )

        # Check if this is an XOP message which we need to decode first
        if message_pack:
            if process_xop(doc, message_pack):
                message_pack = None

        if client.wsse:
            client.wsse.verify(doc)

        doc, http_headers = plugins.apply_ingress(
            client, doc, response.headers, operation
        )

        # If the response code is not 200 or if there is a Fault node available
        # then assume that an error occured.
        fault_node = doc.find("soap-env:Body/soap-env:Fault", namespaces=self.nsmap)
        if response.status_code != 200 or fault_node is not None:
            return self.process_error(doc, operation)

        result = operation.process_reply(doc)

        if message_pack:
            message_pack._set_root(result)
            return message_pack
        return result
Beispiel #8
0
    def process_reply(self, client, operation, response):
        """Process the XML reply from the server.

        :param client: The client with which the operation was called
        :type client: zeep.client.Client
        :param operation: The operation object from which this is a reply
        :type operation: zeep.wsdl.definitions.Operation
        :param response: The response object returned by the remote server
        :type response: requests.Response

        """
        if response.status_code in (201, 202) and not response.content:
            return None

        elif response.status_code != 200 and not response.content:
            raise TransportError(
                u'Server returned HTTP status %d (no content available)'
                % response.status_code,
                status_code=response.status_code)

        content_type = response.headers.get('Content-Type', 'text/xml')
        media_type = get_media_type(content_type)
        message_pack = None

        # If the reply is a multipart/related then we need to retrieve all the
        # parts
        if media_type == 'multipart/related':
            decoder = MultipartDecoder(
                response.content, content_type, response.encoding or 'utf-8')
            content = decoder.parts[0].content
            if len(decoder.parts) > 1:
                message_pack = MessagePack(parts=decoder.parts[1:])
        else:
            content = response.content

        try:
            doc = parse_xml(content, self.transport, settings=client.settings)
        except XMLSyntaxError as exc:
            raise TransportError(
                'Server returned response (%s) with invalid XML: %s.\nContent: %r'
                % (response.status_code, exc, response.content),
                status_code=response.status_code,
                content=response.content)

        # Check if this is an XOP message which we need to decode first
        if message_pack:
            if process_xop(doc, message_pack):
                message_pack = None

        if client.wsse:
            client.wsse.verify(doc)

        doc, http_headers = plugins.apply_ingress(
            client, doc, response.headers, operation)

        # If the response code is not 200 or if there is a Fault node available
        # then assume that an error occured.
        fault_node = doc.find(
            'soap-env:Body/soap-env:Fault', namespaces=self.nsmap)
        if response.status_code != 200 or fault_node is not None:
            return self.process_error(doc, operation)

        result = operation.process_reply(doc)

        if message_pack:
            message_pack._set_root(result)
            return message_pack
        return result