Skip to content

Commit 84f4ded

Browse files
author
Cursor
committed
Simplify pycurl module with low-level helpers
Rewrite pycurl_proxy to provide: 1. Low-level helpers for existing pycurl code: - set_proxy_headers(curl, headers) - sets PROXYHEADER on any Curl instance - HeaderCapture(curl) - captures and parses proxy/origin headers 2. High-level convenience functions (get, post, etc.) for simple use cases This approach is more "pycurl-native" - users can add proxy header support to existing code with just 2 lines instead of rewriting their code.
1 parent c8aaf4c commit 84f4ded

3 files changed

Lines changed: 427 additions & 345 deletions

File tree

docs/pycurl.rst

Lines changed: 102 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -15,90 +15,142 @@ Then you can use the proxy header extension.
1515
Usage
1616
-----
1717

18-
Using the ProxyCurl Class
19-
~~~~~~~~~~~~~~~~~~~~~~~~~
18+
Low-Level Helpers (for existing pycurl code)
19+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2020

21-
The ``ProxyCurl`` class wraps pycurl to provide easy proxy header handling:
21+
If you already have pycurl code, you can add proxy header support with minimal changes:
2222

2323
.. code-block:: python
2424
25-
from python_proxy_headers.pycurl_proxy import ProxyCurl
25+
import pycurl
26+
from python_proxy_headers.pycurl_proxy import set_proxy_headers, HeaderCapture
2627
27-
# Create a ProxyCurl instance with proxy headers
28-
curl = ProxyCurl(proxy_headers={'X-ProxyMesh-Country': 'US'})
28+
c = pycurl.Curl()
29+
c.setopt(pycurl.URL, 'https://httpbin.org/ip')
30+
c.setopt(pycurl.PROXY, 'http://proxy.example.com:8080')
2931
30-
# Make a request through a proxy
31-
response = curl.get(
32-
'https://httpbin.org/ip',
33-
proxy='http://user:pass@proxy.example.com:8080'
34-
)
32+
# Add custom headers to send to the proxy
33+
set_proxy_headers(c, {'X-ProxyMesh-Country': 'US'})
3534
36-
# Access the response
37-
print(response.status_code)
38-
print(response.text)
35+
# Capture response headers (installs HEADERFUNCTION callback)
36+
capture = HeaderCapture(c)
37+
38+
c.perform()
3939
4040
# Access headers from the proxy's CONNECT response
41-
print(response.proxy_headers)
42-
print(response.proxy_status_code)
41+
print(capture.proxy_headers) # {'X-ProxyMesh-IP': '1.2.3.4', ...}
42+
print(capture.proxy_status) # 200
43+
44+
# Access headers from the origin server
45+
print(capture.origin_headers) # {'Content-Type': 'application/json', ...}
4346
44-
Using Convenience Functions
45-
~~~~~~~~~~~~~~~~~~~~~~~~~~~
47+
c.close()
4648
47-
For one-off requests, use the module-level functions:
49+
High-Level Convenience Functions
50+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
51+
52+
For simpler use cases, use the module-level functions:
4853

