33Test harness for python-proxy-headers extensions.
44
55This script tests each module's ability to:
6- 1. Make a request through a proxy
6+ 1. Send custom headers to a proxy server
772. Receive and capture proxy response headers
883. Extract the specified header (default: X-ProxyMesh-IP)
99
1010Configuration via environment variables:
11- PROXY_URL - Proxy URL (e.g., http://user:pass@proxy.example.com:8080)
12- HTTPS_PROXY - Fallback if PROXY_URL not set
13- TEST_URL - URL to request (default: https://httpbin.org/ip)
14- PROXY_HEADER - Header to check for (default: X-ProxyMesh-IP)
11+ PROXY_URL - Proxy URL (e.g., http://user:pass@proxy.example.com:8080)
12+ HTTPS_PROXY - Fallback if PROXY_URL not set
13+ TEST_URL - URL to request (default: https://httpbin.org/ip)
14+ PROXY_HEADER - Response header to check for (default: X-ProxyMesh-IP)
15+ SEND_PROXY_HEADER - Header name to send to proxy (optional)
16+ SEND_PROXY_VALUE - Header value to send to proxy (optional)
1517
1618Usage:
1719 python test_proxy_headers.py [module1] [module2] ...
2224 # Test specific modules
2325 python test_proxy_headers.py requests httpx
2426
25- # With custom header
27+ # With custom response header to check
2628 PROXY_HEADER=X-Custom-Header python test_proxy_headers.py
29+
30+ # Send a custom header to the proxy
31+ SEND_PROXY_HEADER=X-ProxyMesh-Country SEND_PROXY_VALUE=US python test_proxy_headers.py
2732
2833Exit codes:
2934 0 - All tests passed
@@ -50,6 +55,15 @@ class TestConfig:
5055 proxy_url : str
5156 test_url : str
5257 proxy_header : str
58+ send_proxy_header : Optional [str ] = None
59+ send_proxy_value : Optional [str ] = None
60+
61+ @property
62+ def proxy_headers_to_send (self ) -> Dict [str , str ]:
63+ """Get dict of headers to send to proxy, if configured."""
64+ if self .send_proxy_header and self .send_proxy_value :
65+ return {self .send_proxy_header : self .send_proxy_value }
66+ return {}
5367
5468 @classmethod
5569 def from_env (cls ) -> 'TestConfig' :
@@ -62,11 +76,15 @@ def from_env(cls) -> 'TestConfig':
6276
6377 test_url = os .environ .get ('TEST_URL' , 'https://httpbin.org/ip' )
6478 proxy_header = os .environ .get ('PROXY_HEADER' , 'X-ProxyMesh-IP' )
79+ send_proxy_header = os .environ .get ('SEND_PROXY_HEADER' )
80+ send_proxy_value = os .environ .get ('SEND_PROXY_VALUE' )
6581
6682 return cls (
6783 proxy_url = proxy_url ,
6884 test_url = test_url ,
69- proxy_header = proxy_header
85+ proxy_header = proxy_header ,
86+ send_proxy_header = send_proxy_header ,
87+ send_proxy_value = send_proxy_value
7088 )
7189
7290
@@ -144,8 +162,11 @@ def test(self, config: TestConfig) -> TestResult:
144162 try :
145163 from python_proxy_headers .urllib3_proxy_manager import proxy_from_url
146164
147- # Create proxy manager (ProxyHeaderManager)
148- manager = proxy_from_url (config .proxy_url )
165+ # Create proxy manager (ProxyHeaderManager) with optional proxy headers
166+ manager = proxy_from_url (
167+ config .proxy_url ,
168+ proxy_headers = config .proxy_headers_to_send or None
169+ )
149170
150171 # Make request
151172 # The extension merges proxy CONNECT headers into response.headers
@@ -196,8 +217,8 @@ def test(self, config: TestConfig) -> TestResult:
196217 try :
197218 from python_proxy_headers .requests_adapter import ProxySession
198219
199- # Create session with proxy headers
200- with ProxySession () as session :
220+ # Create session with optional proxy headers to send
221+ with ProxySession (proxy_headers = config . proxy_headers_to_send or None ) as session :
201222 session .proxies = {
202223 'http' : config .proxy_url ,
203224 'https' : config .proxy_url
@@ -251,12 +272,22 @@ def test(self, config: TestConfig) -> TestResult:
251272 try :
252273 import asyncio
253274 from python_proxy_headers .aiohttp_proxy import ProxyClientSession
275+ from multidict import CIMultiDict
254276
255277 async def _test_async ():
256278 # ProxyClientSession automatically includes ProxyTCPConnector
257279 # and merges proxy headers into response.headers
258280 async with ProxyClientSession () as session :
259- async with session .get (config .test_url , proxy = config .proxy_url ) as response :
281+ # Build proxy_headers for aiohttp if configured
282+ proxy_headers = None
283+ if config .proxy_headers_to_send :
284+ proxy_headers = CIMultiDict (config .proxy_headers_to_send )
285+
286+ async with session .get (
287+ config .test_url ,
288+ proxy = config .proxy_url ,
289+ proxy_headers = proxy_headers
290+ ) as response :
260291 # The extension merges proxy headers into response.headers
261292 header_value = self ._check_header (dict (response .headers ), config .proxy_header )
262293 status = response .status
@@ -309,8 +340,15 @@ def test(self, config: TestConfig) -> TestResult:
309340 from python_proxy_headers .httpx_proxy import HTTPProxyTransport
310341 import httpx
311342
312- # Create transport with proxy
313- transport = HTTPProxyTransport (proxy = config .proxy_url )
343+ # Build proxy with optional headers
344+ proxy_headers_to_send = config .proxy_headers_to_send
345+ if proxy_headers_to_send :
346+ proxy = httpx .Proxy (url = config .proxy_url , headers = proxy_headers_to_send )
347+ else :
348+ proxy = config .proxy_url
349+
350+ # Create transport with proxy (including headers if configured)
351+ transport = HTTPProxyTransport (proxy = proxy )
314352
315353 # Create client with custom transport mounted for both http and https
316354 with httpx .Client (mounts = {'http://' : transport , 'https://' : transport }) as client :
@@ -400,10 +438,12 @@ def run_tests(test_names: Optional[List[str]] = None, config: Optional[TestConfi
400438 print (f"\n { '=' * 60 } " )
401439 print ("Python Proxy Headers - Test Harness" )
402440 print (f"{ '=' * 60 } " )
403- print (f"Proxy URL: { _mask_password (config .proxy_url )} " )
404- print (f"Test URL: { config .test_url } " )
405- print (f"Header: { config .proxy_header } " )
406- print (f"Modules: { ', ' .join (test_names )} " )
441+ print (f"Proxy URL: { _mask_password (config .proxy_url )} " )
442+ print (f"Test URL: { config .test_url } " )
443+ print (f"Check Header: { config .proxy_header } " )
444+ if config .send_proxy_header :
445+ print (f"Send Header: { config .send_proxy_header } : { config .send_proxy_value } " )
446+ print (f"Modules: { ', ' .join (test_names )} " )
407447 print (f"{ '=' * 60 } \n " )
408448
409449 for name in test_names :
0 commit comments