【问题标题】:Is there any way to Call python soap spyne server with c++ Gsoap client?有没有办法用 c++ Gsoap 客户端调用 python soap spyne 服务器?
【发布时间】:2019-12-15 21:02:34
【问题描述】:

实际上我有一个使用soap spyne运行的python脚本和soap服务器,我需要使用c ++ gsoap客户端调用该soap api,以便python脚本将运行并获取输出作为对客户端的响应 我可以使用 SOAP UI 和 python zeep 客户端调用 api,但是当我尝试使用 gsoap 调用客户端时,它给了我错误

DEBUG:spyne.protocol.soap.soap11:ValueError: lxml 不支持从带有编码声明的 unicode 字符串反序列化

gsoap 和soap spyne 生成的wsdl 文件也有不同的命名空间

```python
from spyne import Application, rpc, ServiceBase, Integer,     Unicode,String
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
from spyne.model.complex import ComplexModel
from spyne.model.complex import Array
from twisted.internet import reactor
from twisted.web.server import Site
from twisted.web.wsgi import WSGIResource
from twisted.python import log


import sys
sys.path.insert(1,'../cloud-client/slicing')
import speech as t

class caps__CSoapReqBuf(ComplexModel):
    stringarray=String
    size=Integer


class caps__CSoapResponse(ComplexModel):
    __namespace__ = "spyne.examples.hello.soap"
    nRetCode=Integer
    strResponseData=String

class caps__CSoapRequest(ComplexModel):
    __namespace__ = "spyne.examples.hello.soap"
    nRequestType = Integer
    wstrRequestParam= String

class caps_CCallbackData(ComplexModel):
    __namespace__ = "spyne.examples.hello.soap"
    nPort=Integer
    strFunction = String


class TranscriptionService(ServiceBase):
    @rpc(String, String, caps_CCallbackData, caps__CSoapResponse,     _returns=Integer)
    def caps__SoapRequestString(ctx, function_name, SoapRequest,     CallbackData, SoapResponse):
        parameters = SoapRequest
        list = parameters.split('|')
        d = dict(s.split(':') for s in list)
        filename = d['path']
        samplerate = int(d['sr'])
        outputpath = d['outputpath']

       # samplerate=parameters.samplerate       
            if(function_name=='gettranscription'):
            print("gettranscription")
            out=t.main(filename,samplerate)
            SoapResponse.nRetCode=1
            SoapResponse.wstrResponseData=out
            return 0
        elif(function_name=='getocr'):
            return "Do OCR"
        else:
            return "error"

    @rpc(caps__CSoapResponse,_returns=Unicode)   
    def caps_SoapResponseString(ctx,caps__CSoapResponse):
        response = caps__CSoapResponse.wstrResponseData
        return response




application = Application([TranscriptionService],     'spyne.examples.hello.soap',
                          in_protocol=Soap11(validator='lxml'),
                          out_protocol=Soap11())
wsgi_application = WsgiApplication(application)
if __name__ == '__main__':
    import logging
    from wsgiref.simple_server import make_server
    ip = '192.168.0.103'
    port = 8090
    resource = WSGIResource(reactor, reactor, wsgi_application)
    site = Site(resource)
    reactor.listenTCP(port, site,interface=ip)
    logging.basicConfig(level=logging.DEBUG)
    logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
    logging.info("listening to "+ ip +":"+str(port))
    reactor.run()
```

更新 更新代码后,会出现以下错误。

``` Response
'<soap11env:Envelope 
xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/">\n  
<soap11env:Body>\n    <soap11env:Fault>\n      
<faultcode>soap11env:Client.ResourceNotFound</faultcode>\n      
<faultstring>Requested resource 
\'{http://tempuri.org/caps.xsd/Service.wsdl}\' not 
found</faultstring>\n      <faultactor></faultactor>\n    
</soap11env:Fault>\n  </soap11env:Body>\n</soap11env:Envelope>\n'
DEBUG:spyne:gc.collect() took around 40ms.
```

【问题讨论】:

  • 请提及您的代码,以便社区可以为您提供适当的帮助。
  • 我已经用代码更新了问题

标签: python c++ soap gsoap spyne


【解决方案1】:

在这方面,lxml 对它认为可以处理的流类型有点严格。

我相信解决这个冲突的正确做法是从 xml 字符串中去除编码声明。

您可以为“wsgi_call”事件添加一个处理程序来实现这一点。请参阅events example 以了解相关 API 的外观。

【讨论】:

  • 感谢您在做出您建议的更改后的回答,但仍然无法正常工作,请参考有问题的更新
  • 我看到您没有按照我的建议进行更改。请再看一遍。
【解决方案2】:

我对此的解决方案是让 lxml 失败并使用 WebOb 手动解析有效负载,然后将其放置在用户定义的上下文中。您可以稍后访问ctx.udc 来访问数据。所以:

...
from webob import Request as WebObRequest
...

HOST = '0.0.0.0'
PORT = 8000

# parse payload manually 
def _on_wsgi_call(ctx):
    req = WebObRequest(ctx.transport.req)
    decoded = req.body.decode('utf-8')
    envelope = Etree.fromstring(decoded)

    # depending on your data, you may need to update this step 
    element = next(envelope.iter())
    ctx.udc = element.text


if __name__ == '__main__':
    application = initialize([YourService])
    wsgi_application = WsgiApplication(application)
    wsgi_application.event_manager.add_listener('wsgi_call', _on_wsgi_call)
    resource = WSGIResource(reactor, reactor, wsgi_application)
    site = Site(resource)
    reactor.listenTCP(PORT, site, interface=HOST)

    logging.info('listening on: %s:%d' % (HOST, PORT))
    logging.info('wsdl is at: http://%s:%d/?wsdl' % (HOST, PORT))

    sys.exit(reactor.run())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多