Ошибка python suds при разборе ответа SOAP

Я использую скрипт для получения информации из биллинговой системы (без IP-адресов):

from suds.client import Client

from netaddr import *
import logging

logging.basicConfig(filename='provisionSV.log',format='%(asctime)s %(levelname)s  (message)s',level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)

url = 'http://X.X.X.X:X/services/X?wsdl'
client = Client(url)
resultGet = client.service.getCustomerAllowancesRequestType_Search('myself', 100000000000000, 309999900000001)

В логах вижу, что запрос прошел нормально, получаю ответ:

HEADERS: {'Soapaction': b'"urn:getCustomerAllowancesRequestType_Search"', 'Content-Type': 'text/xml; charset=utf-8', 'SOAPAction': b'"urn:getCustomerAllowancesRequestType_Search"', 'Content-type': 'text/xml; charset=utf-8'}
MESSAGE:
b'<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-   ENV="http://schemas.xmlsoap.org/soap/envelope/"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns1="http://tresoap.intecbilling.com/2.0/SEP" xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns2="GX"><SOAP-ENV:Header/> <ns0:Body><ns1:getCustomerAllowancesRequestType_SearchRequest>  <ns2:REQUESTOR>myself</ns2:REQUESTOR><ns2:ON_BEHALF_OF>100000000000000</ns2:ON_BEHALF_OF>  <ns2:EXTERNAL_CUSTOMER_ID>309999900000001</ns2:EXTERNAL_CUSTOMER_ID>  </ns1:getCustomerAllowancesRequestType_SearchRequest></ns0:Body></SOAP-ENV:Envelope>'
2014-12-04 11:26:32,985 DEBUG received:
CODE: 200
HEADERS: Date: Thu, 04 Dec 2014 11:40:00 GMT
Content-Type: multipart/related;    boundary=MIMEBoundaryurn_uuid_CFD62554D8E1A6B4381417693216561; type="text/xml"; start=" <0.urn:uuid:[email protected]>"
Connection: close
Server: Jetty(6.1.26)


MESSAGE:
b'--MIMEBoundaryurn_uuid_CFD62554D8E1A6B4381417693216561\r\nContent-Type: text/xml;  charset=utf-8\r\nContent-Transfer-Encoding: 8bit\r\nContent-ID:  <0.urn:uuid:[email protected]>\r\n\r\n<?xml version=\'1.0\'  encoding=\'utf-8\'?><soapenv:Envelope  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body> <getCustomerAllowancesRequestType_SearchResponse  xmlns="http://tresoap.intecbilling.com/2.0/X" xmlns:tns="GX"><tns:RESULT> <tns:MESSAGE_CODE>0</tns:MESSAGE_CODE><tns:MESSAGE_TEXT>No End User Package for the End- User with External_Customer_Id \'309999900000001\'.</tns:MESSAGE_TEXT></tns:RESULT> </getCustomerAllowancesRequestType_SearchResponse></soapenv:Body></soapenv:Envelope>\r\n-- MIMEBoundaryurn_uuid_CFD62554D8E1A6B4381417693216561--'
2014-12-04 11:26:32,986 DEBUG HTTP succeeded:
b'--MIMEBoundaryurn_uuid_CFD62554D8E1A6B4381417693216561\r\nContent-Type: text/xml;  charset=utf-8\r\nContent-Transfer-Encoding: 8bit\r\nContent-ID:  <0.urn:uuid:[email protected]>\r\n\r\n<?xml version=\'1.0\'  encoding=\'utf-8\'?><soapenv:Envelope  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body> <getCustomerAllowancesRequestType_SearchResponse  xmlns="http://tresoap.intecbilling.com/2.0/SEP" xmlns:tns="GX"><tns:RESULT> <tns:MESSAGE_CODE>0</tns:MESSAGE_CODE><tns:MESSAGE_TEXT>No End User Package for the End- User with External_Customer_Id \'309999900000001\'.</tns:MESSAGE_TEXT></tns:RESULT> </getCustomerAllowancesRequestType_SearchResponse></soapenv:Body></soapenv:Envelope>\r\n-- MIMEBoundaryurn_uuid_CFD62554D8E1A6B4381417693216561--'
2014-12-04 11:26:32,986 ERROR <suds.sax.document.Document object at 0x2b6e3d8ae550>

Но я получаю исключение синтаксического анализа в приложении:

Traceback (most recent call last):
File "/usr/local/lib/python3.4/xml/sax/expatreader.py", line 207, in feed
   self._parser.Parse(data, isFinal)
xml.parsers.expat.ExpatError: syntax error: line 1, column 0

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/root/fciannel/python-project/autheudsessions/venv/lib/python3.4/site-packages/suds/client.py", line 521, in __call__
return client.invoke(args, kwargs)
File "/root/fciannel/python-project/autheudsessions/venv/lib/python3.4/site-packages/suds/client.py", line 581, in invoke
result = self.send(soapenv)
File "/root/fciannel/python-project/autheudsessions/venv/lib/python3.4/site-packages/suds/client.py", line 619, in send
description=tostr(e), original_soapenv=original_soapenv)
File "/root/fciannel/python-project/autheudsessions/venv/lib/python3.4/site-packages/suds/client.py", line 661, in process_reply
replyroot = _parse(reply)
File "/root/fciannel/python-project/autheudsessions/venv/lib/python3.4/site-packages/suds/client.py", line 832, in _parse
return Parser().parse(string=string)
File "/root/fciannel/python-project/autheudsessions/venv/lib/python3.4/site-packages/suds/sax/parser.py", line 133, in parse
sax.parse(source)
File "/usr/local/lib/python3.4/xml/sax/expatreader.py", line 107, in parse
xmlreader.IncrementalParser.parse(self, source)
File "/usr/local/lib/python3.4/xml/sax/xmlreader.py", line 123, in parse
self.feed(buffer)
File "/usr/local/lib/python3.4/xml/sax/expatreader.py", line 211, in feed
self._err_handler.fatalError(exc)
File "/usr/local/lib/python3.4/xml/sax/handler.py", line 38, in fatalError
raise exception xml.sax._exceptions.SAXParseException: 
<unknown>:1:0: syntax error

Что не так с ответом, который я получаю?


person badtrains    schedule 04.12.2014    source источник


Ответы (2)


Ну, тело ответа HTTP не является правильно сформированным XML, потому что оно обернуто структурой MIME/multipart. Насколько я знаю, suds не поддерживает ответы с типом контента «multipart/related». Я думаю, вам придется разобрать ответ самостоятельно, прежде чем передать его парсеру XML.

Я думаю, что лучшим способом решить проблему может быть написание собственного MessagePlugin и реализовать метод received(context) (фактический ответ является частью контекста).

person Felix Schwarz    schedule 04.12.2014

Большое спасибо, это сработало, я написал плагин, который удаляет часть MIME. Это простой пример:

class MyPlugin(MessagePlugin):
    def received(self, context):
        answer = context.reply
        answerDecoded = answer.decode()
        xmlMessage = re.search(r'(<soapenv\:Envelope.*)\r', answerDecoded)
        replyFinal = xmlMessage.group(1)+'\n'
        replyFinalDecoded = replyFinal.encode()
        context.reply = replyFinalDecoded

С этим пока вроде все в порядке.

Большое спасибо за вашу подсказку!

person badtrains    schedule 07.12.2014