44import sys
55import unittest
66import base64
7+ import urllib
78from io import BytesIO
89from urllib .parse import urlencode
910
1617local_resolve = None
1718request_target_prefix = None
1819no_auth = False
20+ proxy_tunnel = False
21+ proxy_masque = False
1922
2023ACCEPT_JSON = 'Accept: application/json'
2124ACCEPT_HTML = 'Accept: text/html'
@@ -32,17 +35,37 @@ def setUp(self):
3235 if target_ca_cert is not None :
3336 self .c .setopt (pycurl .CAINFO , target_ca_cert )
3437 if target_proxy is not None :
35- self .c .setopt (pycurl .PROXY , target_proxy )
36- if proxy_ca_cert is not None :
37- self .c .setopt (pycurl .PROXY_CAINFO , proxy_ca_cert )
38+ if proxy_masque :
39+ proxy_uri = urllib .parse .urlparse (target_proxy )
40+ if proxy_uri .username is not None and proxy_uri .password is not None :
41+ s = f"{ proxy_uri .username } :{ proxy_uri .password } "
42+ auth_header = "Proxy-Authorization: Basic {}" .format (
43+ base64 .standard_b64encode (s .encode ("utf-8" )).decode ('utf-8' ))
44+ self .c .setopt (pycurl .HTTPHEADER , [auth_header ])
45+ else :
46+ self .c .setopt (pycurl .PROXY , target_proxy )
47+ if proxy_ca_cert is not None :
48+ self .c .setopt (pycurl .PROXY_CAINFO , proxy_ca_cert )
49+ if proxy_tunnel :
50+ self .c .setopt (pycurl .HTTPPROXYTUNNEL , 1 )
3851 if local_resolve is not None :
3952 self .c .setopt (pycurl .RESOLVE , [local_resolve ])
4053
4154 def tearDown (self ):
4255 self .c .close ()
4356
4457 def set_url_and_request_target (self , path : str ):
45- self .c .setopt (pycurl .URL , f"{ target_site } { path } " )
58+ target_uri = f"{ target_site } { path } "
59+ if target_proxy is not None and proxy_masque :
60+ proxy_uri = urllib .parse .urlparse (target_proxy )
61+ encoded_target_uri = urllib .parse .quote (target_uri , safe = '' ) # use safe parameter to also escape '/'
62+ if ':' in proxy_uri .hostname :
63+ uri = f"{ proxy_uri .scheme } ://[{ proxy_uri .hostname } ]:{ proxy_uri .port } /.well-known/masque/http/{ encoded_target_uri } "
64+ else :
65+ uri = f"{ proxy_uri .scheme } ://{ proxy_uri .hostname } :{ proxy_uri .port } /.well-known/masque/http/{ encoded_target_uri } "
66+ self .c .setopt (pycurl .URL , uri )
67+ else :
68+ self .c .setopt (pycurl .URL , target_uri )
4669 if request_target_prefix is not None :
4770 self .c .setopt (pycurl .REQUEST_TARGET , f"{ request_target_prefix } { path } " )
4871
@@ -187,6 +210,8 @@ def test_put_file_chunked(self):
187210 parser .add_argument ('--resolve' , nargs = '?' , help = 'Local Resolve Record for curl' )
188211 parser .add_argument ('--request-target-prefix' , nargs = '?' , help = 'Set request target' )
189212 parser .add_argument ('--no-auth' , action = 'store_true' , help = 'No http auth tests' )
213+ parser .add_argument ('--proxy-tunnel' , action = 'store_true' , help = 'Tunnel the traffic through the proxy' )
214+ parser .add_argument ('--proxy-masque' , action = 'store_true' , help = 'Use masque/http well known uri' )
190215
191216 (args , left_args ) = parser .parse_known_args ()
192217
@@ -202,6 +227,8 @@ def test_put_file_chunked(self):
202227 request_target_prefix = args .request_target_prefix
203228 target_site = args .site
204229 no_auth = args .no_auth
230+ proxy_tunnel = args .proxy_tunnel
231+ proxy_masque = args .proxy_masque
205232
206233 left_args .insert (0 , sys .argv [0 ])
207234
0 commit comments