前回、swaRef にて、SOAPでファイルを送信してみました。
Python + Zeep にて、SOAPのswaRef でファイルを送信する - メモ的な思考的な
今回は、wsi:swaRefという仕様でファイルを送信してみます。
- 仕様書
なお、今回扱うwsi:swaRefについてですが、SOAPエンベロープは、
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Body> <ns0:RequestInterface xmlns:ns0="http://example.com/HelloWorld"> <ns0:image>cid:image=spam</ns0:image> </ns0:RequestInterface> </soap-env:Body> </soap-env:Envelope>
のように <ns0:image>cid:image=spam</ns0:image>
と、プレフィックス cid:
を付与する形となります。
また、動作確認は SOAP UI を使っているため、もしかしたらそれ以外の環境では動作しないかもしれません。
目次
環境
実装するもの
です。
Transportについては、SwAの実装を流用できますので、今回は省略します(後述のGitHubにはTransportも実装してあります)。
WSDLの実装
今回は image
elementの型として ref:swaRef
を指定します。
そのため、
- 名前空間
ref
の追加 - image elementの型を
ref:swaRef
と定義
をします。
ただ、名前空間を追加してZeepを実行すると
zeep.exceptions.NamespaceError: Unable to resolve type {http://ws-i.org/profiles/basic/1.1/xsd}swaRef. No schema available for the namespace 'http://ws-i.org/profiles/basic/1.1/xsd'.
というエラーが発生します。
$ curl http://ws-i.org/profiles/basic/1.1/xsd -L The page cannot be displayed because an internal server error has occurred.
とエラーになりました。
これにより、定義が見つからないために、Zeepがエラーを出していることが分かりました。
どこかに定義がないかを探してみると、仕様書の「4.4 Referencing Attachments from the SOAP Envelope」に記載がありました。
As a convenience, WS-I has published the schema for this schema type at: http://ws-i.org/profiles/basic/1.1/swaref.xsd
ただ、URLが微妙に異なっているため、WSDLの内容を差し替えてみました。
ただ、それでも同じエラーが発生しました。
No schema available for the namespace 'http://ws-i.org/profiles/basic/1.1/swaref.xsd'.
何か良い方法がないかを探したところ、スキーマを import する方法がありました。
XML Schemaのインポート
そこで、
$ curl http://ws-i.org/profiles/basic/1.1/swaref.xsd > wsi_swa_ref.xsd % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 4058 100 4058 0 0 11694 0 --:--:-- --:--:-- --:--:-- 11728
とcurlでxmlを wsi_swa_ref.xsd
として取得します。
次に、取得したxsdファイルをimportします。
<wsdl:types> <xsd:schema> <xsd:import namespace="http://ws-i.org/profiles/basic/1.1/xsd" schemaLocation="wsi_swa_ref.xsd" /> </xsd:schema> <xsd:schema elementFormDefault="qualified" targetNamespace="http://example.com/HelloWorld"> ...
これにより、型 ref:swaRef
が使えるようになったため、型を差し替えました。
<xsd:element name="RequestInterface"> <xsd:complexType> <xsd:sequence> <!-- WSI:swaRefのため、swaRef型の引数を用意 --> <xsd:element minOccurs="0" name="image" type="ref:swaRef" /> </xsd:sequence> </xsd:complexType> </xsd:element>
Zeepを実行するスクリプト
こちらも SwA のものを流用・修正します。
wsi:swaRefの場合、
- SOAPエンベロープ部分の image 要素を
<ns0:image>cid:image=ham</ns0:image>
にする - 添付ファイル部分の Content-ID を
Content-ID: <image=ham>
にする
とするため、
def run(attachment_content_id, is_base64ize=False): session = Session() # WSI:swaRefの仕様書に合わせ、添付ファイルのContent-IDにプレフィックス 'image=' を追加 attachment_content_id_with_prefix = f'image={attachment_content_id}' transport = WsiSwaRefTransport(ATTACHMENT, attachment_content_id=attachment_content_id_with_prefix, is_base64ize=is_base64ize, session=session) history_plugin = HistoryPlugin() client = Client(str(WSDL), transport=transport, plugins=[history_plugin]) # WSI:swaRefの仕様書に合わせ、imageタグの値のプレフィックスに 'cid:' を追加 response = client.service.requestMessage(image=f'cid:{attachment_content_id_with_prefix}')
という修正を加えました。
動作確認
SwAと同様、SOAP UIを使って動作を確認します。
SOAP UIをセットアップ後に実行すると、以下の結果となりました。 (量が多いため、バイナリのまま送信したもののみ記載)
$ python wsi_swa_ref_runner.py ---------------------------------------- 添付ファイルはバイナリのまま送信 ---------------------------------------- b'--boundary_62604d9834ed41c7bdfbb5a1ea5f7cf7\r\n Content-Type: text/xml; charset=utf-8\r\n Content-Transfer-Encoding: 8bit\r\n Content-ID: start_6b3ff1a1815c429786706f33495e4f25\r\n\r\n <?xml version=\'1.0\' encoding=\'utf-8\'?>\n <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Body> <ns0:RequestInterface xmlns:ns0="http://example.com/HelloWorld"> <ns0:image>cid:image=ham</ns0:image> </ns0:RequestInterface> </soap-env:Body> </soap-env:Envelope>\r\n --boundary_62604d9834ed41c7bdfbb5a1ea5f7cf7\r\n Content-Transfer-Encoding: binary\r\n Content-Type: image/png; name="shinanogold.png"\r\n Content-ID: <image=ham>\r\n Content-Disposition: attachment; name="shinanogold.png"; filename="shinanogold.png"\r\n\r\n \x89PNG...IEND\xaeB`\x82\r\n --boundary_62604d9834ed41c7bdfbb5a1ea5f7cf7--' --- history --- {'envelope': <Element {http://schemas.xmlsoap.org/soap/envelope/}Envelope at 0x111cefec8>, 'http_headers': { 'SOAPAction': '"http://example.com/HelloWorld/requestMessage"', 'Content-Type': 'multipart/related; boundary="boundary_62604d9834ed41c7bdfbb5a1ea5f7cf7"; type="text/xml"; start="start_6b3ff1a1815c429786706f33495e4f25"; charset=utf-8', 'Content-Length': '6336'}} ? --- envelope --- <soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"> <soap-env:Body> <ns0:RequestInterface xmlns:ns0="http://example.com/HelloWorld"> <ns0:image>cid:image=ham</ns0:image> </ns0:RequestInterface> </soap-env:Body> </soap-env:Envelope>
SOAP UIのログを見ると、2エントリが追加されていました。
内容は以下の通りです。
SOAP UIの説明では、wsi:swaRefだとTypeが SWAREF
になるようですが、今回は MIME
のままでした。
SOAP Attachments and Files | SoapUI
とはいえ、SOAP UI以外の環境がないため、今回はこれで良しとします。
また、ファイルをエクスポートしても、送信したファイル shinanogold.png
を取得できました。
参考
- SOAP Attachments with SWAREF: MockMotor
- Web サービス・プログラミングのヒントと秘訣: WS-I の wsi:swaRef XML タイプを使用したアタッチメント (添付)
ソースコード
GitHubに上げました。 file_attachments/wsi_swa_ref/
ディレクトリの中が今回のファイルです。
https://github.com/thinkAmi-sandbox/python_zeep-sample