使用suds访问响应soap标头

时间:2012-12-12 16:55:28

标签: python soap suds

我正在尝试使用suds访问的肥皂1.1 / 1.2网络服务。

不幸的是,该服务将身份验证令牌放入响应soap标头中。

是否可以以某种方式访问​​标题?

我知道可以在请求中设置自定义soap标头,但这不是我正在寻找的。

3 个答案:

答案 0 :(得分:4)

我一直在使用(仍然维护的)suds-jurko分支,并因为client.last_received()在分叉后被删除而遇到麻烦。所以我必须想出一种替代方法来访问标题。

幸运的是,您可以使用消息插件来存储已解析的文档,然后通过插件访问标头。为了方便起见,您可以基于service-method处理标头,而不是使用xml文档中的原始值,以获得正确的类型/结构化值。

from suds.plugin import MessagePlugin

class HeaderPlugin(MessagePlugin):
    def __init__(self):
        self.document = None

    def parsed(self, context):
        self.document = context.reply

    def get_headers(self, method):
        method = method.method
        binding = method.binding.output
        rtypes = binding.headpart_types(method, False)

        envns = ('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/')
        soapenv = self.document.getChild('Envelope', envns)
        soapheaders = soapenv.getChild('Header', envns)
        nodes = soapheaders.children
        if len(nodes):
            resolved = rtypes[0].resolve(nobuiltin=True)
            return binding.unmarshaller().process(nodes[0], resolved)
        return None

用法:

from suds.client import Client

hp = HeaderPlugin()
client = Client(wsdl, plugins=[hp])

response = client.service.LoremIpsum()
headers = hp.get_headers(client.service.LoremIpsum)

示例输出:

>>> headers
(AuthenticationResponseHeader){
   sessionKey = "a631cd00-c6be-416f-9bd3-dbcd322e0848"
   validUntil = 2030-01-01 01:01:01.123456+01:00
 }
>>> headers.validUntil
datetime.datetime(2030, 1, 1, 1, 1, 1, 123456, tzinfo=<suds.sax.date.FixedOffsetTimezone object at 0x7f7347856be0>)

答案 1 :(得分:2)

您可以执行类似

的操作
print client.last_received().getChild("soap:Envelope").getChild("soap:Header")
.getChild("ResponseHeader").getChild("resultCode").getText()

以上内容读取soap头中的字段resultCode。您必须为每个字段执行此操作。这是我所知道的后门左侧读取标题。

有关详细信息,请查看soap headers with suds

答案 2 :(得分:0)

Towr的类插件运行良好,但是当你在Soapheader Response中有多个obj时它会有问题。 他的代码只得到第一个对象。

以下是改进Towr课程的代码:

class HeaderPlugin(MessagePlugin):
    def __init__(self):
        self.document = None

    def parsed(self, context):
        self.document = context.reply

    def get_headers(self, method):
        Result = {}
        method = method.method
        binding = method.binding.output
        SHeaderElem = binding.headpart_types(method, False)

        envns = ('SOAP-ENV', 'http://schemas.xmlsoap.org/soap/envelope/')
        soapenv = self.document.getChild('Envelope', envns)
        soapheaders = soapenv.getChild('Header', envns)
        SHeaderNodes = soapheaders.children

        for Elem in SHeaderElem:
            for Node in SHeaderNodes:
                if(Node.name == Elem.name):
                    ElemRes = Elem.resolve(nobuiltin=True)
                    NodeRes = binding.unmarshaller().process(Node, ElemRes)
                    Result[Elem.name] = NodeRes
        return Result
    #

要更好地理解,请参阅示例。 如果你收到这个肥皂反应:

<soap-env:Envelope xmlns:eb="http://www.ebxml.org/namespaces/messageHeader" xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
    <soap-env:Header>
        <eb:MessageHeader eb:version="1.0" soap-env:mustUnderstand="1">
            <!-- -->
        </eb:MessageHeader>
        <wsse:Security>
            <!-- -->
        </wsse:Security>
    </soap-env:Header>
    <soap-env:Body>
        <!-- -->
    </soap-env:Body>
</soap-env:Envelope>

函数get_headers将返回一个这样的字典:

SoapHeadersResp = {'MessageHeader':MessageHeaderObj, 'Security':SecurityObj}

要使用这个类,只需按照Towr所说的步骤,用这个替换他的HeaderPlugin类。