gpt4 book ai didi

python - 如何使用 Suds 从公共(public) Web 服务器连接到专用网络上的 SOAP API?

转载 作者:太空宇宙 更新时间:2023-11-03 18:44:02 25 4
gpt4 key购买 nike

我有一个网站需要连接到位于专用网络防火墙后面的 SOAP API。我尝试了一些方法,并取得了不同程度的成功。

1。 SSH 隧道

我尝试使用以下内容在网站上设置 SSH 隧道(IP 是随机示例)。

export WEB_HOST=203.0.113.10
export LINUX_HOST_WITH_PUBLIC_IP_ON_PRIVATE_NETWORK=203.0.113.11
export SOAP_API_HOST=198.51.100.10

# from $LINUX_HOST_WITH_PUBLIC_IP_ON_PRIVATE_NETWORK I run the following
ssh -f $LINUX_HOST_WITH_PUBLIC_IP_ON_PRIVATE_NETWORK -L 4000:$SOAP_API_HOST:80 -N

# test with curl
$ curl -I http://localhost:4000
HTTP/1.1 200 OK
...

但是,当我尝试将 Suds 与 API 一起使用时,它似乎不起作用。

$ cat temp.py

from suds.client import Client

url = 'http://localhost:4000/scripts/WebObjects.exe/WebServices.woa/ws/Law?wsdl'
client = Client(url)
print(client.service.doThing())

$ python temp.py
Traceback (most recent call last):
File "temp.py", line 6, in <module>
print(client.service.doThing())
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/suds/client.py", line 542, in __call__
return client.invoke(args, kwargs)
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/suds/client.py", line 602, in invoke
result = self.send(soapenv)
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/suds/client.py", line 637, in send
reply = transport.send(request)
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/suds/transport/https.py", line 64, in send
return HttpTransport.send(self, request)
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/suds/transport/http.py", line 77, in send
fp = self.u2open(u2request)
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/suds/transport/http.py", line 118, in u2open
return url.open(u2request, timeout=tm)
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 404, in open
response = self._open(req, data)
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 422, in _open
'_open', req)
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(*args)
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1214, in http_open
return self.do_open(httplib.HTTPConnection, req)
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 1184, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [Errno 61] Connection refused>

2。使用 python contextmanager 包装 API 调用

我还尝试使用基于 Fabric 代码的 python contextmanager 来包装 API 调用。

$ cat temp2.py                                                                                                     
from contextlib import contextmanager
import socket
import paramiko
import logging


@contextmanager
def remote_tunnel(remote_port, local_port=None, local_host="localhost", remote_bind_address="127.0.0.1", transport=None):
if local_port is None:
local_port = remote_port

sockets = []
channels = []
threads = []

def accept(channel, (src_addr, src_port), (dest_addr, dest_port)):
channels.append(channel)
sock = socket.socket()
sockets.append(sock)

try:
sock.connect((local_host, local_port))
except Exception, e:
print "[%s] rtunnel: cannot connect to %s:%d (from local)" % (env.host_string, local_host, local_port)
chan.close()
return

print "[%s] rtunnel: opened reverse tunnel: %r -> %r -> %r"\
% (env.host_string, channel.origin_addr,
channel.getpeername(), (local_host, local_port))

th = ThreadHandler('fwd', _forwarder, channel, sock)
threads.append(th)

transport.request_port_forward(remote_bind_address, remote_port, handler=accept)

try:
yield
finally:
for sock, chan, th in zip(sockets, channels, threads):
sock.close()
chan.close()
th.thread.join()
th.raise_if_needed()
transport.cancel_port_forward(remote_bind_address, remote_port)


def main():

WEB_HOST = '203.0.113.10'
LINUX_HOST_WITH_PUBLIC_IP_ON_PRIVATE_NETWORK = '203.0.113.11'
SOAP_API_HOST = '198.51.100.10'
LOCAL_PORT = 4000
REMOTE_PORT = 80
SSH_USER = 'foouser'

# Connect to SSH host
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy())
ssh_host = (LINUX_HOST_WITH_PUBLIC_IP_ON_PRIVATE_NETWORK, 22, SSH_USER)

logging.debug('Connecting to ssh host {}:{:d} ...'.format(ssh_host[0], ssh_host[1]))
try:
client.connect(ssh_host[0], ssh_host[1], username=ssh_host[2], key_filename=None, look_for_keys=True, password=None)
except Exception as e:
logging.error('Failed to connect to {}:{:d}: {:r}' % (ssh_host[0], ssh_host[1], e))

with remote_tunnel(remote_port=REMOTE_PORT, local_port=LOCAL_PORT, local_host='localhost', remote_bind_address=SOAP_API_HOST, transport=client.get_transport()):
print(requests.get('http://localhost:4000/'))

if __name__ == '__main__':
main()


$ python temp2.py
Traceback (most recent call last):
File "temp2.py", line 80, in <module>
main()
File "temp2.py", line 76, in main
with remote_tunnel(remote_port=REMOTE_PORT, local_port=LOCAL_PORT, local_host='localhost', remote_bind_address=SOAP_API_HOST, transport=client.get_transport()):
File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "temp2.py", line 35, in remote_tunnel
transport.request_port_forward(remote_bind_address, remote_port, handler=accept)
File "/Users/foouser/.virtualenvs/project/lib/python2.7/site-packages/paramiko/transport.py", line 810, in request_port_forward
raise SSHException('TCP forwarding request denied')
paramiko.SSHException: TCP forwarding request denied

更新

基于 @scott-talbert 的 answer ,我能够在设置 SSH 隧道后使用以下方法获得第一种工作方法。

from suds.client import Client
import os

url = 'http://{}/scripts/WebObjects.exe/WebServices.woa/ws/Law?wsdl'.format(os.getenv('SOAP_API_HOST'))
client = Client(url)
client.set_options(proxy={'http': '127.0.0.1:4000'})
print(client.service.doThing())

如果能弄清楚如何让我的第二种方法发挥作用,那就太好了,这样您就不必设置和管理 SSH 隧道了。

最佳答案

我怀疑 #1 失败的原因是 WSDL 包含您的客户端无法直接访问的 URL,这就是您收到“连接被拒绝”消息的原因。看起来 Suds 可以配置告诉它的 urllib2 实例使用代理服务器 - 请参阅 https://fedorahosted.org/suds/wiki/Documentation 。这可能适合你的情况。您可能必须使用 -D 选项在“SOCKS”模式下运行 ssh。

关于python - 如何使用 Suds 从公共(public) Web 服务器连接到专用网络上的 SOAP API?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19942204/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com