impit 0.2.1__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {impit-0.2.1 → impit-0.2.3}/Cargo.lock +55 -57
  2. {impit-0.2.1 → impit-0.2.3}/PKG-INFO +1 -1
  3. impit-0.2.3/impit/src/errors.rs +107 -0
  4. {impit-0.2.1 → impit-0.2.3}/impit/src/http_headers/mod.rs +21 -13
  5. {impit-0.2.1 → impit-0.2.3}/impit/src/impit.rs +40 -40
  6. {impit-0.2.1 → impit-0.2.3}/impit/src/lib.rs +3 -0
  7. {impit-0.2.1 → impit-0.2.3}/impit/src/request.rs +3 -3
  8. impit-0.2.3/impit-python/python/impit/__init__.py +89 -0
  9. {impit-0.2.1 → impit-0.2.3}/impit-python/python/impit/impit.pyi +69 -0
  10. {impit-0.2.1 → impit-0.2.3}/impit-python/src/async_client.rs +27 -18
  11. {impit-0.2.1 → impit-0.2.3}/impit-python/src/client.rs +34 -23
  12. impit-0.2.3/impit-python/src/errors.rs +110 -0
  13. impit-0.2.3/impit-python/src/lib.rs +111 -0
  14. {impit-0.2.1 → impit-0.2.3}/impit-python/src/response.rs +11 -0
  15. {impit-0.2.1 → impit-0.2.3}/impit-python/test/async_test.py +8 -2
  16. {impit-0.2.1 → impit-0.2.3}/impit-python/test/basic_test.py +7 -2
  17. {impit-0.2.1 → impit-0.2.3}/impit-python/uv.lock +178 -178
  18. {impit-0.2.1 → impit-0.2.3}/pyproject.toml +1 -1
  19. impit-0.2.3/python/impit/__init__.py +89 -0
  20. {impit-0.2.1 → impit-0.2.3}/python/impit/impit.pyi +69 -0
  21. impit-0.2.1/impit-python/python/impit/__init__.py +0 -33
  22. impit-0.2.1/impit-python/src/lib.rs +0 -45
  23. impit-0.2.1/python/impit/__init__.py +0 -33
  24. {impit-0.2.1 → impit-0.2.3}/Cargo.toml +0 -0
  25. {impit-0.2.1 → impit-0.2.3}/README.md +0 -0
  26. {impit-0.2.1 → impit-0.2.3}/impit/Cargo.toml +0 -0
  27. {impit-0.2.1 → impit-0.2.3}/impit/README.md +0 -0
  28. {impit-0.2.1 → impit-0.2.3}/impit/docs/index.html +0 -0
  29. {impit-0.2.1 → impit-0.2.3}/impit/examples/basic.rs +0 -0
  30. {impit-0.2.1 → impit-0.2.3}/impit/src/http3.rs +0 -0
  31. {impit-0.2.1 → impit-0.2.3}/impit/src/http_headers/statics.rs +0 -0
  32. {impit-0.2.1 → impit-0.2.3}/impit/src/response_parsing/mod.rs +0 -0
  33. {impit-0.2.1 → impit-0.2.3}/impit/src/tls/ffdhe.rs +0 -0
  34. {impit-0.2.1 → impit-0.2.3}/impit/src/tls/mod.rs +0 -0
  35. {impit-0.2.1 → impit-0.2.3}/impit/src/tls/statics.rs +0 -0
  36. {impit-0.2.1 → impit-0.2.3}/impit-python/Cargo.toml +0 -0
  37. {impit-0.2.1 → impit-0.2.3}/impit-python/README.md +0 -0
  38. {impit-0.2.1 → impit-0.2.3}/impit-python/clippy.toml +0 -0
  39. {impit-0.2.1 → impit-0.2.3}/impit-python/python/impit/py.typed +0 -0
  40. {impit-0.2.1 → impit-0.2.3}/impit-python/src/request.rs +0 -0
  41. {impit-0.2.1 → impit-0.2.3}/impit-python/test/__init__.py +0 -0
  42. {impit-0.2.1 → impit-0.2.3}/impit-python/test/httpbin.py +0 -0
  43. {impit-0.2.1 → impit-0.2.3}/python/impit/py.typed +0 -0
