ruyihttp 0.8.1__py3-none-win_amd64.whl

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 (175) hide show
  1. ruyihttp/__init__.py +98 -0
  2. ruyihttp/_connect.py +109 -0
  3. ruyihttp/_firefox.py +267 -0
  4. ruyihttp/_http2.py +548 -0
  5. ruyihttp/_http3.py +503 -0
  6. ruyihttp/_nss.py +378 -0
  7. ruyihttp/_retry.py +39 -0
  8. ruyihttp/_socks.py +57 -0
  9. ruyihttp/_transport.py +1234 -0
  10. ruyihttp/adapters.py +9 -0
  11. ruyihttp/api.py +40 -0
  12. ruyihttp/firefox-profile.json +49 -0
  13. ruyihttp/firefox-root-constraints.json +3 -0
  14. ruyihttp/firefox-roots.pem +2991 -0
  15. ruyihttp/firefox-suffixes.dat +16501 -0
  16. ruyihttp/freebl3.dll +0 -0
  17. ruyihttp/licenses/README.md +29 -0
  18. ruyihttp/licenses/firefox-license.html +6470 -0
  19. ruyihttp/licenses/firefox-notice.txt +9 -0
  20. ruyihttp/licenses/mozilla-runtime-data.txt +21 -0
  21. ruyihttp/licenses/rust-aho-corasick-1.1.0-COPYING.txt +3 -0
  22. ruyihttp/licenses/rust-aho-corasick-1.1.0-LICENSE-MIT.txt +21 -0
  23. ruyihttp/licenses/rust-aho-corasick-1.1.0-UNLICENSE.txt +24 -0
  24. ruyihttp/licenses/rust-base64-0.22.1-LICENSE-APACHE.txt +201 -0
  25. ruyihttp/licenses/rust-base64-0.22.1-LICENSE-MIT.txt +21 -0
  26. ruyihttp/licenses/rust-bindgen-0.73.1-LICENSE.txt +29 -0
  27. ruyihttp/licenses/rust-bitflags-2.10.0-LICENSE-MIT.txt +25 -0
  28. ruyihttp/licenses/rust-block-buffer-0.10.3-LICENSE-APACHE.txt +201 -0
  29. ruyihttp/licenses/rust-block-buffer-0.10.3-LICENSE-MIT.txt +25 -0
  30. ruyihttp/licenses/rust-bytes-1.11.1-LICENSE.txt +25 -0
  31. ruyihttp/licenses/rust-cexpr-0.6.0-LICENSE-MIT.txt +25 -0
  32. ruyihttp/licenses/rust-cfg-if-1.0.0-LICENSE-MIT.txt +25 -0
  33. ruyihttp/licenses/rust-cfg_aliases-0.2.2-LICENSE.txt +9 -0
  34. ruyihttp/licenses/rust-clang-sys-1.7.0-LICENSE.txt +202 -0
  35. ruyihttp/licenses/rust-cpufeatures-0.2.8-LICENSE-MIT.txt +25 -0
  36. ruyihttp/licenses/rust-crypto-common-0.1.6-LICENSE-MIT.txt +25 -0
  37. ruyihttp/licenses/rust-darling-0.20.10-LICENSE.txt +21 -0
  38. ruyihttp/licenses/rust-dependencies.json +2052 -0
  39. ruyihttp/licenses/rust-digest-0.10.7-LICENSE-MIT.txt +25 -0
  40. ruyihttp/licenses/rust-enum-map-2.7.3-LICENSES-Apache-2.0.txt +73 -0
  41. ruyihttp/licenses/rust-enum-map-2.7.3-LICENSES-CC0-1.0.txt +121 -0
  42. ruyihttp/licenses/rust-enum-map-2.7.3-LICENSES-MIT.txt +9 -0
  43. ruyihttp/licenses/rust-enumset-1.1.2-LICENSE-MIT.txt +26 -0
  44. ruyihttp/licenses/rust-env_logger-0.10.0-LICENSE-MIT.txt +23 -0
  45. ruyihttp/licenses/rust-equivalent-1.0.1-LICENSE-MIT.txt +25 -0
  46. ruyihttp/licenses/rust-fnv-1.0.7-LICENSE-MIT.txt +25 -0
  47. ruyihttp/licenses/rust-generic-array-0.14.6-LICENSE.txt +21 -0
  48. ruyihttp/licenses/rust-hashbrown-0.17.1-LICENSE-MIT.txt +25 -0
  49. ruyihttp/licenses/rust-heck-0.5.0-LICENSE-MIT.txt +25 -0
  50. ruyihttp/licenses/rust-hex-0.4.3-LICENSE-APACHE.txt +202 -0
  51. ruyihttp/licenses/rust-hex-0.4.3-LICENSE-MIT.txt +20 -0
  52. ruyihttp/licenses/rust-http-1.4.0-LICENSE-APACHE.txt +201 -0
  53. ruyihttp/licenses/rust-http-1.4.0-LICENSE-MIT.txt +25 -0
  54. ruyihttp/licenses/rust-ident_case-1.0.1-LICENSE.txt +19 -0
  55. ruyihttp/licenses/rust-indexmap-2.11.4-LICENSE-MIT.txt +25 -0
  56. ruyihttp/licenses/rust-itoa-1.0.15-LICENSE-APACHE.txt +176 -0
  57. ruyihttp/licenses/rust-libc-0.2.186-LICENSE-MIT.txt +25 -0
  58. ruyihttp/licenses/rust-libloading-0.8.6-LICENSE.txt +12 -0
  59. ruyihttp/licenses/rust-minimal-lexical-0.2.1-LICENSE-APACHE.txt +201 -0
  60. ruyihttp/licenses/rust-minimal-lexical-0.2.1-LICENSE.md.txt +37 -0
  61. ruyihttp/licenses/rust-mtu-0.4.1-LICENSE-MIT.txt +25 -0
  62. ruyihttp/licenses/rust-nom-7.1.3-LICENSE.txt +20 -0
  63. ruyihttp/licenses/rust-pkcs11-bindings-0.1.8-LICENSE.txt +21 -0
  64. ruyihttp/licenses/rust-qlog-0.16.0-COPYING.txt +23 -0
  65. ruyihttp/licenses/rust-quinn-udp-0.6.0-LICENSE-APACHE.txt +201 -0
  66. ruyihttp/licenses/rust-quinn-udp-0.6.0-LICENSE-MIT.txt +7 -0
  67. ruyihttp/licenses/rust-regex-syntax-0.8.5-src-unicode_tables-LICENSE-UNICODE.txt +57 -0
  68. ruyihttp/licenses/rust-rustc-hash-2.1.1-LICENSE-APACHE.txt +176 -0
  69. ruyihttp/licenses/rust-rustc-hash-2.1.1-LICENSE-MIT.txt +23 -0
  70. ruyihttp/licenses/rust-serde_spanned-1.0.3-LICENSE-MIT.txt +19 -0
  71. ruyihttp/licenses/rust-serde_with-3.12.0-LICENSE-MIT.txt +25 -0
  72. ruyihttp/licenses/rust-sfv-0.14.0-LICENSE-MIT.txt +27 -0
  73. ruyihttp/licenses/rust-sha1-0.10.5-LICENSE-MIT.txt +27 -0
  74. ruyihttp/licenses/rust-shlex-2.0.1-LICENSE-APACHE.txt +13 -0
  75. ruyihttp/licenses/rust-shlex-2.0.1-LICENSE-MIT.txt +21 -0
  76. ruyihttp/licenses/rust-smallvec-1.15.2-LICENSE-MIT.txt +25 -0
  77. ruyihttp/licenses/rust-static_assertions-1.1.0-LICENSE-MIT.txt +21 -0
  78. ruyihttp/licenses/rust-strsim-0.11.1-LICENSE.txt +23 -0
  79. ruyihttp/licenses/rust-strum-0.27.1-LICENSE.txt +21 -0
  80. ruyihttp/licenses/rust-typenum-1.16.0-LICENSE-APACHE.txt +201 -0
  81. ruyihttp/licenses/rust-typenum-1.16.0-LICENSE-MIT.txt +21 -0
  82. ruyihttp/licenses/rust-typenum-1.16.0-LICENSE.txt +1 -0
  83. ruyihttp/licenses/rust-unicode-ident-1.0.6-LICENSE-UNICODE.txt +46 -0
  84. ruyihttp/licenses/rust-version_check-0.9.4-LICENSE-MIT.txt +19 -0
  85. ruyihttp/licenses/rust-windows-0.62.2-license-apache-2.0.txt +201 -0
  86. ruyihttp/licenses/rust-windows-0.62.2-license-mit.txt +21 -0
  87. ruyihttp/licenses/rust-winnow-0.7.13-LICENSE-MIT.txt +18 -0
  88. ruyihttp/licenses/rust-zeroize-1.8.1-LICENSE-MIT.txt +21 -0
  89. ruyihttp/licenses/rust-zeroize_derive-1.4.2-LICENSE-MIT.txt +21 -0
  90. ruyihttp/mozglue.dll +0 -0
  91. ruyihttp/necko_core.dll +0 -0
  92. ruyihttp/necko_quic.dll +0 -0
  93. ruyihttp/nss3.dll +0 -0
  94. ruyihttp/runtime-manifest.json +16 -0
  95. ruyihttp/sessions.py +83 -0
  96. ruyihttp/softokn3.dll +0 -0
  97. ruyihttp-0.8.1.dist-info/METADATA +273 -0
  98. ruyihttp-0.8.1.dist-info/RECORD +175 -0
  99. ruyihttp-0.8.1.dist-info/WHEEL +5 -0
  100. ruyihttp-0.8.1.dist-info/licenses/LICENSE +373 -0
  101. ruyihttp-0.8.1.dist-info/licenses/THIRD_PARTY_NOTICES.md +36 -0
  102. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/README.md +29 -0
  103. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/firefox-license.html +6470 -0
  104. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/firefox-notice.txt +9 -0
  105. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/mozilla-runtime-data.txt +21 -0
  106. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-aho-corasick-1.1.0-COPYING.txt +3 -0
  107. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-aho-corasick-1.1.0-LICENSE-MIT.txt +21 -0
  108. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-aho-corasick-1.1.0-UNLICENSE.txt +24 -0
  109. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-base64-0.22.1-LICENSE-APACHE.txt +201 -0
  110. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-base64-0.22.1-LICENSE-MIT.txt +21 -0
  111. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-bindgen-0.73.1-LICENSE.txt +29 -0
  112. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-bitflags-2.10.0-LICENSE-MIT.txt +25 -0
  113. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-block-buffer-0.10.3-LICENSE-APACHE.txt +201 -0
  114. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-block-buffer-0.10.3-LICENSE-MIT.txt +25 -0
  115. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-bytes-1.11.1-LICENSE.txt +25 -0
  116. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-cexpr-0.6.0-LICENSE-MIT.txt +25 -0
  117. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-cfg-if-1.0.0-LICENSE-MIT.txt +25 -0
  118. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-cfg_aliases-0.2.2-LICENSE.txt +9 -0
  119. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-clang-sys-1.7.0-LICENSE.txt +202 -0
  120. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-cpufeatures-0.2.8-LICENSE-MIT.txt +25 -0
  121. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-crypto-common-0.1.6-LICENSE-MIT.txt +25 -0
  122. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-darling-0.20.10-LICENSE.txt +21 -0
  123. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-dependencies.json +2052 -0
  124. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-digest-0.10.7-LICENSE-MIT.txt +25 -0
  125. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-enum-map-2.7.3-LICENSES-Apache-2.0.txt +73 -0
  126. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-enum-map-2.7.3-LICENSES-CC0-1.0.txt +121 -0
  127. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-enum-map-2.7.3-LICENSES-MIT.txt +9 -0
  128. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-enumset-1.1.2-LICENSE-MIT.txt +26 -0
  129. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-env_logger-0.10.0-LICENSE-MIT.txt +23 -0
  130. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-equivalent-1.0.1-LICENSE-MIT.txt +25 -0
  131. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-fnv-1.0.7-LICENSE-MIT.txt +25 -0
  132. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-generic-array-0.14.6-LICENSE.txt +21 -0
  133. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-hashbrown-0.17.1-LICENSE-MIT.txt +25 -0
  134. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-heck-0.5.0-LICENSE-MIT.txt +25 -0
  135. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-hex-0.4.3-LICENSE-APACHE.txt +202 -0
  136. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-hex-0.4.3-LICENSE-MIT.txt +20 -0
  137. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-http-1.4.0-LICENSE-APACHE.txt +201 -0
  138. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-http-1.4.0-LICENSE-MIT.txt +25 -0
  139. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-ident_case-1.0.1-LICENSE.txt +19 -0
  140. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-indexmap-2.11.4-LICENSE-MIT.txt +25 -0
  141. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-itoa-1.0.15-LICENSE-APACHE.txt +176 -0
  142. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-libc-0.2.186-LICENSE-MIT.txt +25 -0
  143. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-libloading-0.8.6-LICENSE.txt +12 -0
  144. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-minimal-lexical-0.2.1-LICENSE-APACHE.txt +201 -0
  145. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-minimal-lexical-0.2.1-LICENSE.md.txt +37 -0
  146. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-mtu-0.4.1-LICENSE-MIT.txt +25 -0
  147. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-nom-7.1.3-LICENSE.txt +20 -0
  148. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-pkcs11-bindings-0.1.8-LICENSE.txt +21 -0
  149. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-qlog-0.16.0-COPYING.txt +23 -0
  150. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-quinn-udp-0.6.0-LICENSE-APACHE.txt +201 -0
  151. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-quinn-udp-0.6.0-LICENSE-MIT.txt +7 -0
  152. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-regex-syntax-0.8.5-src-unicode_tables-LICENSE-UNICODE.txt +57 -0
  153. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-rustc-hash-2.1.1-LICENSE-APACHE.txt +176 -0
  154. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-rustc-hash-2.1.1-LICENSE-MIT.txt +23 -0
  155. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-serde_spanned-1.0.3-LICENSE-MIT.txt +19 -0
  156. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-serde_with-3.12.0-LICENSE-MIT.txt +25 -0
  157. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-sfv-0.14.0-LICENSE-MIT.txt +27 -0
  158. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-sha1-0.10.5-LICENSE-MIT.txt +27 -0
  159. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-shlex-2.0.1-LICENSE-APACHE.txt +13 -0
  160. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-shlex-2.0.1-LICENSE-MIT.txt +21 -0
  161. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-smallvec-1.15.2-LICENSE-MIT.txt +25 -0
  162. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-static_assertions-1.1.0-LICENSE-MIT.txt +21 -0
  163. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-strsim-0.11.1-LICENSE.txt +23 -0
  164. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-strum-0.27.1-LICENSE.txt +21 -0
  165. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-typenum-1.16.0-LICENSE-APACHE.txt +201 -0
  166. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-typenum-1.16.0-LICENSE-MIT.txt +21 -0
  167. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-typenum-1.16.0-LICENSE.txt +1 -0
  168. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-unicode-ident-1.0.6-LICENSE-UNICODE.txt +46 -0
  169. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-version_check-0.9.4-LICENSE-MIT.txt +19 -0
  170. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-windows-0.62.2-license-apache-2.0.txt +201 -0
  171. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-windows-0.62.2-license-mit.txt +21 -0
  172. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-winnow-0.7.13-LICENSE-MIT.txt +18 -0
  173. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-zeroize-1.8.1-LICENSE-MIT.txt +21 -0
  174. ruyihttp-0.8.1.dist-info/licenses/ruyihttp/licenses/rust-zeroize_derive-1.4.2-LICENSE-MIT.txt +21 -0
  175. ruyihttp-0.8.1.dist-info/top_level.txt +1 -0