4954
.. code-block:: python
5055
51-
from python_proxy_headers import pycurl_proxy
56+
from python_proxy_headers.pycurl_proxy import get
5257
53-
response = pycurl_proxy.get(
58+
response = get(
5459
'https://httpbin.org/ip',
5560
proxy='http://proxy.example.com:8080',
56-
proxy_headers={'X-Custom-Header': 'value'}
61+
proxy_headers={'X-ProxyMesh-Country': 'US'}
5762
)
5863
64+
print(response.status_code)
5965
print(response.text)
6066
print(response.proxy_headers)
6167
6268
API Reference
6369
-------------
6470

65-
ProxyCurl Class
66-
~~~~~~~~~~~~~~~
71+
Low-Level Functions
72+
~~~~~~~~~~~~~~~~~~~
6773

68-
.. py:class:: ProxyCurl(proxy_headers=None)
74+
.. py:function:: set_proxy_headers(curl, headers)
6975
70-
PycURL wrapper with proxy header support.
76+
Set custom headers to send to the proxy server during CONNECT.
7177

72-
:param proxy_headers: Dict of headers to send to the proxy server
78+
:param curl: A pycurl.Curl instance
79+
:param headers: Dict of headers to send to the proxy
7380

74-
.. py:method:: request(method, url, proxy=None, proxy_headers=None, headers=None, data=None, timeout=None, verify=True)
81+
.. py:class:: HeaderCapture(curl=None)
7582
76-
Make an HTTP request with proxy header support.
83+
Captures and parses HTTP response headers from pycurl requests.
7784

78-
:param method: HTTP method (GET, POST, etc.)
79-
:param url: Target URL
80-
:param proxy: Proxy URL (e.g., 'http://user:pass@proxy:8080')
81-
:param proxy_headers: Headers to send to the proxy (merged with instance headers)
82-
:param headers: Headers to send to the origin server
83-
:param data: Request body for POST/PUT
84-
:param timeout: Request timeout in seconds
85-
:param verify: Whether to verify SSL certificates
86-
:returns: ProxyResponse object
85+
:param curl: Optional pycurl.Curl instance. If provided, automatically
86+
installs the HEADERFUNCTION callback.
8787

88-
.. py:method:: get(url, **kwargs)
89-
.. py:method:: post(url, **kwargs)
90-
.. py:method:: put(url, **kwargs)
91-
.. py:method:: delete(url, **kwargs)
92-
.. py:method:: head(url, **kwargs)
93-
.. py:method:: options(url, **kwargs)
94-
.. py:method:: patch(url, **kwargs)
88+
.. py:method:: install(curl)
9589
96-
ProxyResponse Class
97-
~~~~~~~~~~~~~~~~~~~
90+
Install the header callback on a pycurl.Curl instance.
91+
92+
:param curl: A pycurl.Curl instance
93+
:returns: self, for chaining
94+
95+
.. py:method:: reset()
96+
97+
Clear captured headers for reuse.
98+
99+
.. py:attribute:: proxy_headers
100+
:type: dict
101+
102+
Headers from the proxy's CONNECT response.
103+
104+
.. py:attribute:: proxy_status
105+
:type: int or None
106+
107+
Status code from the proxy's CONNECT response.
108+
109+
.. py:attribute:: origin_headers
110+
:type: dict
111+
112+
Headers from the origin server's response.
113+
114+
.. py:attribute:: origin_status
115+
:type: int or None
116+
117+
Status code from the origin server's response.
118+
119+
.. py:attribute:: all_headers
120+
:type: dict
121+
122+
All headers merged (proxy headers first, then origin).
123+
124+
High-Level Functions
125+
~~~~~~~~~~~~~~~~~~~~
126+
127+
.. py:function:: request(method, url, proxy=None, proxy_headers=None, headers=None, data=None, timeout=None, verify=True)
128+
129+
Make an HTTP request with proxy header support.
130+
131+
:param method: HTTP method (GET, POST, etc.)
132+
:param url: Target URL
133+
:param proxy: Proxy URL (e.g., 'http://user:pass@proxy:8080')
134+
:param proxy_headers: Headers to send to the proxy
135+
:param headers: Headers to send to the origin server
136+
:param data: Request body for POST/PUT/PATCH
137+
:param timeout: Request timeout in seconds
138+
:param verify: Whether to verify SSL certificates
139+
:returns: Response object
140+
141+
.. py:function:: get(url, **kwargs)
142+
.. py:function:: post(url, **kwargs)
143+
.. py:function:: put(url, **kwargs)
144+
.. py:function:: delete(url, **kwargs)
145+
.. py:function:: head(url, **kwargs)
146+
.. py:function:: patch(url, **kwargs)
147+
148+
Response Class
149+
~~~~~~~~~~~~~~
98150

99-
.. py:class:: ProxyResponse
151+
.. py:class:: Response
100152
101-
Response object containing body and headers from both proxy and origin.
153+
Response object from high-level API.
102154

103155
.. py:attribute:: status_code
104156
:type: int
@@ -120,7 +172,7 @@ ProxyResponse Class
120172

121173
Headers from the proxy's CONNECT response (HTTPS only).
122174

123-
.. py:attribute:: proxy_status_code
175+
.. py:attribute:: proxy_status
124176
:type: int or None
125177

126178
Status code from the proxy's CONNECT response (HTTPS only).

0 commit comments

Comments
 (0)