簡體   English   中英

帶有 Zeep 的 Python SOAP 客戶端 - 導入命名空間

[英]Python SOAP client with Zeep - import namespace

一點背景知識:我開這個問題出現在這里,解決認證問題后。 我更喜歡打開一個新的,以避免與原始問題無關的評論污染前一個,並使其具有適當的可見性。

我正在開發一個 SOAP 客戶端,該客戶端與服務器在同一個 Intranet 中運行,但無法訪問 Internet。

from requests.auth import HTTPBasicAuth
from zeep import Client
from zeep.transports import Transport

wsdl = 'http://mysite.dom/services/MyWebServices?WSDL'
client = Client(wsdl, transport=HTTPBasicAuth('user','pass'), cache=None)

問題:WSDL 包含對位於 Intranet 外部的外部資源的導入('import namespace="schemas.xmlsoap.org/soap/encoding/"'),因此 Zeep 客戶端實例化失敗:

Exception: HTTPConnectionPool(host='schemas.xmlsoap.org', port=80): Max retries exceeded with url: /soap/encoding/ (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x7f3dab9d30b8>: Failed to establish a new connection: [Errno 110] Connection timed out',))

問題:是否可以(並且有意義)在不訪問外部資源的情況下創建 Zeep 客戶端?

作為一個額外的細節,另一個用 Java 編寫的客戶端,基於 XML rpc ServiceFactory 似乎對這種問題更有彈性,即使沒有可用的互聯網連接,服務也會被創建(並工作)。 真的需要從 xmlsoap.org 導入命名空間嗎?

編輯,@mvt 回答后:

所以,我選擇了建議的解決方案,它允許我同時控制對外部資源的訪問(閱讀:禁止訪問與托管端點的服務器不同的服務器)。

class MyTransport(zeep.Transport):
    def load(self, url):
        if not url:
            raise ValueError("No url given to load")
        parsed_url = urlparse(url)
        if parsed_url.scheme in ('http', 'https'):
            if parsed_url.netloc == "myserver.ext":
                response = self.session.get(url, timeout=self.load_timeout)
                response.raise_for_status()
                return response.content
            elif url == "http://schemas.xmlsoap.org/soap/encoding/":
                url = "/some/path/myfile.xsd"
            else:
                raise
        elif parsed_url.scheme == 'file':
            if url.startswith('file://'):
                url = url[7:]
        with open(os.path.expanduser(url), 'rb') as fh:
            return fh.read()

您可以創建自己的 tranport 類的子類,並向 load() 方法添加額外的邏輯,以便從文件系統重定向/加載特定的 url。

我認為代碼很簡單: https : //github.com/mvantellingen/python-zeep/blob/master/src/zeep/transports.py :-)

我建議您自定義覆蓋 URL 並從超類調用 load()。 這樣,如果超類代碼發生更改(它已更改),您就不需要重構您的 CustomTransport 類。

from zeep.transports import Transport

class CustomTransport(Transport):
    def load(self, url):
        # Custom URL overriding to local file storage
        if url and url == "http://schemas.xmlsoap.org/soap/encoding/":
            url = "/path/to/schemas.xmlsoap.org.xsd"

        # Call zeep.transports.Transport's load()
        return super(CustomTransport, self).load(url)

此處描述在 zeep 中使用傳輸的方法,但這里有一個使用 CustomTransport 的快速示例:

from requests import Session
from requests.auth import HTTPBasicAuth
from zeep import Client

session = Session()
client = Client('http://example.com/production.svc?wsdl', transport=CustomTransport(session=session))
client.service.foo()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM