从 Spyne 响应变量中删除名称空间
Remove the namespace from Spyne response variables
根据特定的 WSDL 实现 WebService。客户无法更改。正确处理来自客户端的请求,但由于变量中的名称空间,客户端抱怨响应。
我想要的(基于WSDL的soapUI响应):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cal="http://callback.foo.com/">
<soapenv:Header/>
<soapenv:Body>
<cal:foo_statusResponse>
<result>SUCCESS</result>
<notify>Thanks!</notify>
</cal:foo_statusResponse>
</soapenv:Body>
</soapenv:Envelope>
我得到了什么(注意 tns:
关于导致验证问题的变量):
<senv:Envelope xmlns:tns="http://callback.foo.com/" xmlns:senv="http://schemas.xmlsoap.org/soap/envelope/">
<senv:Body>
<tns:foo_statusResponse>
<tns:result>SUCCESS</tns:result>
<tns:notify>Thanks!</tns:notify>
</tns:foo_statusResponse>
</senv:Body>
</senv:Envelope>
Java 客户端抛出此异常:
[com.sun.istack.SAXParseException2; lineNumber: 2; columnNumber: 162;
unexpected element (uri:"http://callback.foo.com/", local:"result").
Expected elements are <{}result>,<{}notify>]
实施片段:
class fooStatusRS(ComplexModel):
result = Unicode()
notify = Unicode()
class foo_callback(ServiceBase):
@srpc(Unicode, Unicode, Unicode, Unicode, statusbarInfo, anotherResponse,
_out_header=None,
_out_variable_names=("result", "notify"),
_returns=(Unicode, Unicode),
_out_message_name="foo_statusResponse",
_operation_name="foo_status_rq")
def foo_status(foo_id, reply, ref, status, statusbar, another):
if foo_id:
print foo_id
return fooStatusRS(result="SUCCESS", notify="Foo received!")
这是不可能的(目前),维护者在类似的问题 here 中回答了这个问题。
解决方法是为 "method_return_string" 添加 event_manager 的侦听器,然后执行一些字符串操作。
def _method_return_string(ctx):
ctx.out_string[0] = ctx.out_string[0].replace("tns:result>", "result>")
ctx.out_string[0] = ctx.out_string[0].replace("tns:notify>", "notify>")
可以通过覆盖 application.interface
中的 nsmap 来修复
def fix_nsmap(application):
conversion_dict = {
'tns': None,
'senv': 'soap',
}
nsmap = application.interface.nsmap
for k, v in conversion_dict.iteritems():
nsmap[v] = nsmap[k]
del nsmap[k]
application.interface.nsmap = nsmap
application_security2 = Application(
[Security2Service],
tns=NS,
name='Security2',
in_protocol=Soap11(),
out_protocol=Soap11()
)
fix_nsmap(application_security2)
nsmap[None] 设置默认 NS
如果您想知道如何为 method_return_string
添加侦听器到 event_manager,请参阅下面的完整示例:
from spyne import Application, rpc, ServiceBase, Iterable, Integer, Unicode
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
class HelloWorldService(ServiceBase):
@rpc(Unicode, Integer, _returns=Iterable(Unicode))
def say_hello(ctx, name, times):
for i in range(times):
yield u'Hello, %s' % name
def on_method_return_string(ctx):
ctx.out_string[0] = ctx.out_string[0].replace(b'Hello>', b'Good by')
HelloWorldService.event_manager.add_listener('method_return_string',
on_method_return_string)
application = Application([HelloWorldService], '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
server = make_server('127.0.0.1', 8000, wsgi_application)
server.serve_forever()
从 Spyne 2.12 开始,这仍然是从响应变量中删除命名空间的唯一方法。
根据特定的 WSDL 实现 WebService。客户无法更改。正确处理来自客户端的请求,但由于变量中的名称空间,客户端抱怨响应。
我想要的(基于WSDL的soapUI响应):
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cal="http://callback.foo.com/">
<soapenv:Header/>
<soapenv:Body>
<cal:foo_statusResponse>
<result>SUCCESS</result>
<notify>Thanks!</notify>
</cal:foo_statusResponse>
</soapenv:Body>
</soapenv:Envelope>
我得到了什么(注意 tns:
关于导致验证问题的变量):
<senv:Envelope xmlns:tns="http://callback.foo.com/" xmlns:senv="http://schemas.xmlsoap.org/soap/envelope/">
<senv:Body>
<tns:foo_statusResponse>
<tns:result>SUCCESS</tns:result>
<tns:notify>Thanks!</tns:notify>
</tns:foo_statusResponse>
</senv:Body>
</senv:Envelope>
Java 客户端抛出此异常:
[com.sun.istack.SAXParseException2; lineNumber: 2; columnNumber: 162; unexpected element (uri:"http://callback.foo.com/", local:"result"). Expected elements are <{}result>,<{}notify>]
实施片段:
class fooStatusRS(ComplexModel):
result = Unicode()
notify = Unicode()
class foo_callback(ServiceBase):
@srpc(Unicode, Unicode, Unicode, Unicode, statusbarInfo, anotherResponse,
_out_header=None,
_out_variable_names=("result", "notify"),
_returns=(Unicode, Unicode),
_out_message_name="foo_statusResponse",
_operation_name="foo_status_rq")
def foo_status(foo_id, reply, ref, status, statusbar, another):
if foo_id:
print foo_id
return fooStatusRS(result="SUCCESS", notify="Foo received!")
这是不可能的(目前),维护者在类似的问题 here 中回答了这个问题。
解决方法是为 "method_return_string" 添加 event_manager 的侦听器,然后执行一些字符串操作。
def _method_return_string(ctx):
ctx.out_string[0] = ctx.out_string[0].replace("tns:result>", "result>")
ctx.out_string[0] = ctx.out_string[0].replace("tns:notify>", "notify>")
可以通过覆盖 application.interface
中的 nsmap 来修复 def fix_nsmap(application):
conversion_dict = {
'tns': None,
'senv': 'soap',
}
nsmap = application.interface.nsmap
for k, v in conversion_dict.iteritems():
nsmap[v] = nsmap[k]
del nsmap[k]
application.interface.nsmap = nsmap
application_security2 = Application(
[Security2Service],
tns=NS,
name='Security2',
in_protocol=Soap11(),
out_protocol=Soap11()
)
fix_nsmap(application_security2)
nsmap[None] 设置默认 NS
如果您想知道如何为 method_return_string
添加侦听器到 event_manager,请参阅下面的完整示例:
from spyne import Application, rpc, ServiceBase, Iterable, Integer, Unicode
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
class HelloWorldService(ServiceBase):
@rpc(Unicode, Integer, _returns=Iterable(Unicode))
def say_hello(ctx, name, times):
for i in range(times):
yield u'Hello, %s' % name
def on_method_return_string(ctx):
ctx.out_string[0] = ctx.out_string[0].replace(b'Hello>', b'Good by')
HelloWorldService.event_manager.add_listener('method_return_string',
on_method_return_string)
application = Application([HelloWorldService], '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
server = make_server('127.0.0.1', 8000, wsgi_application)
server.serve_forever()
从 Spyne 2.12 开始,这仍然是从响应变量中删除命名空间的唯一方法。