sudsを使用してアクセスしようとしているsoap1.1/1.2Webサービスがあります。
残念ながら、サービスは認証トークンを応答soapヘッダーに配置します。
どういうわけかヘッダーにアクセスすることは可能ですか?
リクエストにカスタムsoapヘッダーを設定できることは知っていますが、それは私が探しているものではありません。
私は(まだ維持されている)suds-jurkoブランチを使用してきましたが、client.last_received()
フォークされた後、早期に削除されたため、問題が発生しました。そのため、ヘッダーにアクセスする別の方法を考え出す必要がありました。
幸い、メッセージプラグインを使用して解析されたドキュメントを保存し、後でプラグインを介してヘッダーにアクセスできます。利便性を高めるために、xmlドキュメントの生の値を操作する代わりに、service-methodに基づいてヘッダーを処理し、正しく型指定/構造化された値を取得できます。
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>)
あなたは次のようなことをすることができます
print client.last_received().getChild("soap:Envelope").getChild("soap:Header")
.getChild("ResponseHeader").getChild("resultCode").getText()
上記は、soapヘッダーのフィールドresultCodeを読み取ります。フィールドごとにこれを行う必要があります。これは私が知っている限りヘッダーを読むために残された裏口でした。
詳細については、泡付きの石鹸ヘッダーを見てください
Towrのクラスプラグインはうまく機能しますが、SoapheaderResponseに複数の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は、次のようなdictを返します。
SoapHeadersResp = {'MessageHeader':MessageHeaderObj, 'Security':SecurityObj}
このクラスを使用するには、Towrが言ったのと同じ手順に従い、HeaderPluginクラスをこのクラスに置き換えます。