Python + Zeep + History pluginで、SOAPのリクエストとレスポンスを確認してみた

前回、Zeep + SOAP UI + 自作WSDLを使ってSOAPのリクエスト・レスポンスを試してみました。
Python + Zeep + SOAP UI + 自作WSDLで、SOAPのリクエストとレスポンスを試してみた - メモ的な思考的な

実際のリクエスト・レスポンスの内容は、SOAP UI のログで確認していました。

ただ、SOAP UIが使えない環境ではどのように確認すればよいか分からなかったため、メモを残します。

 
目次

 

環境

 

ZeepのHistory Plugin

最新の送受信履歴を確認

Zeepの公式ドキュメントを読んだところ、その用途のプラグインが記載されていました。
https://python-zeep.readthedocs.io/en/master/plugins.html#historyplugin

 
試してみたところ、リクエスト・レスポンスが確認できました。

ただ、そのままではenvelopeが lxml.etree._Element オブジェクトなため、中身まで見れませんでした。

import pathlib
from zeep import Client
from zeep.plugins import HistoryPlugin

WSDL = pathlib.Path.cwd().joinpath('RequestResponse.wsdl')


history_plugin = HistoryPlugin()
client = Client(str(WSDL), plugins=[history_plugin])
response = client.service.requestMessage(userName='taro')

print(history_plugin.last_sent)
# =>
# {'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10929d988>,
#  'http_headers': {
#    'SOAPAction': '"http://example.com/HelloWorld/requestMessage"',
#    'Content-Type': 'text/xml; charset=utf-8'}}

print(type(history_plugin.last_sent['envelope']))
# => <class 'lxml.etree._Element'>

print(history_plugin.last_sent['envelope'])
# => <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x102c54a48>

 

lxml.etreeにより、Envelopeの中身を確認

データ型が history_plugin.last_sent['envelope'] であることから、 lxml.etree を使って解析してみました。

なお、 etree.tounicode()

Deprecated: use tostring(el, encoding='unicode') instead.

https://lxml.de/api/lxml.etree-module.html#tounicode

と書かれていたため、 etree.tostring() を使います。

 
SOAP UIで確認できたものと同一でした。

print(etree.tostring(history_plugin.last_sent['envelope'], pretty_print=True, encoding='unicode'))
# =>
# <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
#   <soap-env:Body>
#     <ns0:RequestInterface xmlns:ns0="http://example.com/HelloWorld">
#       <ns0:userName>taro</ns0:userName>
#     </ns0:RequestInterface>
#   </soap-env:Body>
# </soap-env:Envelope>

 
レスポンスも同様に確認できました。

print(response)
# => Hello, taro

print(history_plugin.last_received)
# =>
# {'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x1092e1ac8>,
#  'http_headers': {
#    'Content-Type': 'text/xml; charset=utf-8',
#    'Content-Encoding': 'gzip',
#    'Content-Length': '198', 'Server': 'Jetty(6.1.26)'}}

print(type(history_plugin.last_received['envelope']))
# => <class 'lxml.etree._Element'>

print(history_plugin.last_received['envelope'])
# => <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x102c98b48>

print(etree.tostring(history_plugin.last_received['envelope'], pretty_print=True, encoding='unicode'))
# => (長いので改行あり)
# <soapenv:Envelope
#       xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
#       xmlns:hel="http://example.com/HelloWorld">
#    <soapenv:Header/>
#    <soapenv:Body>
#       <hel:ResponseInterface>
#
#          <hel:returnMessage>Hello, taro</hel:returnMessage>
#       </hel:ResponseInterface>
#    </soapenv:Body>
# </soapenv:Envelope>

 

複数件の送受信履歴を確認

複数件の送受信履歴を確認したい場合は、

By default at most one transaction (sent/received) is kept. But this can be changed when you create the plugin by passing the maxlen kwarg.

とのことです。

 
ソースコードを見たところ、collections.deque型のインスタンス変数 _buffer に結果が格納されるようでした。
https://github.com/mvantellingen/python-zeep/blob/3.1.0/src/zeep/plugins.py#L49

そのため、以下のようにして表示できました。

import pathlib

from lxml import etree
from zeep import Client
from zeep.plugins import HistoryPlugin

WSDL = pathlib.Path.cwd().joinpath('RequestResponse.wsdl')

# インスタンスを生成する時に、引数maxlenを指定
history_plugin = HistoryPlugin(maxlen=3)
client = Client(str(WSDL), plugins=[history_plugin])

# taro > jiro > saburo の順番にデータを送信
client.service.requestMessage(userName='taro')
client.service.requestMessage(userName='jiro')
client.service.requestMessage(userName='saburo')

print(history_plugin._buffer)
# =>
# deque([
#   {'received': {
#       'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10ae37a08>,
#       'http_headers': {
#           'Content-Type': 'text/xml; charset=utf-8', 'Content-Encoding': 'gzip',
#           'Content-Length': '198', 'Server': 'Jetty(6.1.26)'}},
#    'sent': {
#       'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10adf28c8>,
#       'http_headers': {
#           'SOAPAction': '"http://example.com/HelloWorld/requestMessage"',
#           'Content-Type': 'text/xml; charset=utf-8'}}},
#   {'received': {
#       'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10ae43648>,
#       'http_headers': {
#           'Content-Type': 'text/xml; charset=utf-8', 'Content-Encoding': 'gzip',
#           'Content-Length': '199', 'Server': 'Jetty(6.1.26)'}},
#    'sent': {
#       'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10ae28e88>,
#       'http_headers': {
#           'SOAPAction': '"http://example.com/HelloWorld/requestMessage"',
#           'Content-Type': 'text/xml; charset=utf-8'}}},
#   {'received': {
#       'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10ae43dc8>,
#       'http_headers': {
#           'Content-Type': 'text/xml; charset=utf-8', 'Content-Encoding': 'gzip',
#           'Content-Length': '199', 'Server': 'Jetty(6.1.26)'}},
#    'sent': {
#       'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x10ae43088>,
#       'http_headers': {
#           'SOAPAction': '"http://example.com/HelloWorld/requestMessage"',
#           'Content-Type': 'text/xml; charset=utf-8'}}}],
#   maxlen=3)


# 3件目に saburo を送っていることを確認
buf = history_plugin._buffer[2]
print(type(buf))
# => <class 'dict'>

print(etree.tostring(buf['sent']['envelope'], pretty_print=True, encoding='unicode'))
# =>
# <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
# <soap-env:Body>
# <ns0:RequestInterface xmlns:ns0="http://example.com/HelloWorld">
# <ns0:userName>saburo</ns0:userName>
# </ns0:RequestInterface>
# </soap-env:Body>
# </soap-env:Envelope>

 

ソースコード

GitHubに上げました。 history_plugin ディレクトリが今回のファイルです。
https://github.com/thinkAmi-sandbox/python_zeep-sample