Skip to content

Commit a8c09c0

Browse files
author
Cursor
committed
Add support for sending custom proxy headers during tests
- Add SEND_PROXY_HEADER and SEND_PROXY_VALUE environment variables - Each module test now sends custom headers to the proxy if configured - Updated documentation and output to show send header configuration Usage: SEND_PROXY_HEADER=X-ProxyMesh-Country SEND_PROXY_VALUE=US python test_proxy_headers.py
1 parent 07d0d59 commit a8c09c0

1 file changed

Lines changed: 58 additions & 18 deletions

File tree

test_proxy_headers.py

100644100755
Lines changed: 58 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
Test harness for python-proxy-headers extensions.
44
55
This script tests each module's ability to:
6-
1. Make a request through a proxy
6+
1. Send custom headers to a proxy server
77
2. Receive and capture proxy response headers
88
3. Extract the specified header (default: X-ProxyMesh-IP)
99
1010
Configuration 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
1618
Usage:
1719
python test_proxy_headers.py [module1] [module2] ...
@@ -22,8 +24,11 @@
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
2833
Exit 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

Comments
 (0)