httpx-patched 1.6.2.1

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 (336) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +191 -0
  3. data/README.md +162 -0
  4. data/doc/release_notes/0_0_1.md +7 -0
  5. data/doc/release_notes/0_0_2.md +9 -0
  6. data/doc/release_notes/0_0_3.md +9 -0
  7. data/doc/release_notes/0_0_4.md +7 -0
  8. data/doc/release_notes/0_0_5.md +5 -0
  9. data/doc/release_notes/0_10_0.md +66 -0
  10. data/doc/release_notes/0_10_1.md +37 -0
  11. data/doc/release_notes/0_10_2.md +5 -0
  12. data/doc/release_notes/0_11_0.md +74 -0
  13. data/doc/release_notes/0_11_1.md +5 -0
  14. data/doc/release_notes/0_11_2.md +5 -0
  15. data/doc/release_notes/0_11_3.md +5 -0
  16. data/doc/release_notes/0_12_0.md +55 -0
  17. data/doc/release_notes/0_13_0.md +58 -0
  18. data/doc/release_notes/0_13_1.md +5 -0
  19. data/doc/release_notes/0_13_2.md +9 -0
  20. data/doc/release_notes/0_14_0.md +79 -0
  21. data/doc/release_notes/0_14_1.md +7 -0
  22. data/doc/release_notes/0_14_2.md +6 -0
  23. data/doc/release_notes/0_14_3.md +5 -0
  24. data/doc/release_notes/0_14_4.md +5 -0
  25. data/doc/release_notes/0_14_5.md +11 -0
  26. data/doc/release_notes/0_15_0.md +53 -0
  27. data/doc/release_notes/0_15_1.md +8 -0
  28. data/doc/release_notes/0_15_2.md +9 -0
  29. data/doc/release_notes/0_15_3.md +5 -0
  30. data/doc/release_notes/0_15_4.md +5 -0
  31. data/doc/release_notes/0_16_0.md +93 -0
  32. data/doc/release_notes/0_16_1.md +5 -0
  33. data/doc/release_notes/0_17_0.md +49 -0
  34. data/doc/release_notes/0_18_0.md +69 -0
  35. data/doc/release_notes/0_18_1.md +12 -0
  36. data/doc/release_notes/0_18_2.md +10 -0
  37. data/doc/release_notes/0_18_3.md +7 -0
  38. data/doc/release_notes/0_18_4.md +14 -0
  39. data/doc/release_notes/0_18_5.md +10 -0
  40. data/doc/release_notes/0_18_6.md +5 -0
  41. data/doc/release_notes/0_18_7.md +5 -0
  42. data/doc/release_notes/0_19_0.md +39 -0
  43. data/doc/release_notes/0_19_1.md +5 -0
  44. data/doc/release_notes/0_19_2.md +7 -0
  45. data/doc/release_notes/0_19_3.md +6 -0
  46. data/doc/release_notes/0_19_4.md +14 -0
  47. data/doc/release_notes/0_19_5.md +13 -0
  48. data/doc/release_notes/0_19_6.md +5 -0
  49. data/doc/release_notes/0_19_7.md +5 -0
  50. data/doc/release_notes/0_19_8.md +5 -0
  51. data/doc/release_notes/0_1_0.md +9 -0
  52. data/doc/release_notes/0_20_0.md +36 -0
  53. data/doc/release_notes/0_20_1.md +5 -0
  54. data/doc/release_notes/0_20_2.md +7 -0
  55. data/doc/release_notes/0_20_3.md +6 -0
  56. data/doc/release_notes/0_20_4.md +17 -0
  57. data/doc/release_notes/0_20_5.md +3 -0
  58. data/doc/release_notes/0_21_0.md +96 -0
  59. data/doc/release_notes/0_21_1.md +12 -0
  60. data/doc/release_notes/0_22_0.md +13 -0
  61. data/doc/release_notes/0_22_1.md +11 -0
  62. data/doc/release_notes/0_22_2.md +5 -0
  63. data/doc/release_notes/0_22_3.md +55 -0
  64. data/doc/release_notes/0_22_4.md +6 -0
  65. data/doc/release_notes/0_22_5.md +6 -0
  66. data/doc/release_notes/0_23_0.md +42 -0
  67. data/doc/release_notes/0_23_1.md +5 -0
  68. data/doc/release_notes/0_23_2.md +5 -0
  69. data/doc/release_notes/0_23_3.md +6 -0
  70. data/doc/release_notes/0_23_4.md +5 -0
  71. data/doc/release_notes/0_24_0.md +48 -0
  72. data/doc/release_notes/0_24_1.md +12 -0
  73. data/doc/release_notes/0_24_2.md +12 -0
  74. data/doc/release_notes/0_24_3.md +12 -0
  75. data/doc/release_notes/0_24_4.md +18 -0
  76. data/doc/release_notes/0_24_5.md +6 -0
  77. data/doc/release_notes/0_24_6.md +5 -0
  78. data/doc/release_notes/0_24_7.md +10 -0
  79. data/doc/release_notes/0_2_0.md +5 -0
  80. data/doc/release_notes/0_2_1.md +16 -0
  81. data/doc/release_notes/0_3_0.md +12 -0
  82. data/doc/release_notes/0_3_1.md +6 -0
  83. data/doc/release_notes/0_4_0.md +51 -0
  84. data/doc/release_notes/0_4_1.md +3 -0
  85. data/doc/release_notes/0_5_0.md +15 -0
  86. data/doc/release_notes/0_5_1.md +14 -0
  87. data/doc/release_notes/0_6_0.md +5 -0
  88. data/doc/release_notes/0_6_1.md +6 -0
  89. data/doc/release_notes/0_6_2.md +6 -0
  90. data/doc/release_notes/0_6_3.md +13 -0
  91. data/doc/release_notes/0_6_4.md +21 -0
  92. data/doc/release_notes/0_6_5.md +22 -0
  93. data/doc/release_notes/0_6_6.md +19 -0
  94. data/doc/release_notes/0_6_7.md +5 -0
  95. data/doc/release_notes/0_7_0.md +46 -0
  96. data/doc/release_notes/0_8_0.md +27 -0
  97. data/doc/release_notes/0_8_1.md +8 -0
  98. data/doc/release_notes/0_8_2.md +7 -0
  99. data/doc/release_notes/0_9_0.md +38 -0
  100. data/doc/release_notes/1_0_0.md +60 -0
  101. data/doc/release_notes/1_0_1.md +5 -0
  102. data/doc/release_notes/1_0_2.md +7 -0
  103. data/doc/release_notes/1_1_0.md +32 -0
  104. data/doc/release_notes/1_1_1.md +17 -0
  105. data/doc/release_notes/1_1_2.md +12 -0
  106. data/doc/release_notes/1_1_3.md +18 -0
  107. data/doc/release_notes/1_1_4.md +6 -0
  108. data/doc/release_notes/1_1_5.md +12 -0
  109. data/doc/release_notes/1_2_0.md +49 -0
  110. data/doc/release_notes/1_2_1.md +6 -0
  111. data/doc/release_notes/1_2_2.md +10 -0
  112. data/doc/release_notes/1_2_3.md +16 -0
  113. data/doc/release_notes/1_2_4.md +8 -0
  114. data/doc/release_notes/1_2_5.md +7 -0
  115. data/doc/release_notes/1_2_6.md +13 -0
  116. data/doc/release_notes/1_3_0.md +18 -0
  117. data/doc/release_notes/1_3_1.md +17 -0
  118. data/doc/release_notes/1_3_2.md +6 -0
  119. data/doc/release_notes/1_3_3.md +5 -0
  120. data/doc/release_notes/1_3_4.md +6 -0
  121. data/doc/release_notes/1_4_0.md +43 -0
  122. data/doc/release_notes/1_4_1.md +19 -0
  123. data/doc/release_notes/1_4_2.md +20 -0
  124. data/doc/release_notes/1_4_3.md +11 -0
  125. data/doc/release_notes/1_4_4.md +14 -0
  126. data/doc/release_notes/1_5_0.md +126 -0
  127. data/doc/release_notes/1_5_1.md +6 -0
  128. data/doc/release_notes/1_6_0.md +50 -0
  129. data/doc/release_notes/1_6_1.md +17 -0
  130. data/doc/release_notes/1_6_2.md +11 -0
  131. data/lib/httpx/adapters/datadog.rb +359 -0
  132. data/lib/httpx/adapters/faraday.rb +303 -0
  133. data/lib/httpx/adapters/sentry.rb +121 -0
  134. data/lib/httpx/adapters/webmock.rb +175 -0
  135. data/lib/httpx/altsvc.rb +163 -0
  136. data/lib/httpx/base64.rb +27 -0
  137. data/lib/httpx/buffer.rb +61 -0
  138. data/lib/httpx/callbacks.rb +35 -0
  139. data/lib/httpx/chainable.rb +106 -0
  140. data/lib/httpx/connection/http1.rb +399 -0
  141. data/lib/httpx/connection/http2.rb +468 -0
  142. data/lib/httpx/connection.rb +954 -0
  143. data/lib/httpx/domain_name.rb +145 -0
  144. data/lib/httpx/errors.rb +111 -0
  145. data/lib/httpx/extensions.rb +59 -0
  146. data/lib/httpx/headers.rb +176 -0
  147. data/lib/httpx/io/ssl.rb +163 -0
  148. data/lib/httpx/io/tcp.rb +239 -0
  149. data/lib/httpx/io/udp.rb +62 -0
  150. data/lib/httpx/io/unix.rb +71 -0
  151. data/lib/httpx/io.rb +11 -0
  152. data/lib/httpx/loggable.rb +56 -0
  153. data/lib/httpx/options.rb +463 -0
  154. data/lib/httpx/parser/http1.rb +186 -0
  155. data/lib/httpx/plugins/auth/basic.rb +20 -0
  156. data/lib/httpx/plugins/auth/digest.rb +102 -0
  157. data/lib/httpx/plugins/auth/ntlm.rb +35 -0
  158. data/lib/httpx/plugins/auth/socks5.rb +22 -0
  159. data/lib/httpx/plugins/auth.rb +25 -0
  160. data/lib/httpx/plugins/aws_sdk_authentication.rb +111 -0
  161. data/lib/httpx/plugins/aws_sigv4.rb +239 -0
  162. data/lib/httpx/plugins/basic_auth.rb +29 -0
  163. data/lib/httpx/plugins/brotli.rb +50 -0
  164. data/lib/httpx/plugins/callbacks.rb +127 -0
  165. data/lib/httpx/plugins/circuit_breaker/circuit.rb +100 -0
  166. data/lib/httpx/plugins/circuit_breaker/circuit_store.rb +53 -0
  167. data/lib/httpx/plugins/circuit_breaker.rb +147 -0
  168. data/lib/httpx/plugins/content_digest.rb +204 -0
  169. data/lib/httpx/plugins/cookies/cookie.rb +174 -0
  170. data/lib/httpx/plugins/cookies/jar.rb +95 -0
  171. data/lib/httpx/plugins/cookies/set_cookie_parser.rb +143 -0
  172. data/lib/httpx/plugins/cookies.rb +107 -0
  173. data/lib/httpx/plugins/digest_auth.rb +67 -0
  174. data/lib/httpx/plugins/expect.rb +120 -0
  175. data/lib/httpx/plugins/fiber_concurrency.rb +195 -0
  176. data/lib/httpx/plugins/follow_redirects.rb +233 -0
  177. data/lib/httpx/plugins/grpc/call.rb +63 -0
  178. data/lib/httpx/plugins/grpc/grpc_encoding.rb +90 -0
  179. data/lib/httpx/plugins/grpc/message.rb +55 -0
  180. data/lib/httpx/plugins/grpc.rb +282 -0
  181. data/lib/httpx/plugins/h2c.rb +127 -0
  182. data/lib/httpx/plugins/internal_telemetry.rb +107 -0
  183. data/lib/httpx/plugins/ntlm_auth.rb +62 -0
  184. data/lib/httpx/plugins/oauth.rb +183 -0
  185. data/lib/httpx/plugins/persistent.rb +82 -0
  186. data/lib/httpx/plugins/proxy/http.rb +184 -0
  187. data/lib/httpx/plugins/proxy/socks4.rb +135 -0
  188. data/lib/httpx/plugins/proxy/socks5.rb +194 -0
  189. data/lib/httpx/plugins/proxy/ssh.rb +94 -0
  190. data/lib/httpx/plugins/proxy.rb +349 -0
  191. data/lib/httpx/plugins/push_promise.rb +81 -0
  192. data/lib/httpx/plugins/query.rb +35 -0
  193. data/lib/httpx/plugins/rate_limiter.rb +55 -0
  194. data/lib/httpx/plugins/response_cache/file_store.rb +140 -0
  195. data/lib/httpx/plugins/response_cache/store.rb +33 -0
  196. data/lib/httpx/plugins/response_cache.rb +333 -0
  197. data/lib/httpx/plugins/retries.rb +230 -0
  198. data/lib/httpx/plugins/ssrf_filter.rb +145 -0
  199. data/lib/httpx/plugins/stream.rb +183 -0
  200. data/lib/httpx/plugins/stream_bidi.rb +315 -0
  201. data/lib/httpx/plugins/upgrade/h2.rb +64 -0
  202. data/lib/httpx/plugins/upgrade.rb +86 -0
  203. data/lib/httpx/plugins/webdav.rb +86 -0
  204. data/lib/httpx/plugins/xml.rb +76 -0
  205. data/lib/httpx/pmatch_extensions.rb +33 -0
  206. data/lib/httpx/pool.rb +190 -0
  207. data/lib/httpx/punycode.rb +22 -0
  208. data/lib/httpx/request/body.rb +158 -0
  209. data/lib/httpx/request.rb +328 -0
  210. data/lib/httpx/resolver/entry.rb +30 -0
  211. data/lib/httpx/resolver/https.rb +256 -0
  212. data/lib/httpx/resolver/multi.rb +102 -0
  213. data/lib/httpx/resolver/native.rb +547 -0
  214. data/lib/httpx/resolver/resolver.rb +173 -0
  215. data/lib/httpx/resolver/system.rb +255 -0
  216. data/lib/httpx/resolver.rb +189 -0
  217. data/lib/httpx/response/body.rb +242 -0
  218. data/lib/httpx/response/buffer.rb +115 -0
  219. data/lib/httpx/response.rb +304 -0
  220. data/lib/httpx/selector.rb +282 -0
  221. data/lib/httpx/session.rb +612 -0
  222. data/lib/httpx/session_extensions.rb +30 -0
  223. data/lib/httpx/timers.rb +133 -0
  224. data/lib/httpx/transcoder/body.rb +43 -0
  225. data/lib/httpx/transcoder/chunker.rb +115 -0
  226. data/lib/httpx/transcoder/deflate.rb +37 -0
  227. data/lib/httpx/transcoder/form.rb +68 -0
  228. data/lib/httpx/transcoder/gzip.rb +71 -0
  229. data/lib/httpx/transcoder/json.rb +71 -0
  230. data/lib/httpx/transcoder/multipart/decoder.rb +141 -0
  231. data/lib/httpx/transcoder/multipart/encoder.rb +120 -0
  232. data/lib/httpx/transcoder/multipart/mime_type_detector.rb +78 -0
  233. data/lib/httpx/transcoder/multipart/part.rb +35 -0
  234. data/lib/httpx/transcoder/multipart.rb +31 -0
  235. data/lib/httpx/transcoder/utils/body_reader.rb +46 -0
  236. data/lib/httpx/transcoder/utils/deflater.rb +75 -0
  237. data/lib/httpx/transcoder.rb +91 -0
  238. data/lib/httpx/utils.rb +75 -0
  239. data/lib/httpx/version.rb +5 -0
  240. data/lib/httpx.rb +66 -0
  241. data/sig/altsvc.rbs +33 -0
  242. data/sig/buffer.rbs +27 -0
  243. data/sig/callbacks.rbs +15 -0
  244. data/sig/chainable.rbs +55 -0
  245. data/sig/connection/http1.rbs +85 -0
  246. data/sig/connection/http2.rbs +116 -0
  247. data/sig/connection.rbs +169 -0
  248. data/sig/domain_name.rbs +17 -0
  249. data/sig/errors.rbs +69 -0
  250. data/sig/headers.rbs +49 -0
  251. data/sig/httpx.rbs +27 -0
  252. data/sig/io/ssl.rbs +27 -0
  253. data/sig/io/tcp.rbs +72 -0
  254. data/sig/io/udp.rbs +25 -0
  255. data/sig/io/unix.rbs +26 -0
  256. data/sig/io.rbs +3 -0
  257. data/sig/loggable.rbs +17 -0
  258. data/sig/options.rbs +202 -0
  259. data/sig/parser/http1.rbs +59 -0
  260. data/sig/plugins/auth/basic.rbs +17 -0
  261. data/sig/plugins/auth/digest.rbs +25 -0
  262. data/sig/plugins/auth/ntlm.rbs +20 -0
  263. data/sig/plugins/auth/socks5.rbs +18 -0
  264. data/sig/plugins/auth.rbs +13 -0
  265. data/sig/plugins/aws_sdk_authentication.rbs +43 -0
  266. data/sig/plugins/aws_sigv4.rbs +78 -0
  267. data/sig/plugins/basic_auth.rbs +15 -0
  268. data/sig/plugins/brotli.rbs +22 -0
  269. data/sig/plugins/callbacks.rbs +38 -0
  270. data/sig/plugins/circuit_breaker.rbs +71 -0
  271. data/sig/plugins/compression.rbs +57 -0
  272. data/sig/plugins/content_digest.rbs +51 -0
  273. data/sig/plugins/cookies/cookie.rbs +55 -0
  274. data/sig/plugins/cookies/jar.rbs +26 -0
  275. data/sig/plugins/cookies/set_cookie_parser.rbs +22 -0
  276. data/sig/plugins/cookies.rbs +28 -0
  277. data/sig/plugins/digest_auth.rbs +21 -0
  278. data/sig/plugins/expect.rbs +15 -0
  279. data/sig/plugins/fiber_concurrency.rbs +51 -0
  280. data/sig/plugins/follow_redirects.rbs +47 -0
  281. data/sig/plugins/grpc/call.rbs +23 -0
  282. data/sig/plugins/grpc/grpc_encoding.rbs +37 -0
  283. data/sig/plugins/grpc/message.rbs +17 -0
  284. data/sig/plugins/grpc.rbs +65 -0
  285. data/sig/plugins/h2c.rbs +27 -0
  286. data/sig/plugins/ntlm_auth.rbs +21 -0
  287. data/sig/plugins/oauth.rbs +68 -0
  288. data/sig/plugins/persistent.rbs +14 -0
  289. data/sig/plugins/proxy/http.rbs +30 -0
  290. data/sig/plugins/proxy/socks4.rbs +37 -0
  291. data/sig/plugins/proxy/socks5.rbs +49 -0
  292. data/sig/plugins/proxy/ssh.rbs +18 -0
  293. data/sig/plugins/proxy.rbs +70 -0
  294. data/sig/plugins/push_promise.rbs +23 -0
  295. data/sig/plugins/query.rbs +18 -0
  296. data/sig/plugins/rate_limiter.rbs +13 -0
  297. data/sig/plugins/response_cache/file_store.rbs +19 -0
  298. data/sig/plugins/response_cache/store.rbs +13 -0
  299. data/sig/plugins/response_cache.rbs +86 -0
  300. data/sig/plugins/retries.rbs +66 -0
  301. data/sig/plugins/ssrf_filter.rbs +26 -0
  302. data/sig/plugins/stream.rbs +54 -0
  303. data/sig/plugins/stream_bidi.rbs +68 -0
  304. data/sig/plugins/upgrade/h2.rbs +9 -0
  305. data/sig/plugins/upgrade.rbs +29 -0
  306. data/sig/plugins/webdav.rbs +23 -0
  307. data/sig/plugins/xml.rbs +37 -0
  308. data/sig/pool.rbs +51 -0
  309. data/sig/punycode.rbs +5 -0
  310. data/sig/request/body.rbs +34 -0
  311. data/sig/request.rbs +88 -0
  312. data/sig/resolver/entry.rbs +13 -0
  313. data/sig/resolver/https.rbs +45 -0
  314. data/sig/resolver/multi.rbs +32 -0
  315. data/sig/resolver/native.rbs +74 -0
  316. data/sig/resolver/resolver.rbs +64 -0
  317. data/sig/resolver/system.rbs +34 -0
  318. data/sig/resolver.rbs +48 -0
  319. data/sig/response/body.rbs +52 -0
  320. data/sig/response/buffer.rbs +23 -0
  321. data/sig/response.rbs +103 -0
  322. data/sig/selector.rbs +68 -0
  323. data/sig/session.rbs +104 -0
  324. data/sig/timers.rbs +54 -0
  325. data/sig/transcoder/body.rbs +24 -0
  326. data/sig/transcoder/chunker.rbs +49 -0
  327. data/sig/transcoder/deflate.rbs +12 -0
  328. data/sig/transcoder/form.rbs +34 -0
  329. data/sig/transcoder/gzip.rbs +27 -0
  330. data/sig/transcoder/json.rbs +28 -0
  331. data/sig/transcoder/multipart.rbs +103 -0
  332. data/sig/transcoder/utils/body_reader.rbs +15 -0
  333. data/sig/transcoder/utils/deflater.rbs +28 -0
  334. data/sig/transcoder.rbs +43 -0
  335. data/sig/utils.rbs +19 -0
  336. metadata +518 -0
