PythonSTB commited on
Commit
52c3e47
·
verified ·
1 Parent(s): 732206b

Upload pycurl/PYCURL_USER_GUIDE.txt with huggingface_hub

Browse files
Files changed (1) hide show
  1. pycurl/PYCURL_USER_GUIDE.txt +320 -0
pycurl/PYCURL_USER_GUIDE.txt ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ================================================================================
2
+ PYCURL - USER GUIDE (Android Python STB) - Generated by RIMI
3
+ ================================================================================
4
+ Covers: what pycurl is, install/verify, Curl object, HTTP GET/POST,
5
+ SSL, timeouts, write callbacks, and libcurl-impersonate features.
6
+
7
+ Written for: Python 3.12 (RIMI build) on Android
8
+ Version: pycurl 7.45.6 (libcurl-impersonate)
9
+ Installed: /data/user/0/com.pythonstb.rimi/files/python/lib/python3.12/site-packages/
10
+ ================================================================================
11
+
12
+
13
+ --------------------------------------------------------------------------------
14
+ 1) WHAT IS PYCURL?
15
+ --------------------------------------------------------------------------------
16
+
17
+ pycurl is a Python interface to libcurl, the multiprotocol file transfer library.
18
+ This build uses libcurl-impersonate (a patched libcurl that mimics real browsers).
19
+
20
+ Features:
21
+ - HTTP, HTTPS, FTP, SFTP, SCP, and many other protocols
22
+ - SSL/TLS with BoringSSL backend (via libcurl-impersonate)
23
+ - Compression: zstd, brotli, gzip
24
+ - HTTP/2 via nghttp2
25
+ - Browser impersonation (Chrome, Firefox, Safari headers)
26
+
27
+ import pycurl
28
+ print(pycurl.version)
29
+ # libcurl/7.88.1 OpenSSL/3.1.4 ... brotli/1.0.9 ...
30
+
31
+
32
+ --------------------------------------------------------------------------------
33
+ 2) INSTALL / VERIFY
34
+ --------------------------------------------------------------------------------
35
+
36
+ Install (already done, but if you ever reinstall):
37
+ pip install pycurl
38
+
39
+ Quick smoke test:
40
+ import pycurl
41
+ c = pycurl.Curl()
42
+ c.setopt(c.URL, "http://httpbin.org/get")
43
+ buf = []
44
+ c.setopt(c.WRITEFUNCTION, buf.append)
45
+ c.perform()
46
+ print(c.getinfo(c.RESPONSE_CODE)) # 200
47
+ c.close()
48
+
49
+ Expected output: 200
50
+
51
+
52
+ --------------------------------------------------------------------------------
53
+ 3) CURL OBJECT
54
+ --------------------------------------------------------------------------------
55
+
56
+ import pycurl
57
+
58
+ # Create a Curl handle (reusable for multiple requests)
59
+ c = pycurl.Curl()
60
+
61
+ # Set options
62
+ c.setopt(pycurl.URL, "http://httpbin.org/get")
63
+ c.setopt(pycurl.CONNECTTIMEOUT, 5)
64
+ c.setopt(pycurl.TIMEOUT, 10)
65
+
66
+ # Perform the request
67
+ buf = []
68
+ c.setopt(pycurl.WRITEFUNCTION, buf.append)
69
+ c.perform()
70
+
71
+ # Get info
72
+ print("status:", c.getinfo(pycurl.RESPONSE_CODE))
73
+ print("time:", c.getinfo(pycurl.TOTAL_TIME))
74
+ print("size:", c.getinfo(pycurl.SIZE_DOWNLOAD))
75
+
76
+ # Close when done
77
+ c.close()
78
+
79
+ Note: Curl handles can be reused. Create once, setopt different URLs, perform.
80
+
81
+
82
+ --------------------------------------------------------------------------------
83
+ 4) HTTP GET
84
+ --------------------------------------------------------------------------------
85
+
86
+ import pycurl
87
+ from io import BytesIO
88
+
89
+ c = pycurl.Curl()
90
+ c.setopt(c.URL, "http://httpbin.org/get")
91
+ c.setopt(c.CONNECTTIMEOUT, 5)
92
+ c.setopt(c.TIMEOUT, 10)
93
+
94
+ buf = BytesIO()
95
+ c.setopt(c.WRITEDATA, buf)
96
+ c.perform()
97
+ print(buf.getvalue()) # response body
98
+ print(c.getinfo(c.RESPONSE_CODE)) # 200
99
+ c.close()
100
+
101
+
102
+ --------------------------------------------------------------------------------
103
+ 5) HTTP POST
104
+ --------------------------------------------------------------------------------
105
+
106
+ import pycurl
107
+
108
+ c = pycurl.Curl()
109
+ c.setopt(c.URL, "http://httpbin.org/post")
110
+ c.setopt(c.CONNECTTIMEOUT, 5)
111
+ c.setopt(c.TIMEOUT, 10)
112
+
113
+ # POST with form data
114
+ c.setopt(c.POSTFIELDS, "name=Alice&age=30")
115
+ c.setopt(c.HTTPHEADER, ["Content-Type: application/x-www-form-urlencoded"])
116
+
117
+ buf = []
118
+ c.setopt(c.WRITEFUNCTION, buf.append)
119
+ c.perform()
120
+ print("status:", c.getinfo(c.RESPONSE_CODE))
121
+ print("body:", "".join(buf)[:200])
122
+ c.close()
123
+
124
+ # POST JSON
125
+ import json
126
+ data = json.dumps({"name": "Alice", "age": 30})
127
+ c2 = pycurl.Curl()
128
+ c2.setopt(c2.URL, "http://httpbin.org/post")
129
+ c2.setopt(c2.CONNECTTIMEOUT, 5)
130
+ c2.setopt(c2.TIMEOUT, 10)
131
+ c2.setopt(c2.POST, True)
132
+ c2.setopt(c2.POSTFIELDS, data)
133
+ c2.setopt(c2.HTTPHEADER, ["Content-Type: application/json"])
134
+ buf2 = []
135
+ c2.setopt(c2.WRITEFUNCTION, buf2.append)
136
+ c2.perform()
137
+ print("status:", c2.getinfo(c2.RESPONSE_CODE))
138
+ c2.close()
139
+
140
+
141
+ --------------------------------------------------------------------------------
142
+ 6) HEADERS
143
+ --------------------------------------------------------------------------------
144
+
145
+ import pycurl
146
+
147
+ c = pycurl.Curl()
148
+ c.setopt(c.URL, "http://httpbin.org/get")
149
+ c.setopt(c.CONNECTTIMEOUT, 5)
150
+ c.setopt(c.TIMEOUT, 10)
151
+
152
+ # Custom headers
153
+ c.setopt(c.HTTPHEADER, [
154
+ "User-Agent: MyApp/1.0",
155
+ "Accept: application/json",
156
+ "X-Custom: test"
157
+ ])
158
+
159
+ # Capture response headers
160
+ resp_headers = []
161
+ c.setopt(c.HEADERFUNCTION, lambda h: resp_headers.append(h.strip()))
162
+ buf = []
163
+ c.setopt(c.WRITEFUNCTION, buf.append)
164
+ c.perform()
165
+ print("headers:", resp_headers[:5])
166
+ c.close()
167
+
168
+
169
+ --------------------------------------------------------------------------------
170
+ 7) SSL / HTTPS
171
+ --------------------------------------------------------------------------------
172
+
173
+ import pycurl
174
+
175
+ c = pycurl.Curl()
176
+ c.setopt(c.URL, "https://httpbin.org/get")
177
+ c.setopt(c.CONNECTTIMEOUT, 5)
178
+ c.setopt(c.TIMEOUT, 10)
179
+
180
+ # SSL verification (enabled by default)
181
+ c.setopt(c.SSL_VERIFYPEER, 1)
182
+ c.setopt(c.SSL_VERIFYHOST, 2)
183
+
184
+ buf = []
185
+ c.setopt(c.WRITEFUNCTION, buf.append)
186
+ c.perform()
187
+ print("status:", c.getinfo(c.RESPONSE_CODE))
188
+ ssl_verify = c.getinfo(c.SSL_VERIFYRESULT)
189
+ print("SSL verify:", ssl_verify)
190
+ c.close()
191
+
192
+ # Disable verification (NOT recommended for production)
193
+ c2 = pycurl.Curl()
194
+ c2.setopt(c2.URL, "https://httpbin.org/get")
195
+ c2.setopt(c2.SSL_VERIFYPEER, 0)
196
+ c2.setopt(c2.SSL_VERIFYHOST, 0)
197
+
198
+
199
+ --------------------------------------------------------------------------------
200
+ 8) TIMEOUTS
201
+ --------------------------------------------------------------------------------
202
+
203
+ import pycurl
204
+
205
+ c = pycurl.Curl()
206
+
207
+ # Connection timeout (DNS + TCP connect)
208
+ c.setopt(c.CONNECTTIMEOUT, 5) # 5 seconds
209
+
210
+ # Total request timeout
211
+ c.setopt(c.TIMEOUT, 30) # 30 seconds
212
+
213
+ # DNS cache timeout
214
+ c.setopt(c.DNS_CACHE_TIMEOUT, 300) # 5 minutes
215
+
216
+ # Low speed limit (abort if speed < 1 byte/sec for 10 seconds)
217
+ c.setopt(c.LOW_SPEED_LIMIT, 1)
218
+ c.setopt(c.LOW_SPEED_TIME, 10)
219
+
220
+
221
+ --------------------------------------------------------------------------------
222
+ 9) WRITE CALLBACKS
223
+ --------------------------------------------------------------------------------
224
+
225
+ import pycurl
226
+ from io import BytesIO
227
+
228
+ # Method 1: WRITEFUNCTION callback
229
+ def on_data(data):
230
+ print("got %d bytes" % len(data))
231
+
232
+ c = pycurl.Curl()
233
+ c.setopt(c.URL, "http://httpbin.org/get")
234
+ c.setopt(c.WRITEFUNCTION, on_data)
235
+ c.perform()
236
+ c.close()
237
+
238
+ # Method 2: WRITEDATA file-like object
239
+ buf = BytesIO()
240
+ c = pycurl.Curl()
241
+ c.setopt(c.URL, "http://httpbin.org/get")
242
+ c.setopt(c.WRITEDATA, buf)
243
+ c.perform()
244
+ print(buf.getvalue()[:100])
245
+ c.close()
246
+
247
+
248
+ --------------------------------------------------------------------------------
249
+ 10) LIBCURL-IMPERSONATE FEATURES
250
+ --------------------------------------------------------------------------------
251
+
252
+ This build uses libcurl-impersonate which supports browser impersonation:
253
+
254
+ import pycurl
255
+
256
+ c = pycurl.Curl()
257
+ c.setopt(c.URL, "https://example.com")
258
+
259
+ # Impersonate Chrome 99
260
+ c.setopt(c.HTTPHEADER, [
261
+ "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
262
+ "AppleWebKit/537.36 (KHTML, like Gecko) "
263
+ "Chrome/99.0.4844.51 Safari/537.36"
264
+ ])
265
+
266
+ # The underlying libcurl-impersonate can also set TLS fingerprints
267
+ # to match Chrome/Firefox/Safari behavior.
268
+
269
+ Available impersonation targets (depends on libcurl-impersonate version):
270
+ - Chrome 99, 100, 101, 104, 107, 110, 116, 119, 120
271
+ - Firefox 99, 102, 104, 113, 117, 118, 120
272
+ - Safari 15.3, 15.5, 15.6, 16.0
273
+
274
+
275
+ --------------------------------------------------------------------------------
276
+ 11) ERROR HANDLING
277
+ --------------------------------------------------------------------------------
278
+
279
+ import pycurl
280
+
281
+ # pycurl.error is raised on failures
282
+ try:
283
+ c = pycurl.Curl()
284
+ c.setopt(c.URL, "http://localhost:1")
285
+ c.setopt(c.CONNECTTIMEOUT, 2)
286
+ c.perform()
287
+ except pycurl.error as e:
288
+ code, message = e.args
289
+ print("error code:", code) # e.g. CURLE_COULDNT_CONNECT (7)
290
+ print("message:", message) # e.g. "Failed to connect..."
291
+ finally:
292
+ c.close()
293
+
294
+ Common error codes:
295
+ CURLE_OK (0) - Success
296
+ CURLE_COULDNT_RESOLVE (6) - DNS resolution failed
297
+ CURLE_COULDNT_CONNECT (7) - TCP connect failed
298
+ CURLE_OPERATION_TIMEDOUT (28) - Timeout
299
+ CURLE_SSL_CONNECT (35) - SSL handshake failed
300
+
301
+
302
+ --------------------------------------------------------------------------------
303
+ 12) PITFALLS & NOTES
304
+ --------------------------------------------------------------------------------
305
+
306
+ - Always close Curl handles when done: c.close()
307
+ - Reuse Curl handles for multiple requests (avoids DNS re-resolution)
308
+ - pycurl.Curl() is NOT thread-safe. Use one Curl per thread.
309
+ - WRITEFUNCTION receives bytes, not str
310
+ - Response headers include the trailing \r\n
311
+ - libcurl-impersonate uses BoringSSL, not OpenSSL
312
+ - Built with static deps: BoringSSL, zstd, brotli, nghttp2
313
+ - Wheels are tagged cp312-cp312-android_24
314
+ - Network tests are skippable (may fail on restricted networks)
315
+ - HTTPS requests require valid CA certs in the system store
316
+ - POSTFIELDS is a string or bytes; use POSTFIELDSIZE for binary data
317
+
318
+ ================================================================================
319
+ Generated by RIMI
320
+ ================================================================================