Django - WebService с xml-символами soaplib или амперсандом?
Это мой первый вопрос, поэтому я постараюсь сделать это как можно лучше.
Я пытаюсь реализовать сервер WebService в Python 2.6 и Django 1.4 с Soaplib 2.0.
Веб-сервис работает, и Django нормально его обслуживает на сервере разработки Django.
Вот код для просмотра Django и URL:
views.py
from soaplib.core.service import rpc, DefinitionBase, soap
from soaplib.core.model.primitive import String, Integer, Boolean
from soaplib.core.model.clazz import Array
from soaplib.core import Application
from soaplib.core.server.wsgi import Application as WSGIApplication
from django.http import HttpResponse
class HelloWorldService(DefinitionBase):
@soap(String,Integer,_returns=Array(String))
def say_smello(self,name,times):
results = []
for i in range(0,times):
results.append('Hello, %s'%name)
return results
@soap(String,_returns=Boolean)
def xml(self,xml):
result = xml
return True
@soap(String,_returns=String)
def xml2(self,xml2):
return xml2
class DjangoSoapApp(WSGIApplication):
csrf_exempt = True
def __init__(self, services, tns):
"""Create Django view for given SOAP soaplib services and
tns"""
return super(DjangoSoapApp,
self).__init__(Application(services, tns))
def __call__(self, request):
django_response = HttpResponse()
def start_response(status, headers):
django_response.status_code = int(status.split(' ', 1)[0])
for header, value in headers:
django_response[header] = value
response = super(DjangoSoapApp, self).__call__(request.META,
start_response)
django_response.content = '\n'.join(response)
return django_response
my_soap_service = DjangoSoapApp([HelloWorldService], __name__)
urls.py
url(r'^soap/wsdl$', 'soap.views.my_soap_service'),
url(r'^soap/$', 'soap.views.my_soap_service'),
Дело в том, что я хочу передать методу WebService xml или xml2 XML и сделать что-то с информацией, содержащейся в XML. Я получаю ошибки.
Если я передаю простую строку без символов, таких как "&", все работает нормально, например:
Сначала давайте импортируем suds и установим suds в Debug:
from suds.client import Client
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
А теперь давайте начнем звонить де WS:
WSDL = "http://server.test/soap/wsdl"
client = Client(WSDL)
client.service.xml('x and y')
работает отлично, я получаю "True", и журналы SUDS показывают, что я делаю это:
DEBUG:suds.client:sending to (http://server.test/soap/wsdl)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="soap.views" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:xml>
<ns0:xml>x and y</ns0:xml>
</ns0:xml>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': '"xml"', 'Content-Type': 'text/xml; charset=utf-8'}
DEBUG:suds.client:http succeeded:
<?xml version='1.0' encoding='utf-8'?>
<senv:Envelope xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:plink="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:senc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="soap.views" xmlns:s12env="http://www.w3.org/2003/05/soap-envelope/" xmlns:s12enc="http://www.w3.org/2003/05/soap-encoding/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:senv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"><senv:Body><s0:xmlResponse><s0:xml Result>true</s0:xmlResult></s0:xmlResponse></senv:Body></senv:Envelope>
True
Но если я сделаю:
client.service.xml('x & y')
не работает, он заканчивается тайм-аутом suds и сервер сообщает о разрыве канала, вот что сообщает журнал suds:
DEBUG:suds.client:sending to (http://server.test/soap/wsdl)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="soap.views" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:xml>
<ns0:xml>x & y</ns0:xml>
</ns0:xml>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': '"xml"', 'Content-Type': 'text/xml; charset=utf-8'}
И это ошибка на пенах:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/site-packages/suds/client.py", line 542, in __call__
return client.invoke(args, kwargs)
File "/usr/lib/python2.6/site-packages/suds/client.py", line 602, in invoke
result = self.send(soapenv)
File "/usr/lib/python2.6/site-packages/suds/client.py", line 643, in send
reply = transport.send(request)
File "/usr/lib/python2.6/site-packages/suds/transport/https.py", line 64, in send
return HttpTransport.send(self, request)
File "/usr/lib/python2.6/site-packages/suds/transport/http.py", line 77, in send
fp = self.u2open(u2request)
File "/usr/lib/python2.6/site-packages/suds/transport/http.py", line 118, in u2open
return url.open(u2request, timeout=tm)
File "/usr/lib/python2.6/urllib2.py", line 391, in open
response = self._open(req, data)
File "/usr/lib/python2.6/urllib2.py", line 409, in _open
'_open', req)
File "/usr/lib/python2.6/urllib2.py", line 369, in _call_chain
result = func(*args)
File "/usr/lib/python2.6/urllib2.py", line 1190, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "/usr/lib/python2.6/urllib2.py", line 1165, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error timed out>
Благодаря этой ссылке: http://grokbase.com/p/python/soap/125nhj9bdm/python-suds-xml-encoding-issue я обнаруживаю, что да, если я размещаю WebService что-то вроде:
client.service.xml("x &amp; y")
Я правильно понял:
DEBUG:suds.client:sending to (http://server.test/soap/wsdl)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="soap.views" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:xml>
<ns0:xml>x &amp; y</ns0:xml>
</ns0:xml>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': '"xml"', 'Content-Type': 'text/xml; charset=utf-8'}
True
Если я использую метод xml2, чтобы увидеть, что возвращает WebService это:
client.service.xml2("x &amp; y")
И логи для юзеров:
DEBUG:suds.client:sending to (http://server.test/soap/wsdl)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="soap.views" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:xml2>
<ns0:xml2>x &amp; y</ns0:xml2>
</ns0:xml2>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': '"xml2"', 'Content-Type': 'text/xml; charset=utf-8'}
DEBUG:suds.client:http succeeded:
<?xml version='1.0' encoding='utf-8'?>
<senv:Envelope xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing" xmlns:plink="http://schemas.xmlsoap.org/ws/2003/05/partner-link/" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:senc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s0="soap.views" xmlns:s12env="http://www.w3.org/2003/05/soap-envelope/" xmlns:s12enc="http://www.w3.org/2003/05/soap-encoding/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:senv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"><senv:Body><s0:xml2Response><s0:xml2Result>x & y</s0:xml2Result></s0:xml2Response></senv:Body></senv:Envelope>
x & y
но я не думаю, что проблема в SUDS, потому что я использую эту версию suds для передачи XML на веб-сервисы java, но я не нашел пути к этому soaplib.
Есть идеи? Это сводит меня с ума xD
Моя конечная цель - получить Webservice с Soaplib и передать ему XML из мыльного клиента в Java.
Спасибо
2 ответа
Ок, решил:D
Я мог изменить только сторону сервера, поэтому я перенес свой код в spyne и работает как Charm.
https://github.com/arskom/spyne
Я нашел это в их сети:
Soaplib-2.0 was never released as a stable package, but the branch is still available
Из мыла мы отправились в Rpclib, а оттуда в Spyne.
Верно, что я обнаружил новую ошибку, на этот раз для suds, но suds, которые я только использовал для тестирования, но если я использую другие клиенты, клиенты SoapUI или Java, работает отлично.
После установки с помощью PIP, это код Django:
urls.py
url(r'^testws/\?wsdl$', 'testmo.views.ws_test'),
url(r'^testws/$', 'testmo.views.ws_test'),
views.py
from django.views.decorators.csrf import csrf_exempt
from spyne.server.django import DjangoApplication
from spyne.model.primitive import String
from spyne.service import ServiceBase
from spyne.interface.wsdl import Wsdl11
from spyne.protocol.soap import Soap11
from spyne.application import Application
from spyne.decorator import srpc
class ServiceWsTest(ServiceBase):
@srpc(String, _returns=String)
def testMethod(string):
return string
ws_test = csrf_exempt(DjangoApplication(Application([ServiceWsTest],
'http://example.com',
in_protocol=Soap11(),
out_protocol=Soap11(),
interface=Wsdl11(),
)))
С этого момента я буду продолжать работать с этой библиотекой
Может быть, вы можете обернуть это, без экранирования, в тег cdata. Более подробная информация на http://en.wikipedia.org/wiki/CDATA
<![CDATA[
x & y
]]>