ruyihttp/__init__.py ADDED
@@ -0,0 +1,98 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ """Requests-style API with standalone NSS and Firefox transport defaults."""
6
+
7
+ import sys
8
+
9
+ from requests import (
10
+ ConnectionError,
11
+ ConnectTimeout,
12
+ FileModeWarning,
13
+ HTTPError,
14
+ JSONDecodeError,
15
+ PreparedRequest,
16
+ ReadTimeout,
17
+ Request,
18
+ RequestException,
19
+ Response,
20
+ Timeout,
21
+ TooManyRedirects,
22
+ URLRequired,
23
+ auth,
24
+ certs,
25
+ codes,
26
+ cookies,
27
+ exceptions,
28
+ hooks,
29
+ models,
30
+ packages,
31
+ status_codes,
32
+ structures,
33
+ utils,
34
+ )
35
+
36
+ from . import adapters, api, sessions
37
+ from ._transport import HeaderMap
38
+ from .api import delete, get, head, options, patch, post, put, request
39
+ from .sessions import Session, session
40
+
41
+ __version__ = "0.8.1"
42
+ NeckoError = RequestException
43
+
44
+ for _module in (
45
+ auth,
46
+ certs,
47
+ cookies,
48
+ exceptions,
49
+ hooks,
50
+ models,
51
+ packages,
52
+ status_codes,
53
+ structures,
54
+ utils,
55
+ ):
56
+ sys.modules[f"{__name__}.{_module.__name__.rsplit('.', 1)[-1]}"] = _module
57
+
58
+ __all__ = [
59
+ "Session",
60
+ "session",
61
+ "Request",
62
+ "PreparedRequest",
63
+ "Response",
64
+ "request",
65
+ "get",
66
+ "post",
67
+ "put",
68
+ "patch",
69
+ "delete",
70
+ "head",
71
+ "options",
72
+ "codes",
73
+ "RequestException",
74
+ "ConnectionError",
75
+ "ConnectTimeout",
76
+ "HTTPError",
77
+ "ReadTimeout",
78
+ "Timeout",
79
+ "TooManyRedirects",
80
+ "URLRequired",
81
+ "JSONDecodeError",
82
+ "FileModeWarning",
83
+ "NeckoError",
84
+ "HeaderMap",
85
+ "exceptions",
86
+ "auth",
87
+ "cookies",
88
+ "adapters",
89
+ "api",
90
+ "sessions",
91
+ "models",
92
+ "structures",
93
+ "utils",
94
+ "certs",
95
+ "hooks",
96
+ "packages",
97
+ "status_codes",
98
+ ]
ruyihttp/_connect.py ADDED
@@ -0,0 +1,109 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ import threading
6
+ import time
7
+
8
+ from requests.exceptions import ConnectTimeout
9
+
10
+
11
+ class Attempt:
12
+ def __init__(self, deadline):
13
+ self.deadline = deadline
14
+ self.cancelled = threading.Event()
15
+ self._lock = threading.Lock()
16
+ self._interrupt = None
17
+
18
+ def remaining(self):
19
+ if self.cancelled.is_set():
20
+ raise OSError("Connection attempt cancelled")
21
+ if self.deadline is None:
22
+ return None
23
+ remaining = self.deadline - time.monotonic()
24
+ if remaining <= 0:
25
+ raise ConnectTimeout("Connection deadline elapsed")
26
+ return remaining
27
+
28
+ def set_interrupt(self, interrupt):
29
+ with self._lock:
30
+ self._interrupt = interrupt
31
+ if self.cancelled.is_set():
32
+ interrupt()
33
+
34
+ def detach(self):
35
+ with self._lock:
36
+ self._interrupt = None
37
+
38
+ def cancel(self):
39
+ with self._lock:
40
+ self.cancelled.set()
41
+ if self._interrupt is not None:
42
+ self._interrupt()
43
+
44
+
45
+ def race(primary, backup, timeout, delay=0.1):
46
+ started = time.monotonic()
47
+ deadline = None if timeout is None else started + timeout
48
+ attempts = [Attempt(deadline), Attempt(deadline)]
49
+ condition = threading.Condition()
50
+ completed = {}
51
+ winner = []
52
+ stopped = False
53
+
54
+ def run(index, factory):
55
+ connection = None
56
+ error = None
57
+ try:
58
+ if index:
59
+ with condition:
60
+ while not stopped and not winner and 0 not in completed:
61
+ remaining = started + delay - time.monotonic()
62
+ if remaining <= 0:
63
+ break
64
+ condition.wait(remaining)
65
+ if stopped or winner:
66
+ return
67
+ attempts[index].remaining()
68
+ connection = factory(attempts[index])
69
+ except Exception as caught:
70
+ error = caught
71
+ finally:
72
+ attempts[index].detach()
73
+ with condition:
74
+ completed[index] = error
75
+ if connection is not None and not stopped and not winner:
76
+ winner.append(connection)
77
+ connection = None
78
+ condition.notify_all()
79
+ if connection is not None:
80
+ connection.close()
81
+
82
+ threads = [
83
+ threading.Thread(
84
+ target=run, args=(0, primary), name="necko-connect-h3", daemon=True
85
+ ),
86
+ threading.Thread(
87
+ target=run, args=(1, backup), name="necko-connect-tcp", daemon=True
88
+ ),
89
+ ]
90
+ for thread in threads:
91
+ thread.start()
92
+ try:
93
+ with condition:
94
+ while not winner and len(completed) != 2:
95
+ remaining = None if deadline is None else deadline - time.monotonic()
96
+ if remaining is not None and remaining <= 0:
97
+ raise ConnectTimeout("Connection deadline elapsed")
98
+ condition.wait(remaining)
99
+ if winner:
100
+ return winner[0]
101
+ raise completed.get(1) or completed.get(0) or OSError("Connection failed")
102
+ finally:
103
+ with condition:
104
+ stopped = True
105
+ condition.notify_all()
106
+ for attempt in attempts:
107
+ attempt.cancel()
108
+ for thread in threads:
109
+ thread.join(timeout=0.1)
ruyihttp/_firefox.py ADDED
@@ -0,0 +1,267 @@
1
+ # This Source Code Form is subject to the terms of the Mozilla Public
2
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
+
5
+ import copy
6
+ import ipaddress
7
+ import os
8
+ from http.cookiejar import DefaultCookiePolicy
9
+ from pathlib import Path
10
+ from urllib.parse import urlsplit, urlunsplit
11
+
12
+ from publicsuffixlist import PublicSuffixList
13
+ from requests.cookies import RequestsCookieJar, get_cookie_header
14
+ from requests.structures import CaseInsensitiveDict
15
+
16
+
17
+ def data_path(name, directory=None):
18
+ runtime = os.environ.get("NECKO_CORE_LIBRARY")
19
+ if directory is not None or runtime:
20
+ base = (
21
+ Path(directory).expanduser()
22
+ if directory is not None
23
+ else Path(runtime).expanduser().resolve().parent
24
+ )
25
+ for candidate in (base / name, base / "ruyihttp" / name, base / "necko" / name):
26
+ if candidate.is_file():
27
+ return candidate
28
+ local = Path(__file__).with_name(name)
29
+ return local
30
+
31
+
32
+ _suffix_file = data_path("firefox-suffixes.dat")
33
+ if _suffix_file.is_file():
34
+ with _suffix_file.open(encoding="utf-8") as _suffix_data:
35
+ _SUFFIXES = PublicSuffixList(_suffix_data)
36
+ else:
37
+ _SUFFIXES = PublicSuffixList()
38
+ USER_AGENT = (
39
+ "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:158.0) Gecko/20100101 Firefox/158.0"
40
+ )
41
+ ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
42
+
43
+
44
+ def origin(url):
45
+ parsed = urlsplit(url)
46
+ host = parsed.hostname or ""
47
+ if ":" in host:
48
+ host = f"[{host}]"
49
+ port = parsed.port
50
+ if port and port != (443 if parsed.scheme == "https" else 80):
51
+ host += f":{port}"
52
+ return f"{parsed.scheme}://{host}"
53
+
54
+
55
+ def site(url):
56
+ parsed = urlsplit(url)
57
+ host = parsed.hostname or ""
58
+ return parsed.scheme, _SUFFIXES.privatesuffix(host) or host
59
+
60
+
61
+ def relation(source, target):
62
+ if not source:
63
+ return "none"
64
+ if origin(source) == origin(target):
65
+ return "same-origin"
66
+ return "same-site" if site(source) == site(target) else "cross-site"
67
+
68
+
69
+ def trustworthy(url):
70
+ parsed = urlsplit(url)
71
+ if parsed.scheme == "https" or parsed.hostname == "localhost":
72
+ return True
73
+ try:
74
+ return ipaddress.ip_address(parsed.hostname).is_loopback
75
+ except ValueError:
76
+ return False
77
+
78
+
79
+ def default_headers(context):
80
+ return CaseInsensitiveDict([
81
+ ("User-Agent", USER_AGENT),
82
+ ("Accept", ACCEPT if context == "navigation" else "*/*"),
83
+ ("Accept-Language", "en-US,en;q=0.9"),
84
+ ("Accept-Encoding", "gzip, deflate, br, zstd"),
85
+ ("Connection", "keep-alive"),
86
+ ])
87
+
88
+
89
+ def apply_headers(request, context, document_url, user_activation=True):
90
+ headers = request.headers
91
+ if not hasattr(request, "_firefox_explicit"):
92
+ request._firefox_explicit = set(headers)
93
+ explicit = request._firefox_explicit
94
+ if headers.get("Accept-Encoding") == "gzip, deflate, br, zstd" and not trustworthy(
95
+ request.url
96
+ ):
97
+ headers["Accept-Encoding"] = "gzip, deflate"
98
+ reference = document_url or headers.get("Referer")
99
+ relationship = relation(reference, request.url)
100
+ computed = {}
101
+ if context == "navigation":
102
+ computed["Upgrade-Insecure-Requests"] = "1"
103
+ if trustworthy(request.url):
104
+ computed.update({
105
+ "Sec-Fetch-Dest": "document" if context == "navigation" else "empty",
106
+ "Sec-Fetch-Mode": "navigate" if context == "navigation" else "cors",
107
+ "Sec-Fetch-Site": relationship,
108
+ })
109
+ if context == "navigation" and user_activation:
110
+ computed["Sec-Fetch-User"] = "?1"
111
+ computed["Priority"] = "u=0, i" if context == "navigation" else "u=4"
112
+ if reference:
113
+ secure_downgrade = (
114
+ urlsplit(reference).scheme == "https"
115
+ and urlsplit(request.url).scheme != "https"
116
+ )
117
+ if not secure_downgrade:
118
+ parsed = urlsplit(reference)
119
+ computed["Referer"] = (
120
+ urlunsplit((
121
+ parsed.scheme,
122
+ urlsplit(origin(reference)).netloc,
123
+ parsed.path or "/",
124
+ parsed.query,
125
+ "",
126
+ ))
127
+ if relationship == "same-origin"
128
+ else origin(reference) + "/"
129
+ )
130
+ if (
131
+ request.method not in ("GET", "HEAD")
132
+ or context == "fetch"
133
+ and relationship != "same-origin"
134
+ ):
135
+ computed["Origin"] = origin(reference)
136
+ elif request.method not in ("GET", "HEAD"):
137
+ computed["Origin"] = "null"
138
+ for name in (
139
+ "Sec-Fetch-Dest",
140
+ "Sec-Fetch-Mode",
141
+ "Sec-Fetch-Site",
142
+ "Sec-Fetch-User",
143
+ "Upgrade-Insecure-Requests",
144
+ "Priority",
145
+ "Referer",
146
+ "Origin",
147
+ ):
148
+ if name not in explicit:
149
+ headers.pop(name, None)
150
+ if name in computed:
151
+ headers[name] = computed[name]
152
+ request._firefox_context = context
153
+ request._firefox_document = reference
154
+
155
+
156
+ def wire_headers(headers, http2):
157
+ ordered = CaseInsensitiveDict()
158
+ first = (
159
+ "Host",
160
+ "User-Agent",
161
+ "Accept",
162
+ "Accept-Language",
163
+ "Accept-Encoding",
164
+ "Referer",
165
+ "Origin",
166
+ "Content-Type",
167
+ "Content-Length",
168
+ "Connection",
169
+ "Cookie",
170
+ "Alt-Used",
171
+ "Upgrade-Insecure-Requests",
172
+ "Sec-Fetch-Dest",
173
+ "Sec-Fetch-Mode",
174
+ "Sec-Fetch-Site",
175
+ "Sec-Fetch-User",
176
+ "Priority",
177
+ )
178
+ for name in first:
179
+ if name in headers:
180
+ ordered[name] = headers[name]
181
+ for name, value in headers.items():
182
+ if name not in ordered:
183
+ ordered[name] = value
184
+ if http2:
185
+ ordered["TE"] = "trailers"
186
+ return ordered
187
+
188
+
189
+ class CookiePolicy(DefaultCookiePolicy):
190
+ def __init__(self, context="navigation", document_url=None):
191
+ super().__init__(strict_ns_domain=self.DomainStrictNonDomain)
192
+ self.context = context
193
+ self.document_url = document_url
194
+
195
+ def set_ok(self, cookie, request):
196
+ if not super().set_ok(cookie, request):
197
+ return False
198
+ domain = cookie.domain.lstrip(".")
199
+ if cookie.domain_specified and _SUFFIXES.publicsuffix(domain) == domain:
200
+ return False
201
+ if cookie.secure and not trustworthy(request.get_full_url()):
202
+ return False
203
+ if cookie.name.startswith("__Secure-") and not cookie.secure:
204
+ return False
205
+ if cookie.name.startswith("__Host-") and (
206
+ not cookie.secure or cookie.domain_specified or cookie.path != "/"
207
+ ):
208
+ return False
209
+ same_site = self.same_site(cookie)
210
+ return same_site != "none" or cookie.secure
211
+
212
+ def return_ok(self, cookie, request):
213
+ if not super().return_ok(cookie, request):
214
+ return False
215
+ if not self.document_url or site(self.document_url) == site(
216
+ request.get_full_url()
217
+ ):
218
+ return True
219
+ same_site = self.same_site(cookie)
220
+ if same_site == "none":
221
+ return cookie.secure
222
+ return (
223
+ same_site != "strict"
224
+ and self.context == "navigation"
225
+ and (
226
+ request.get_method()
227
+ if hasattr(request, "get_method")
228
+ else request._r.method
229
+ )
230
+ in ("GET", "HEAD", "OPTIONS", "TRACE")
231
+ )
232
+
233
+ @staticmethod
234
+ def same_site(cookie):
235
+ return str(
236
+ next(
237
+ (
238
+ value
239
+ for key, value in cookie._rest.items()
240
+ if key.lower() == "samesite"
241
+ ),
242
+ "Lax",
243
+ )
244
+ ).lower()
245
+
246
+
247
+ def apply_cookies(request, context, document_url):
248
+ jar = getattr(request, "_cookies", None)
249
+ if jar is not None:
250
+ for cookie in list(jar):
251
+ if not cookie.domain:
252
+ bound = copy.copy(cookie)
253
+ bound.domain = urlsplit(request.url).hostname
254
+ if "." not in bound.domain and ":" not in bound.domain:
255
+ bound.domain += ".local"
256
+ jar.clear(cookie.domain, cookie.path, cookie.name)
257
+ jar.set_cookie(bound)
258
+ jar.set_policy(CookiePolicy(context, document_url))
259
+ if getattr(request, "_firefox_cookie_header", False):
260
+ request.headers.pop("Cookie", None)
261
+ value = get_cookie_header(jar, request)
262
+ if value:
263
+ request.headers["Cookie"] = value
264
+
265
+
266
+ def cookie_jar(context, document_url):
267
+ return RequestsCookieJar(policy=CookiePolicy(context, document_url))