@@ -132,14 +132,15 @@ dependencies = [
132
132
 
133
133
  [[package]]
134
134
  name = "async-executor"
135
- version = "1.13.1"
135
+ version = "1.13.2"
136
136
  source = "registry+https://github.com/rust-lang/crates.io-index"
137
- checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec"
137
+ checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa"
138
138
  dependencies = [
139
139
  "async-task",
140
140
  "concurrent-queue",
141
141
  "fastrand",
142
142
  "futures-lite",
143
+ "pin-project-lite",
143
144
  "slab",
144
145
  ]
145
146
 
@@ -207,17 +208,6 @@ dependencies = [
207
208
  "tracing",
208
209
  ]
209
210
 
210
- [[package]]
211
- name = "async-recursion"
212
- version = "1.1.1"
213
- source = "registry+https://github.com/rust-lang/crates.io-index"
214
- checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
215
- dependencies = [
216
- "proc-macro2",
217
- "quote",
218
- "syn",
219
- ]
220
-
221
211
  [[package]]
222
212
  name = "async-signal"
223
213
  version = "0.2.10"
@@ -294,9 +284,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
294
284
 
295
285
  [[package]]
296
286
  name = "aws-lc-fips-sys"
297
- version = "0.13.5"
287
+ version = "0.13.6"
298
288
  source = "registry+https://github.com/rust-lang/crates.io-index"
299
- checksum = "2d9c2e952a1f57e8cbc78b058a968639e70c4ce8b9c0a5e6363d4e5670eed795"
289
+ checksum = "e99d74bb793a19f542ae870a6edafbc5ecf0bc0ba01d4636b7f7e0aba9ee9bd3"
300
290
  dependencies = [
301
291
  "bindgen",
302
292
  "cc",
@@ -333,9 +323,9 @@ dependencies = [
333
323
 
334
324
  [[package]]
335
325
  name = "backtrace"
336
- version = "0.3.74"
326
+ version = "0.3.75"
337
327
  source = "registry+https://github.com/rust-lang/crates.io-index"
338
- checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
328
+ checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
339
329
  dependencies = [
340
330
  "addr2line",
341
331
  "cfg-if",
@@ -396,9 +386,9 @@ dependencies = [
396
386
 
397
387
  [[package]]
398
388
  name = "brotli"
399
- version = "8.0.0"
389
+ version = "8.0.1"
400
390
  source = "registry+https://github.com/rust-lang/crates.io-index"
401
- checksum = "cf19e729cdbd51af9a397fb9ef8ac8378007b797f8273cfbfdf45dcaa316167b"
391
+ checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d"
402
392
  dependencies = [
403
393
  "alloc-no-stdlib",
404
394
  "alloc-stdlib",
@@ -435,9 +425,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
435
425
 
436
426
  [[package]]
437
427
  name = "cc"
438
- version = "1.2.19"
428
+ version = "1.2.21"
439
429
  source = "registry+https://github.com/rust-lang/crates.io-index"
440
- checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362"
430
+ checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0"
441
431
  dependencies = [
442
432
  "jobserver",
443
433
  "libc",
@@ -1163,9 +1153,9 @@ dependencies = [
1163
1153
 
1164
1154
  [[package]]
1165
1155
  name = "hashbrown"
1166
- version = "0.15.2"
1156
+ version = "0.15.3"
1167
1157
  source = "registry+https://github.com/rust-lang/crates.io-index"
1168
- checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
1158
+ checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3"
1169
1159
 
1170
1160
  [[package]]
1171
1161
  name = "heck"
@@ -1181,9 +1171,9 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
1181
1171
 
1182
1172
  [[package]]
1183
1173
  name = "hickory-client"
1184
- version = "0.25.1"
1174
+ version = "0.25.2"
1185
1175
  source = "registry+https://github.com/rust-lang/crates.io-index"
1186
- checksum = "1bbd1b5def7a1b77783366577e86cb51172196f689823b0f8107da9391ba183f"
1176
+ checksum = "c466cd63a4217d5b2b8e32f23f58312741ce96e3c84bf7438677d2baff0fc555"
1187
1177
  dependencies = [
1188
1178
  "cfg-if",
1189
1179
  "data-encoding",
@@ -1200,14 +1190,12 @@ dependencies = [
1200
1190
 
1201
1191
  [[package]]
1202
1192
  name = "hickory-proto"
1203
- version = "0.25.1"
1193
+ version = "0.25.2"
1204
1194
  source = "registry+https://github.com/rust-lang/crates.io-index"
1205
- checksum = "6d844af74f7b799e41c78221be863bade11c430d46042c3b49ca8ae0c6d27287"
1195
+ checksum = "f8a6fe56c0038198998a6f217ca4e7ef3a5e51f46163bd6dd60b5c71ca6c6502"
1206
1196
  dependencies = [
1207
- "async-recursion",
1208
1197
  "async-trait",
1209
1198
  "cfg-if",
1210
- "critical-section",
1211
1199
  "data-encoding",
1212
1200
  "enum-as-inner",
1213
1201
  "futures-channel",
@@ -1321,7 +1309,7 @@ dependencies = [
1321
1309
  "tokio",
1322
1310
  "tokio-rustls",
1323
1311
  "tower-service",
1324
- "webpki-roots",
1312
+ "webpki-roots 0.26.11",
1325
1313
  ]
1326
1314
 
1327
1315
  [[package]]
@@ -1515,7 +1503,7 @@ dependencies = [
1515
1503
  "thiserror",
1516
1504
  "tokio",
1517
1505
  "url",
1518
- "webpki-roots",
1506
+ "webpki-roots 0.26.11",
1519
1507
  ]
1520
1508
 
1521
1509
  [[package]]
@@ -1980,9 +1968,9 @@ dependencies = [
1980
1968
 
1981
1969
  [[package]]
1982
1970
  name = "openssl-sys"
1983
- version = "0.9.107"
1971
+ version = "0.9.108"
1984
1972
  source = "registry+https://github.com/rust-lang/crates.io-index"
1985
- checksum = "8288979acd84749c744a9014b4382d42b8f7b2592847b5afb2ed29e5d16ede07"
1973
+ checksum = "e145e1651e858e820e4860f7b9c5e169bc1d8ce1c86043be79fa7b7634821847"
1986
1974
  dependencies = [
1987
1975
  "cc",
1988
1976
  "libc",
@@ -2316,9 +2304,9 @@ dependencies = [
2316
2304
 
2317
2305
  [[package]]
2318
2306
  name = "quinn-udp"
2319
- version = "0.5.11"
2307
+ version = "0.5.12"
2320
2308
  source = "registry+https://github.com/rust-lang/crates.io-index"
2321
- checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5"
2309
+ checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842"
2322
2310
  dependencies = [
2323
2311
  "cfg_aliases",
2324
2312
  "libc",
@@ -2399,9 +2387,9 @@ dependencies = [
2399
2387
 
2400
2388
  [[package]]
2401
2389
  name = "redox_syscall"
2402
- version = "0.5.11"
2390
+ version = "0.5.12"
2403
2391
  source = "registry+https://github.com/rust-lang/crates.io-index"
2404
- checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
2392
+ checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
2405
2393
  dependencies = [
2406
2394
  "bitflags",
2407
2395
  ]
@@ -2489,7 +2477,7 @@ dependencies = [
2489
2477
  "wasm-bindgen-futures",
2490
2478
  "wasm-streams",
2491
2479
  "web-sys",
2492
- "webpki-roots",
2480
+ "webpki-roots 0.26.11",
2493
2481
  "windows-registry",
2494
2482
  ]
2495
2483
 
@@ -2540,9 +2528,9 @@ dependencies = [
2540
2528
 
2541
2529
  [[package]]
2542
2530
  name = "rustix"
2543
- version = "1.0.5"
2531
+ version = "1.0.7"
2544
2532
  source = "registry+https://github.com/rust-lang/crates.io-index"
2545
- checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
2533
+ checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
2546
2534
  dependencies = [
2547
2535
  "bitflags",
2548
2536
  "errno",
@@ -2579,18 +2567,19 @@ dependencies = [
2579
2567
 
2580
2568
  [[package]]
2581
2569
  name = "rustls-pki-types"
2582
- version = "1.11.0"
2570
+ version = "1.12.0"
2583
2571
  source = "registry+https://github.com/rust-lang/crates.io-index"
2584
- checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
2572
+ checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
2585
2573
  dependencies = [
2586
2574
  "web-time",
2575
+ "zeroize",
2587
2576
  ]
2588
2577
 
2589
2578
  [[package]]
2590
2579
  name = "rustls-webpki"
2591
- version = "0.103.1"
2580
+ version = "0.103.2"
2592
2581
  source = "registry+https://github.com/rust-lang/crates.io-index"
2593
- checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
2582
+ checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437"
2594
2583
  dependencies = [
2595
2584
  "aws-lc-rs",
2596
2585
  "ring",
@@ -2832,9 +2821,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
2832
2821
 
2833
2822
  [[package]]
2834
2823
  name = "syn"
2835
- version = "2.0.100"
2824
+ version = "2.0.101"
2836
2825
  source = "registry+https://github.com/rust-lang/crates.io-index"
2837
- checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
2826
+ checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
2838
2827
  dependencies = [
2839
2828
  "proc-macro2",
2840
2829
  "quote",
@@ -2852,9 +2841,9 @@ dependencies = [
2852
2841
 
2853
2842
  [[package]]
2854
2843
  name = "synstructure"
2855
- version = "0.13.1"
2844
+ version = "0.13.2"
2856
2845
  source = "registry+https://github.com/rust-lang/crates.io-index"
2857
- checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
2846
+ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
2858
2847
  dependencies = [
2859
2848
  "proc-macro2",
2860
2849
  "quote",
@@ -2897,7 +2886,7 @@ dependencies = [
2897
2886
  "fastrand",
2898
2887
  "getrandom 0.3.2",
2899
2888
  "once_cell",
2900
- "rustix 1.0.5",
2889
+ "rustix 1.0.7",
2901
2890
  "windows-sys 0.59.0",
2902
2891
  ]
2903
2892
 
@@ -2990,9 +2979,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
2990
2979
 
2991
2980
  [[package]]
2992
2981
  name = "tokio"
2993
- version = "1.44.2"
2982
+ version = "1.45.0"
2994
2983
  source = "registry+https://github.com/rust-lang/crates.io-index"
2995
- checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
2984
+ checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
2996
2985
  dependencies = [
2997
2986
  "backtrace",
2998
2987
  "bytes",
@@ -3338,9 +3327,18 @@ dependencies = [
3338
3327
 
3339
3328
  [[package]]
3340
3329
  name = "webpki-roots"
3341
- version = "0.26.8"
3330
+ version = "0.26.11"
3331
+ source = "registry+https://github.com/rust-lang/crates.io-index"
3332
+ checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
3333
+ dependencies = [
3334
+ "webpki-roots 1.0.0",
3335
+ ]
3336
+
3337
+ [[package]]
3338
+ name = "webpki-roots"
3339
+ version = "1.0.0"
3342
3340
  source = "registry+https://github.com/rust-lang/crates.io-index"
3343
- checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
3341
+ checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb"
3344
3342
  dependencies = [
3345
3343
  "rustls-pki-types",
3346
3344
  ]
@@ -3585,18 +3583,18 @@ dependencies = [
3585
3583
 
3586
3584
  [[package]]
3587
3585
  name = "zerocopy"
3588
- version = "0.8.24"
3586
+ version = "0.8.25"
3589
3587
  source = "registry+https://github.com/rust-lang/crates.io-index"
3590
- checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879"
3588
+ checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
3591
3589
  dependencies = [
3592
3590
  "zerocopy-derive",
3593
3591
  ]
3594
3592
 
3595
3593
  [[package]]
3596
3594
  name = "zerocopy-derive"
3597
- version = "0.8.24"
3595
+ version = "0.8.25"
3598
3596
  source = "registry+https://github.com/rust-lang/crates.io-index"
3599
- checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be"
3597
+ checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
3600
3598
  dependencies = [
3601
3599
  "proc-macro2",
3602
3600
  "quote",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: impit
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Classifier: Development Status :: 4 - Beta
5
5
  Classifier: Intended Audience :: Developers
6
6
  Classifier: License :: OSI Approved :: Apache Software License
@@ -0,0 +1,107 @@
1
+ use std::time::Duration;
2
+
3
+ use thiserror::Error;
4
+
5
+ pub struct ErrorContext {
6
+ pub timeout: Duration,
7
+ pub max_redirects: usize,
8
+ pub method: String,
9
+ pub protocol: String,
10
+ pub url: String,
11
+ }
12
+
13
+ /// Error types that can be returned by the [`Impit`] struct.
14
+ ///
15
+ /// The `ImpitError` enum is used to represent the different types of errors that can occur when making requests.
16
+ /// The `RequestError` variant is used to wrap the `reqwest::Error` type.
17
+ #[derive(Error, Debug)]
18
+ pub enum ImpitError {
19
+ #[error("HTTP error occurred.")]
20
+ HTTPError,
21
+ #[error("Request error occurred.")]
22
+ RequestError,
23
+ #[error("Transport error occurred.")]
24
+ TransportError,
25
+ #[error("Request timeout ({0}) ms exceeded.")]
26
+ TimeoutException(u128),
27
+ #[error("Connection timed out.")]
28
+ ConnectTimeout,
29
+ #[error("Read operation timed out.")]
30
+ ReadTimeout,
31
+ #[error("Write operation timed out.")]
32
+ WriteTimeout,
33
+ #[error("Connection pool timed out.")]
34
+ PoolTimeout,
35
+ #[error("Network error occurred.")]
36
+ NetworkError,
37
+ #[error("Failed to connect to the server.")]
38
+ ConnectError,
39
+ #[error("Failed to read data from the server.")]
40
+ ReadError,
41
+ #[error("Failed to write data to the server.")]
42
+ WriteError,
43
+ #[error("Failed to close the connection.")]
44
+ CloseError,
45
+ #[error("Protocol error occurred.")]
46
+ ProtocolError,
47
+ #[error("Local protocol error occurred.")]
48
+ LocalProtocolError,
49
+ #[error("Remote protocol error occurred.")]
50
+ RemoteProtocolError,
51
+ #[error("The proxy URL `{0}` is invalid or unreachable.")]
52
+ ProxyError(String),
53
+ #[error("The protocol is unsupported.")]
54
+ UnsupportedProtocol,
55
+ #[error("The response body couldn't be decoded.")]
56
+ DecodingError,
57
+ #[error("Too many redirects occurred. Maximum allowed: {0}")]
58
+ TooManyRedirects(usize),
59
+ #[error("HTTP status error occurred with status code {0}.")]
60
+ HTTPStatusError(u16),
61
+ #[error("The URL is invalid.")]
62
+ InvalidURL,
63
+ #[error("A cookie conflict occurred.")]
64
+ CookieConflict,
65
+ #[error("A stream error occurred.")]
66
+ StreamError,
67
+ #[error("The stream has already been consumed.")]
68
+ StreamConsumed,
69
+ #[error("The response has not been read.")]
70
+ ResponseNotRead,
71
+ #[error("The request has not been read.")]
72
+ RequestNotRead,
73
+ #[error("The stream has been closed.")]
74
+ StreamClosed,
75
+ #[error("The URL couldn't be parsed.")]
76
+ UrlParsingError,
77
+ #[error("The URL ({0}) is missing the hostname.")]
78
+ UrlMissingHostnameError(String),
79
+ #[error("The URL uses an unsupported protocol (`{0}`). Currently, only HTTP and HTTPS are supported.")]
80
+ UrlProtocolError(String),
81
+ #[error("The request was made with http3_prior_knowledge, but HTTP/3 usage wasn't enabled.")]
82
+ Http3Disabled,
83
+ #[error("The request method `{0}` is invalid. Only GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS and TRACE are supported.")]
84
+ InvalidMethod(String),
85
+ #[error("{0}")]
86
+ BindingPassthroughError(String),
87
+ #[error("The header name `{0}` is invalid. Header names must be ASCII and cannot contain control characters or whitespace.")]
88
+ InvalidHeaderName(String),
89
+ #[error("The header value `{0}` is invalid.")]
90
+ InvalidHeaderValue(String),
91
+ #[error("{0:#?}")]
92
+ ReqwestError(reqwest::Error),
93
+ }
94
+
95
+ impl ImpitError {
96
+ pub fn from(error: reqwest::Error, context: ErrorContext) -> Self {
97
+ if error.is_timeout() {
98
+ return ImpitError::TimeoutException(context.timeout.as_millis());
99
+ }
100
+
101
+ if error.is_redirect() {
102
+ return ImpitError::TooManyRedirects(context.max_redirects);
103
+ }
104
+
105
+ ImpitError::RequestError
106
+ }
107
+ }
@@ -1,9 +1,6 @@
1
- use crate::emulation::Browser;
1
+ use crate::{emulation::Browser, errors::ImpitError};
2
2
  use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
3
- use std::{
4
- collections::{HashMap, HashSet},
5
- str::FromStr,
6
- };
3
+ use std::{collections::HashSet, str::FromStr};
7
4
 
8
5
  mod statics;
9
6
 
@@ -23,7 +20,7 @@ impl HttpHeaders {
23
20
  }
24
21
  }
25
22
 
26
- impl From<HttpHeaders> for HeaderMap {
23
+ impl From<HttpHeaders> for Result<HeaderMap, ImpitError> {
27
24
  fn from(val: HttpHeaders) -> Self {
28
25
  let impersonated_headers = match val.context.browser {
29
26
  Some(Browser::Chrome) => statics::CHROME_HEADERS,
@@ -60,13 +57,24 @@ impl From<HttpHeaders> for HeaderMap {
60
57
  continue;
61
58
  }
62
59
 
63
- headers.append(
64
- HeaderName::from_str(name).unwrap(),
65
- HeaderValue::from_str(value).unwrap(),
66
- );
60
+ let header_name = HeaderName::from_str(name);
61
+ let header_value = HeaderValue::from_str(value);
62
+
63
+ match (header_name, header_value) {
64
+ (Err(_), _) => {
65
+ return Err(ImpitError::InvalidHeaderName(name.to_string()));
66
+ }
67
+ (_, Err(_)) => {
68
+ return Err(ImpitError::InvalidHeaderValue(value.to_string()));
69
+ }
70
+ (Ok(header_name), Ok(header_value)) => {
71
+ headers.append(header_name, header_value);
72
+ }
73
+ }
74
+
67
75
  used_header_names.insert(name.to_lowercase());
68
76
  }
69
- headers
77
+ Ok(headers)
70
78
  }
71
79
  }
72
80
 
@@ -75,7 +83,7 @@ pub struct HttpHeadersBuilder {
75
83
  host: String,
76
84
  browser: Option<Browser>,
77
85
  https: bool,
78
- custom_headers: HashMap<String, String>,
86
+ custom_headers: Vec<(String, String)>,
79
87
  }
80
88
 
81
89
  impl HttpHeadersBuilder {
@@ -95,7 +103,7 @@ impl HttpHeadersBuilder {
95
103
  self
96
104
  }
97
105
 
98
- pub fn with_custom_headers(&mut self, custom_headers: &HashMap<String, String>) -> &mut Self {
106
+ pub fn with_custom_headers(&mut self, custom_headers: &Vec<(String, String)>) -> &mut Self {
99
107
  self.custom_headers = custom_headers.to_owned();
100
108
  self
101
109
  }
@@ -1,33 +1,17 @@
1
1
  use log::debug;
2
- use reqwest::{Method, Response, Version};
2
+ use reqwest::{header::HeaderMap, Method, Response, Version};
3
3
  use std::{str::FromStr, time::Duration};
4
- use thiserror::Error;
5
4
  use url::Url;
6
5
 
7
6
  use crate::{
8
- emulation::Browser, http3::H3Engine, http_headers::HttpHeaders, request::RequestOptions, tls,
7
+ emulation::Browser,
8
+ errors::{ErrorContext, ImpitError},
9
+ http3::H3Engine,
10
+ http_headers::HttpHeaders,
11
+ request::RequestOptions,
12
+ tls,
9
13
  };
10
14
 
11
- /// Error types that can be returned by the [`Impit`] struct.
12
- ///
13
- /// The `ErrorType` enum is used to represent the different types of errors that can occur when making requests.
14
- /// The `RequestError` variant is used to wrap the `reqwest::Error` type.
15
- #[derive(Error, Debug)]
16
- pub enum ErrorType {
17
- #[error("The URL couldn't be parsed.")]
18
- UrlParsingError,
19
- #[error("The URL is missing the hostname.")]
20
- UrlMissingHostnameError,
21
- #[error("The URL uses an unsupported protocol (`{0}`). Currently, only HTTP and HTTPS are supported.")]
22
- UrlProtocolError(String),
23
- #[error("The request was made with http3_prior_knowledge, but HTTP/3 usage wasn't enabled.")]
24
- Http3Disabled,
25
- #[error("The request method `{0}` is invalid. Only GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS and TRACE are supported.")]
26
- InvalidMethod(String),
27
- #[error(transparent)]
28
- RequestError(#[from] reqwest::Error),
29
- }
30
-
31
15
  /// Impit is the main struct used to make (impersonated) requests.
32
16
  ///
33
17
  /// It uses `reqwest::Client` to make requests and holds info about the impersonated browser.
@@ -250,11 +234,11 @@ impl Impit {
250
234
  }
251
235
  }
252
236
 
253
- fn parse_url(&self, url: String) -> Result<Url, ErrorType> {
254
- let url = Url::parse(&url).map_err(|_| ErrorType::UrlParsingError)?;
237
+ fn parse_url(&self, url: String) -> Result<Url, ImpitError> {
238
+ let url = Url::parse(&url).map_err(|_| ImpitError::UrlParsingError)?;
255
239
 
256
240
  if url.host_str().is_none() {
257
- return Err(ErrorType::UrlMissingHostnameError);
241
+ return Err(ImpitError::UrlMissingHostnameError(url.to_string()));
258
242
  }
259
243
 
260
244
  let protocol = url.scheme();
@@ -262,7 +246,7 @@ impl Impit {
262
246
  match protocol {
263
247
  "http" => Ok(url),
264
248
  "https" => Ok(url),
265
- _ => Err(ErrorType::UrlProtocolError(protocol.to_string())),
249
+ _ => Err(ImpitError::UrlProtocolError(protocol.to_string())),
266
250
  }
267
251
  }
268
252
 
@@ -289,11 +273,11 @@ impl Impit {
289
273
  url: String,
290
274
  body: Option<Vec<u8>>,
291
275
  options: Option<RequestOptions>,
292
- ) -> Result<Response, ErrorType> {
276
+ ) -> Result<Response, ImpitError> {
293
277
  let options = options.unwrap_or_default();
294
278
 
295
279
  if options.http3_prior_knowledge && self.config.max_http_version < Version::HTTP_3 {
296
- return Err(ErrorType::Http3Disabled);
280
+ return Err(ImpitError::Http3Disabled);
297
281
  }
298
282
 
299
283
  let parsed_url = self.parse_url(url.clone())?;
@@ -316,9 +300,11 @@ impl Impit {
316
300
  &self.base_client
317
301
  };
318
302
 
303
+ let header_map: Result<HeaderMap, ImpitError> = headers.into();
304
+
319
305
  let mut request = client
320
- .request(method.clone(), parsed_url)
321
- .headers(headers.into());
306
+ .request(method.clone(), parsed_url.clone())
307
+ .headers(header_map?);
322
308
 
323
309
  if h3 {
324
310
  request = request.version(Version::HTTP_3);
@@ -336,7 +322,21 @@ impl Impit {
336
322
  let response = request.send().await;
337
323
 
338
324
  if response.is_err() {
339
- return Err(ErrorType::RequestError(response.err().unwrap()));
325
+ let max_redirects = match self.config.redirect {
326
+ RedirectBehavior::FollowRedirect(max) => max,
327
+ RedirectBehavior::ManualRedirect => 0,
328
+ };
329
+
330
+ return Err(ImpitError::from(
331
+ response.err().unwrap(),
332
+ ErrorContext {
333
+ timeout: options.timeout.unwrap_or(Duration::from_millis(0)),
334
+ max_redirects,
335
+ method: method.to_string(),
336
+ protocol: parsed_url.scheme().to_string(),
337
+ url: url.clone(),
338
+ },
339
+ ));
340
340
  }
341
341
 
342
342
  let response = response.unwrap();
@@ -371,7 +371,7 @@ impl Impit {
371
371
  &mut self,
372
372
  url: String,
373
373
  options: Option<RequestOptions>,
374
- ) -> Result<Response, ErrorType> {
374
+ ) -> Result<Response, ImpitError> {
375
375
  self.make_request(Method::GET, url, None, options).await
376
376
  }
377
377
 
@@ -385,7 +385,7 @@ impl Impit {
385
385
  &mut self,
386
386
  url: String,
387
387
  options: Option<RequestOptions>,
388
- ) -> Result<Response, ErrorType> {
388
+ ) -> Result<Response, ImpitError> {
389
389
  self.make_request(Method::HEAD, url, None, options).await
390
390
  }
391
391
 
@@ -399,7 +399,7 @@ impl Impit {
399
399
  &mut self,
400
400
  url: String,
401
401
  options: Option<RequestOptions>,
402
- ) -> Result<Response, ErrorType> {
402
+ ) -> Result<Response, ImpitError> {
403
403
  self.make_request(Method::OPTIONS, url, None, options).await
404
404
  }
405
405
 
@@ -413,7 +413,7 @@ impl Impit {
413
413
  &mut self,
414
414
  url: String,
415
415
  options: Option<RequestOptions>,
416
- ) -> Result<Response, ErrorType> {
416
+ ) -> Result<Response, ImpitError> {
417
417
  self.make_request(Method::TRACE, url, None, options).await
418
418
  }
419
419
 
@@ -427,7 +427,7 @@ impl Impit {
427
427
  &mut self,
428
428
  url: String,
429
429
  options: Option<RequestOptions>,
430
- ) -> Result<Response, ErrorType> {
430
+ ) -> Result<Response, ImpitError> {
431
431
  self.make_request(Method::DELETE, url, None, options).await
432
432
  }
433
433
 
@@ -442,7 +442,7 @@ impl Impit {
442
442
  url: String,
443
443
  body: Option<Vec<u8>>,
444
444
  options: Option<RequestOptions>,
445
- ) -> Result<Response, ErrorType> {
445
+ ) -> Result<Response, ImpitError> {
446
446
  self.make_request(Method::POST, url, body, options).await
447
447
  }
448
448
 
@@ -457,7 +457,7 @@ impl Impit {
457
457
  url: String,
458
458
  body: Option<Vec<u8>>,
459
459
  options: Option<RequestOptions>,
460
- ) -> Result<Response, ErrorType> {
460
+ ) -> Result<Response, ImpitError> {
461
461
  self.make_request(Method::PUT, url, body, options).await
462
462
  }
463
463
 
@@ -472,7 +472,7 @@ impl Impit {
472
472
  url: String,
473
473
  body: Option<Vec<u8>>,
474
474
  options: Option<RequestOptions>,
475
- ) -> Result<Response, ErrorType> {
475
+ ) -> Result<Response, ImpitError> {
476
476
  self.make_request(Method::PATCH, url, body, options).await
477
477
  }
478
478
  }
@@ -70,6 +70,9 @@ pub mod impit;
70
70
  /// Customizing request options.
71
71
  pub mod request;
72
72
 
73
+ /// Errors and error handling.
74
+ pub mod errors;
75
+
73
76
  /// Contains browser emulation-related types and functions.
74
77
  pub mod emulation {
75
78