Skip to content

Commit 5225616

Browse files
author
Mario Benito
committed
Proxy configuration suppor
1 parent aeb05ef commit 5225616

File tree

1 file changed

+105
-18
lines changed

1 file changed

+105
-18
lines changed

src/testlink/testlinkhelper.py

+105-18
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,84 @@
1818
# ------------------------------------------------------------------------
1919

2020
import os
21+
import xmlrpclib, httplib
2122
from argparse import ArgumentParser
2223
from version import VERSION
24+
try:
25+
import gzip
26+
except ImportError:
27+
gzip = None #python can be built without zlib/gzip support
28+
29+
30+
class ProxiedTransport(xmlrpclib.Transport):
31+
def __init__(self):
32+
xmlrpclib.Transport.__init__(self)
33+
self.realhost = None
34+
self.proxy = None
35+
36+
def set_proxy(self, proxy):
37+
"""Define HTTP proxy (with optional basic auth)
38+
39+
:param str proxy: Proxy string
40+
"""
41+
cproxy, auth, x509 = self.get_host_info(proxy)
42+
self.proxy = cproxy
43+
if auth:
44+
auth = [ ('Proxy-Authorization', auth[0][1]) ]
45+
if self._extra_headers:
46+
self._extra_headers.extend(auth)
47+
else:
48+
self._extra_headers = auth
49+
50+
def make_connection(self, host):
51+
"""return an existing connection if possible. This allows HTTP/1.1 keep-alive.
52+
53+
:param str|(str, {}) host: Host descriptor (URL or (URL, x509 info) tuple)
54+
:return httplib.HTTPConnection:
55+
"""
56+
if self._connection and host == self._connection[0]:
57+
return self._connection[1]
58+
59+
# create a HTTP connection object from a host descriptor
60+
chost, auth, x509 = self.get_host_info(host)
61+
if auth:
62+
if self._extra_headers:
63+
self._extra_headers.extend(auth)
64+
else:
65+
self._extra_headers = auth
66+
self.realhost = host
67+
self._connection = host, httplib.HTTPConnection(self.proxy)
68+
return self._connection[1]
69+
70+
def send_request(self, connection, handler, request_body):
71+
"""Send request header
72+
73+
:param httplib.HTTPConnection connection: Connection handle
74+
:param str handler: Target RPC handler
75+
:param str request_body:XML-RPC body
76+
"""
77+
if self.accept_gzip_encoding and gzip:
78+
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler), skip_accept_encoding=True)
79+
connection.putheader("Accept-Encoding", "gzip")
80+
else:
81+
connection.putrequest("POST", 'http://%s%s' % (self.realhost, handler))
82+
83+
def send_host(self, connection, host):
84+
"""Send host name
85+
86+
Note: This function doesn't actually add the "Host"
87+
header anymore, it is done as part of the connection.putrequest() in
88+
send_request() above.
89+
90+
:param httplib.HTTPConnection connection: Connection handle
91+
:param str host: Host name
92+
"""
93+
extra_headers = self._extra_headers
94+
if extra_headers:
95+
if isinstance(extra_headers, dict()):
96+
extra_headers = extra_headers.items()
97+
for key, value in extra_headers:
98+
connection.putheader(key, value)
2399

24100

25101
class TestLinkHelper(object):
@@ -52,24 +128,25 @@ class TestLinkHelper(object):
52128
to http://localhost/testlink/lib/api/xmlrpc/v1/xmlrpc.php
53129
"""
54130

55-
__slots__ = ['_server_url', '_devkey']
131+
__slots__ = ['_server_url', '_devkey', '_proxy']
56132

57-
ENVNAME_SERVER_URL = 'TESTLINK_API_PYTHON_SERVER_URL'
58-
ENVNAME_DEVKEY = 'TESTLINK_API_PYTHON_DEVKEY'
59-
DEFAULT_SERVER_URL = 'http://localhost/testlink/lib/api/xmlrpc.php'
60-
DEFAULT_DEVKEY = '42'
133+
ENVNAME_SERVER_URL = 'TESTLINK_API_PYTHON_SERVER_URL'
134+
ENVNAME_DEVKEY = 'TESTLINK_API_PYTHON_DEVKEY'
135+
DEFAULT_SERVER_URL = 'http://localhost/testlink/lib/api/xmlrpc.php'
136+
DEFAULT_DEVKEY = '42'
61137
DEFAULT_DESCRIPTION = 'Python XML-RPC client for the TestLink API v%s' \
62138
% VERSION
63139

64-
def __init__(self, server_url=None, devkey=None):
140+
def __init__(self, server_url=None, devkey=None, proxy=None):
65141
""" fill slots _server_url and _devkey
66142
Priority:
67143
1. init args
68144
2. environment variables
69145
3. default values
70146
"""
71147
self._server_url = server_url
72-
self._devkey = devkey
148+
self._devkey = devkey
149+
self._proxy = proxy
73150
self._setParamsFromEnv()
74151

75152
def _setParamsFromEnv(self):
@@ -79,12 +156,15 @@ def _setParamsFromEnv(self):
79156
80157
If environment variables are not defined, defaults values are set.
81158
"""
82-
if self._server_url == None:
159+
if not self._server_url:
83160
self._server_url = os.getenv(self.ENVNAME_SERVER_URL,
84161
self.DEFAULT_SERVER_URL)
85-
if self._devkey == None:
162+
if not self._devkey:
86163
self._devkey = os.getenv(self.ENVNAME_DEVKEY, self.DEFAULT_DEVKEY)
87164

165+
if not self._proxy:
166+
self._proxy = os.getenv('http_proxy')
167+
88168
def _createArgparser(self, usage):
89169
""" returns a parser for command line arguments """
90170

@@ -96,22 +176,29 @@ def _createArgparser(self, usage):
96176
# must be set individual for each user
97177
a_parser.add_argument('--devKey', default=self._devkey,
98178
help='Users devKey generated by TestLink (default: %(default)s) ')
179+
a_parser.add_argument('--proxy', default=self._proxy,
180+
help='HTTP Proxy (default: %(default)s) ')
99181
return a_parser
100182

101183
def setParamsFromArgs(self, usage=DEFAULT_DESCRIPTION, args=None):
102184
""" fill slots _server_url and _devkey from command line arguments
103185
_server_url <- --server_url
104186
_devkey <- --devKey
105-
187+
_proxy <- --proxy
188+
106189
uses current values of these slots as default values
107190
"""
108-
a_parser = self._createArgparser(usage)
109-
args = a_parser.parse_args(args)
191+
if not args:
192+
a_parser = self._createArgparser(usage)
193+
args = a_parser.parse_args()
110194
self._server_url = args.server_url
111-
self._devkey = args.devKey
112-
113-
114-
def connect(self, tl_api_class):
195+
self._devkey = args.devKey
196+
self._proxy = args.proxy
197+
198+
def connect(self, tl_api_class, **kwargs):
115199
""" returns a new instance of TL_API_CLASS """
116-
return tl_api_class(self._server_url, self._devkey)
117-
200+
if self._proxy:
201+
p = ProxiedTransport()
202+
p.set_proxy(self._proxy)
203+
kwargs['transport'] = p
204+
return tl_api_class(self._server_url, self._devkey, **kwargs)

0 commit comments

Comments
 (0)