@@ -0,0 +1,282 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ GRPCError = Class.new(Error) do
5
+ attr_reader :status, :details, :metadata
6
+
7
+ def initialize(status, details, metadata)
8
+ @status = status
9
+ @details = details
10
+ @metadata = metadata
11
+ super("GRPC error, code=#{status}, details=#{details}, metadata=#{metadata}")
12
+ end
13
+ end
14
+
15
+ module Plugins
16
+ #
17
+ # This plugin adds DSL to build GRPC interfaces.
18
+ #
19
+ # https://gitlab.com/os85/httpx/wikis/GRPC
20
+ #
21
+ module GRPC
22
+ unless String.method_defined?(:underscore)
23
+ module StringExtensions
24
+ refine String do
25
+ def underscore
26
+ s = dup # Avoid mutating the argument, as it might be frozen.
27
+ s.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
28
+ s.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
29
+ s.tr!("-", "_")
30
+ s.downcase!
31
+ s
32
+ end
33
+ end
34
+ end
35
+ using StringExtensions
36
+ end
37
+
38
+ DEADLINE = 60
39
+ MARSHAL_METHOD = :encode
40
+ UNMARSHAL_METHOD = :decode
41
+ HEADERS = {
42
+ "content-type" => "application/grpc",
43
+ "te" => "trailers",
44
+ "accept" => "application/grpc",
45
+ # metadata fits here
46
+ # ex "foo-bin" => base64("bar")
47
+ }.freeze
48
+
49
+ class << self
50
+ def load_dependencies(*)
51
+ require "stringio"
52
+ require "httpx/plugins/grpc/grpc_encoding"
53
+ require "httpx/plugins/grpc/message"
54
+ require "httpx/plugins/grpc/call"
55
+ end
56
+
57
+ def configure(klass)
58
+ klass.plugin(:persistent)
59
+ klass.plugin(:stream)
60
+ end
61
+
62
+ def extra_options(options)
63
+ options.merge(
64
+ fallback_protocol: "h2",
65
+ grpc_rpcs: {}.freeze,
66
+ grpc_compression: false,
67
+ grpc_deadline: DEADLINE
68
+ )
69
+ end
70
+ end
71
+
72
+ module OptionsMethods
73
+ private
74
+
75
+ def option_grpc_service(value)
76
+ String(value)
77
+ end
78
+
79
+ def option_grpc_compression(value)
80
+ case value
81
+ when true, false
82
+ value
83
+ else
84
+ value.to_s
85
+ end
86
+ end
87
+
88
+ def option_grpc_rpcs(value)
89
+ Hash[value]
90
+ end
91
+
92
+ def option_grpc_deadline(value)
93
+ raise TypeError, ":grpc_deadline must be positive" unless value.positive?
94
+
95
+ value
96
+ end
97
+
98
+ def option_call_credentials(value)
99
+ raise TypeError, ":call_credentials must respond to #call" unless value.respond_to?(:call)
100
+
101
+ value
102
+ end
103
+ end
104
+
105
+ module ResponseMethods
106
+ attr_reader :trailing_metadata
107
+
108
+ def merge_headers(trailers)
109
+ @trailing_metadata = Hash[trailers]
110
+ super
111
+ end
112
+ end
113
+
114
+ module RequestBodyMethods
115
+ def initialize(*, **)
116
+ super
117
+
118
+ if (compression = @headers["grpc-encoding"])
119
+ deflater_body = self.class.initialize_deflater_body(@body, compression)
120
+ @body = Transcoder::GRPCEncoding.encode(deflater_body || @body, compressed: !deflater_body.nil?)
121
+ else
122
+ @body = Transcoder::GRPCEncoding.encode(@body, compressed: false)
123
+ end
124
+ end
125
+ end
126
+
127
+ module InstanceMethods
128
+ def with_channel_credentials(ca_path, key = nil, cert = nil, **ssl_opts)
129
+ # @type var ssl_params: ::Hash[::Symbol, untyped]
130
+ ssl_params = {
131
+ **ssl_opts,
132
+ ca_file: ca_path,
133
+ }
134
+ if key
135
+ key = File.read(key) if File.file?(key)
136
+ ssl_params[:key] = OpenSSL::PKey.read(key)
137
+ end
138
+
139
+ if cert
140
+ cert = File.read(cert) if File.file?(cert)
141
+ ssl_params[:cert] = OpenSSL::X509::Certificate.new(cert)
142
+ end
143
+
144
+ with(ssl: ssl_params)
145
+ end
146
+
147
+ def rpc(rpc_name, input, output, **opts)
148
+ rpc_name = rpc_name.to_s
149
+ raise Error, "rpc #{rpc_name} already defined" if @options.grpc_rpcs.key?(rpc_name)
150
+
151
+ rpc_opts = {
152
+ deadline: @options.grpc_deadline,
153
+ }.merge(opts)
154
+
155
+ local_rpc_name = rpc_name.underscore
156
+
157
+ session_class = Class.new(self.class) do
158
+ # define rpc method with ruby style name
159
+ class_eval(<<-OUT, __FILE__, __LINE__ + 1)
160
+ def #{local_rpc_name}(input, **opts) # def grpc_action(input, **opts)
161
+ rpc_execute("#{local_rpc_name}", input, **opts) # rpc_execute("grpc_action", input, **opts)
162
+ end # end
163
+ OUT
164
+
165
+ # define rpc method with original name
166
+ unless local_rpc_name == rpc_name
167
+ class_eval(<<-OUT, __FILE__, __LINE__ + 1)
168
+ def #{rpc_name}(input, **opts) # def grpcAction(input, **opts)
169
+ rpc_execute("#{local_rpc_name}", input, **opts) # rpc_execute("grpc_action", input, **opts)
170
+ end # end
171
+ OUT
172
+ end
173
+ end
174
+
175
+ session_class.new(@options.merge(
176
+ grpc_rpcs: @options.grpc_rpcs.merge(
177
+ local_rpc_name => [rpc_name, input, output, rpc_opts]
178
+ ).freeze
179
+ ))
180
+ end
181
+
182
+ def build_stub(origin, service: nil, compression: false)
183
+ scheme = @options.ssl.empty? ? "http" : "https"
184
+
185
+ origin = URI.parse("#{scheme}://#{origin}")
186
+
187
+ session = self
188
+
189
+ if service && service.respond_to?(:rpc_descs)
190
+ # it's a grpc generic service
191
+ service.rpc_descs.each do |rpc_name, rpc_desc|
192
+ rpc_opts = {
193
+ marshal_method: rpc_desc.marshal_method,
194
+ unmarshal_method: rpc_desc.unmarshal_method,
195
+ }
196
+
197
+ input = rpc_desc.input
198
+ input = input.type if input.respond_to?(:type)
199
+
200
+ output = rpc_desc.output
201
+ if output.respond_to?(:type)
202
+ rpc_opts[:stream] = true
203
+ output = output.type
204
+ end
205
+
206
+ session = session.rpc(rpc_name, input, output, **rpc_opts)
207
+ end
208
+
209
+ service = service.service_name
210
+ end
211
+
212
+ session.with(origin: origin, grpc_service: service, grpc_compression: compression)
213
+ end
214
+
215
+ def execute(rpc_method, input,
216
+ deadline: DEADLINE,
217
+ metadata: nil,
218
+ **opts)
219
+ grpc_request = build_grpc_request(rpc_method, input, deadline: deadline, metadata: metadata, **opts)
220
+ response = request(grpc_request, **opts)
221
+ response.raise_for_status unless opts[:stream]
222
+ GRPC::Call.new(response)
223
+ end
224
+
225
+ private
226
+
227
+ def rpc_execute(rpc_name, input, **opts)
228
+ rpc_name, input_enc, output_enc, rpc_opts = @options.grpc_rpcs[rpc_name]
229
+
230
+ exec_opts = rpc_opts.merge(opts)
231
+
232
+ marshal_method ||= exec_opts.delete(:marshal_method) || MARSHAL_METHOD
233
+ unmarshal_method ||= exec_opts.delete(:unmarshal_method) || UNMARSHAL_METHOD
234
+
235
+ messages = if input.respond_to?(:each)
236
+ Enumerator.new do |y|
237
+ input.each do |message|
238
+ y << input_enc.__send__(marshal_method, message)
239
+ end
240
+ end
241
+ else
242
+ input_enc.__send__(marshal_method, input)
243
+ end
244
+
245
+ call = execute(rpc_name, messages, **exec_opts)
246
+
247
+ call.decoder = output_enc.method(unmarshal_method)
248
+
249
+ call
250
+ end
251
+
252
+ def build_grpc_request(rpc_method, input, deadline:, metadata: nil, **)
253
+ uri = @options.origin.dup
254
+ rpc_method = "/#{rpc_method}" unless rpc_method.start_with?("/")
255
+ rpc_method = "/#{@options.grpc_service}#{rpc_method}" if @options.grpc_service
256
+ uri.path = rpc_method
257
+
258
+ headers = HEADERS.merge(
259
+ "grpc-accept-encoding" => ["identity", *@options.supported_compression_formats]
260
+ )
261
+ unless deadline == Float::INFINITY
262
+ # convert to milliseconds
263
+ deadline = (deadline * 1000.0).to_i
264
+ headers["grpc-timeout"] = "#{deadline}m"
265
+ end
266
+
267
+ headers = headers.merge(metadata.transform_keys(&:to_s)) if metadata
268
+
269
+ # prepare compressor
270
+ compression = @options.grpc_compression == true ? "gzip" : @options.grpc_compression
271
+
272
+ headers["grpc-encoding"] = compression if compression
273
+
274
+ headers.merge!(@options.call_credentials.call.transform_keys(&:to_s)) if @options.call_credentials
275
+
276
+ build_request("POST", uri, headers: headers, body: input)
277
+ end
278
+ end
279
+ end
280
+ register_plugin :grpc, GRPC
281
+ end
282
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ module Plugins
5
+ #
6
+ # This plugin adds support for upgrading a plaintext HTTP/1.1 connection to HTTP/2
7
+ # (https://datatracker.ietf.org/doc/html/rfc7540#section-3.2)
8
+ #
9
+ # https://gitlab.com/os85/httpx/wikis/Connection-Upgrade#h2c
10
+ #
11
+ module H2C
12
+ VALID_H2C_VERBS = %w[GET OPTIONS HEAD].freeze
13
+
14
+ class << self
15
+ def load_dependencies(klass)
16
+ klass.plugin(:upgrade)
17
+ end
18
+
19
+ def call(connection, request, response)
20
+ connection.upgrade_to_h2c(request, response)
21
+ end
22
+
23
+ def extra_options(options)
24
+ options.merge(
25
+ h2c_class: Class.new(options.http2_class) { include(H2CParser) },
26
+ max_concurrent_requests: 1,
27
+ upgrade_handlers: options.upgrade_handlers.merge("h2c" => self),
28
+ )
29
+ end
30
+ end
31
+
32
+ module OptionsMethods
33
+ def option_h2c_class(value)
34
+ value
35
+ end
36
+ end
37
+
38
+ module RequestMethods
39
+ def valid_h2c_verb?
40
+ VALID_H2C_VERBS.include?(@verb)
41
+ end
42
+ end
43
+
44
+ module ConnectionMethods
45
+ using URIExtensions
46
+
47
+ def initialize(*)
48
+ super
49
+ @h2c_handshake = false
50
+ end
51
+
52
+ def send(request)
53
+ return super if @h2c_handshake
54
+
55
+ return super unless request.valid_h2c_verb? && request.scheme == "http"
56
+
57
+ return super if @upgrade_protocol == "h2c"
58
+
59
+ @h2c_handshake = true
60
+
61
+ # build upgrade request
62
+ request.headers.add("connection", "upgrade")
63
+ request.headers.add("connection", "http2-settings")
64
+ request.headers["upgrade"] = "h2c"
65
+ request.headers["http2-settings"] = ::HTTP2::Client.settings_header(request.options.http2_settings)
66
+
67
+ super
68
+ end
69
+
70
+ def upgrade_to_h2c(request, response)
71
+ prev_parser = @parser
72
+
73
+ if prev_parser
74
+ prev_parser.reset
75
+ @inflight -= prev_parser.requests.size
76
+ end
77
+
78
+ @parser = request.options.h2c_class.new(@write_buffer, @options)
79
+ set_parser_callbacks(@parser)
80
+ @inflight += 1
81
+ @parser.upgrade(request, response)
82
+ @upgrade_protocol = "h2c"
83
+
84
+ prev_parser.requests.each do |req|
85
+ req.transition(:idle)
86
+ send(req)
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def send_request_to_parser(request)
93
+ super
94
+
95
+ return unless request.headers["upgrade"] == "h2c" && parser.is_a?(Connection::HTTP1)
96
+
97
+ max_concurrent_requests = parser.max_concurrent_requests
98
+
99
+ return if max_concurrent_requests == 1
100
+
101
+ parser.max_concurrent_requests = 1
102
+ request.once(:response) do
103
+ parser.max_concurrent_requests = max_concurrent_requests
104
+ end
105
+ end
106
+ end
107
+
108
+ module H2CParser
109
+ def upgrade(request, response)
110
+ # skip checks, it is assumed that this is the first
111
+ # request in the connection
112
+ stream = @connection.upgrade
113
+
114
+ # on_settings
115
+ handle_stream(stream, request)
116
+ @streams[request] = stream
117
+
118
+ # clean up data left behind in the buffer, if the server started
119
+ # sending frames
120
+ data = response.read
121
+ @connection << data
122
+ end
123
+ end
124
+ end
125
+ register_plugin(:h2c, H2C)
126
+ end
127
+ end
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ module Plugins
5
+ #
6
+ # The InternalTelemetry plugin is for internal use only. It is therefore undocumented, and
7
+ # its use is disencouraged, as API compatiblity will **not be guaranteed**.
8
+ #
9
+ # The gist of it is: when debug_level of logger is enabled to 3 or greater, considered internal-only
10
+ # supported log levels, it'll be loaded by default.
11
+ #
12
+ # Against a specific point of time, which will be by default the session initialization, but can be set
13
+ # by the end user in $http_init_time, different diff metrics can be shown. The "point of time" is calculated
14
+ # using the monotonic clock.
15
+ module InternalTelemetry
16
+ DEBUG_LEVEL = 3
17
+
18
+ def self.extra_options(options)
19
+ options.merge(debug_level: 3)
20
+ end
21
+
22
+ module TrackTimeMethods
23
+ private
24
+
25
+ def elapsed_time
26
+ yield
27
+ ensure
28
+ meter_elapsed_time("#{self.class.superclass}##{caller_locations(1, 1)[0].label}")
29
+ end
30
+
31
+ def meter_elapsed_time(label)
32
+ $http_init_time ||= Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
33
+ prev_time = $http_init_time
34
+ after_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
35
+ # $http_init_time = after_time
36
+ elapsed = after_time - prev_time
37
+ # klass = self.class
38
+
39
+ # until (class_name = klass.name)
40
+ # klass = klass.superclass
41
+ # end
42
+ log(
43
+ level: DEBUG_LEVEL,
44
+ color: :red,
45
+ debug_level: @options ? @options.debug_level : DEBUG_LEVEL,
46
+ debug: nil
47
+ ) do
48
+ "[ELAPSED TIME]: #{label}: #{elapsed} (ms)" << "\e[0m"
49
+ end
50
+ end
51
+ end
52
+
53
+ module InstanceMethods
54
+ def self.included(klass)
55
+ klass.prepend TrackTimeMethods
56
+ super
57
+ end
58
+
59
+ def initialize(*)
60
+ meter_elapsed_time("Session: initializing...")
61
+ super
62
+ meter_elapsed_time("Session: initialized!!!")
63
+ end
64
+
65
+ def close(*)
66
+ super
67
+ meter_elapsed_time("Session -> close")
68
+ end
69
+
70
+ private
71
+
72
+ def build_requests(*)
73
+ elapsed_time { super }
74
+ end
75
+
76
+ def fetch_response(*)
77
+ response = super
78
+ meter_elapsed_time("Session -> response") if response
79
+ response
80
+ end
81
+
82
+ def coalesce_connections(conn1, conn2, selector, *)
83
+ result = super
84
+
85
+ meter_elapsed_time("Connection##{conn2.object_id} coalescing to Connection##{conn1.object_id}") if result
86
+
87
+ result
88
+ end
89
+ end
90
+
91
+ module PoolMethods
92
+ def self.included(klass)
93
+ klass.prepend Loggable
94
+ klass.prepend TrackTimeMethods
95
+ super
96
+ end
97
+
98
+ def checkin_connection(connection)
99
+ super.tap do
100
+ meter_elapsed_time("Pool##{object_id}: checked in connection for Connection##{connection.object_id}[#{connection.origin}]}")
101
+ end
102
+ end
103
+ end
104
+ end
105
+ register_plugin :internal_telemetry, InternalTelemetry
106
+ end
107
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HTTPX
4
+ module Plugins
5
+ #
6
+ # https://gitlab.com/os85/httpx/wikis/Auth#ntlm-auth
7
+ #
8
+ module NTLMAuth
9
+ class << self
10
+ def load_dependencies(_klass)
11
+ require_relative "auth/ntlm"
12
+ end
13
+
14
+ def extra_options(options)
15
+ options.merge(max_concurrent_requests: 1)
16
+ end
17
+ end
18
+
19
+ module OptionsMethods
20
+ private
21
+
22
+ def option_ntlm(value)
23
+ raise TypeError, ":ntlm must be a #{Authentication::Ntlm}" unless value.is_a?(Authentication::Ntlm)
24
+
25
+ value
26
+ end
27
+ end
28
+
29
+ module InstanceMethods
30
+ def ntlm_auth(user, password, domain = nil)
31
+ with(ntlm: Authentication::Ntlm.new(user, password, domain: domain))
32
+ end
33
+
34
+ private
35
+
36
+ def send_requests(*requests)
37
+ requests.flat_map do |request|
38
+ ntlm = request.options.ntlm
39
+
40
+ if ntlm
41
+ request.headers["authorization"] = ntlm.negotiate
42
+ probe_response = wrap { super(request).first }
43
+
44
+ return probe_response unless probe_response.is_a?(Response)
45
+
46
+ if probe_response.status == 401 && ntlm.can_authenticate?(probe_response.headers["www-authenticate"])
47
+ request.transition(:idle)
48
+ request.headers["authorization"] = ntlm.authenticate(request, probe_response.headers["www-authenticate"])
49
+ super(request)
50
+ else
51
+ probe_response
52
+ end
53
+ else
54
+ super(request)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ register_plugin :ntlm_auth, NTLMAuth
61
+ end
62
+ end