wreq 1.2.3-x64-mingw-ucrt

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 (69) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.lock +1687 -0
  3. data/Cargo.toml +54 -0
  4. data/Gemfile +18 -0
  5. data/LICENSE +201 -0
  6. data/README.md +153 -0
  7. data/Rakefile +90 -0
  8. data/build.rs +16 -0
  9. data/docs/windows-gnu-tokio-crash.md +70 -0
  10. data/examples/body.rb +42 -0
  11. data/examples/client.rb +33 -0
  12. data/examples/cookie.rb +24 -0
  13. data/examples/emulate_request.rb +37 -0
  14. data/examples/headers.rb +27 -0
  15. data/examples/proxy.rb +113 -0
  16. data/examples/send_stream.rb +85 -0
  17. data/examples/stream.rb +14 -0
  18. data/examples/thread_interrupt.rb +83 -0
  19. data/extconf.rb +7 -0
  20. data/lib/wreq.rb +303 -0
  21. data/lib/wreq_ruby/3.3/wreq_ruby.so +0 -0
  22. data/lib/wreq_ruby/3.4/wreq_ruby.so +0 -0
  23. data/lib/wreq_ruby/4.0/wreq_ruby.so +0 -0
  24. data/lib/wreq_ruby/body.rb +36 -0
  25. data/lib/wreq_ruby/client.rb +526 -0
  26. data/lib/wreq_ruby/cookie.rb +156 -0
  27. data/lib/wreq_ruby/emulate.rb +232 -0
  28. data/lib/wreq_ruby/error.rb +157 -0
  29. data/lib/wreq_ruby/header.rb +205 -0
  30. data/lib/wreq_ruby/http.rb +160 -0
  31. data/lib/wreq_ruby/response.rb +209 -0
  32. data/script/build_platform_gem.rb +34 -0
  33. data/script/build_windows_gnu.ps1 +257 -0
  34. data/src/arch.rs +33 -0
  35. data/src/client/body/form.rs +2 -0
  36. data/src/client/body/json.rs +16 -0
  37. data/src/client/body/stream.rs +146 -0
  38. data/src/client/body.rs +57 -0
  39. data/src/client/param.rs +19 -0
  40. data/src/client/query.rs +2 -0
  41. data/src/client/req.rs +274 -0
  42. data/src/client/resp.rs +248 -0
  43. data/src/client.rs +413 -0
  44. data/src/cookie.rs +312 -0
  45. data/src/emulate.rs +376 -0
  46. data/src/error.rs +163 -0
  47. data/src/extractor.rs +117 -0
  48. data/src/gvl.rs +154 -0
  49. data/src/header.rs +245 -0
  50. data/src/http.rs +142 -0
  51. data/src/lib.rs +98 -0
  52. data/src/macros.rs +123 -0
  53. data/src/rt.rs +46 -0
  54. data/test/client_cookie_test.rb +46 -0
  55. data/test/client_test.rb +136 -0
  56. data/test/cookie_test.rb +182 -0
  57. data/test/emulation_test.rb +21 -0
  58. data/test/error_handling_test.rb +92 -0
  59. data/test/header_test.rb +290 -0
  60. data/test/inspect_test.rb +125 -0
  61. data/test/module_methods_test.rb +75 -0
  62. data/test/orig_header_test.rb +115 -0
  63. data/test/request_parameters_test.rb +175 -0
  64. data/test/request_test.rb +244 -0
  65. data/test/response_test.rb +69 -0
  66. data/test/stream_test.rb +397 -0
  67. data/test/test_helper.rb +52 -0
  68. data/wreq.gemspec +68 -0
  69. metadata +123 -0
@@ -0,0 +1,397 @@
1
+ require "test_helper"
2
+ require "socket"
3
+
4
+ class StreamTest < Minitest::Test
5
+ def test_simple_push_stream
6
+ client = Wreq::Client.new
7
+ sender = Wreq::BodySender.new(4)
8
+ producer = Thread.new do
9
+ 3.times { |i| sender.push("chunk-#{i}\n") }
10
+ sender.close
11
+ end
12
+
13
+ resp = client.post("#{HTTPBIN_URL}/post", body: sender, headers: {"Content-Type" => "text/plain"})
14
+
15
+ assert_equal 200, resp.code
16
+
17
+ echoed = resp.json["data"]
18
+ assert_includes echoed, "chunk-0"
19
+ assert_includes echoed, "chunk-1"
20
+ assert_includes echoed, "chunk-2"
21
+
22
+ producer.join
23
+ end
24
+
25
+ def test_response_body_chunks_stream
26
+ client = Wreq::Client.new
27
+ resp = client.get("#{HTTPBIN_URL}/stream/5")
28
+ chunks = []
29
+
30
+ resp.chunks do |chunk|
31
+ chunks << chunk
32
+ assert_kind_of String, chunk, "Each yielded chunk must be a String"
33
+ assert_match(/\{.*\}/, chunk)
34
+ end
35
+
36
+ assert_equal 5, chunks.size, "Should yield exactly 5 chunks from /stream/5"
37
+ end
38
+
39
+ def test_chunks_yields_binary_encoding
40
+ client = Wreq::Client.new
41
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
42
+
43
+ resp.chunks do |chunk|
44
+ assert chunk.encoding == Encoding::BINARY || chunk.encoding == Encoding::ASCII_8BIT,
45
+ "Chunk should have binary encoding, got #{chunk.encoding}"
46
+ end
47
+ end
48
+
49
+ def test_chunks_with_single_chunk_body
50
+ client = Wreq::Client.new
51
+ resp = client.get("#{HTTPBIN_URL}/bytes/1024")
52
+ chunk_count = 0
53
+ total_bytes = 0
54
+
55
+ resp.chunks do |chunk|
56
+ chunk_count += 1
57
+ total_bytes += chunk.bytesize
58
+ end
59
+
60
+ assert chunk_count >= 1, "Should yield at least one chunk"
61
+ assert_equal 1024, total_bytes, "Total bytes should match content length"
62
+ end
63
+
64
+ def test_chunks_returns_nil
65
+ client = Wreq::Client.new
66
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
67
+
68
+ result = resp.chunks { |_chunk| :processing }
69
+
70
+ assert_nil result, "chunks should return nil after completion"
71
+ end
72
+
73
+ def test_chunks_with_empty_body
74
+ client = Wreq::Client.new
75
+ resp = client.get("#{HTTPBIN_URL}/status/204")
76
+ chunk_count = 0
77
+
78
+ resp.chunks do |_chunk|
79
+ chunk_count += 1
80
+ end
81
+
82
+ assert_equal 0, chunk_count, "No chunks should be yielded for empty 204 response"
83
+ end
84
+
85
+ def test_chunks_without_block_raises_error
86
+ client = Wreq::Client.new
87
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
88
+
89
+ assert_raises(LocalJumpError) do
90
+ resp.chunks
91
+ end
92
+ end
93
+
94
+ def test_other_threads_run_during_streaming
95
+ client = Wreq::Client.new
96
+ resp = client.get("#{HTTPBIN_URL}/drip?duration=3&numbytes=3&delay=1")
97
+
98
+ counter = 0
99
+ tick_thread = Thread.new do
100
+ 30.times do
101
+ counter += 1
102
+ sleep 0.1
103
+ end
104
+ end
105
+
106
+ chunks_received = 0
107
+ resp.chunks do |_chunk|
108
+ chunks_received += 1
109
+ end
110
+
111
+ tick_thread.join(10)
112
+
113
+ assert counter > 5,
114
+ "Counter only reached #{counter} - other threads may not be running during streaming. " \
115
+ "GVL should be released during I/O waits."
116
+ assert chunks_received >= 1, "Should have received at least one chunk"
117
+ end
118
+
119
+ def test_multiple_concurrent_streams
120
+ client = Wreq::Client.new
121
+ results = {}
122
+ done = {}
123
+
124
+ t1 = Thread.new do
125
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
126
+ chunks = []
127
+ resp.chunks { |chunk| chunks << chunk }
128
+ results[:t1] = chunks.size
129
+ done[:t1] = true
130
+ end
131
+
132
+ t2 = Thread.new do
133
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
134
+ chunks = []
135
+ resp.chunks { |chunk| chunks << chunk }
136
+ results[:t2] = chunks.size
137
+ done[:t2] = true
138
+ end
139
+
140
+ t1.join(15)
141
+ t2.join(15)
142
+
143
+ assert done[:t1], "Thread 1 should complete"
144
+ assert done[:t2], "Thread 2 should complete"
145
+ assert_equal 3, results[:t1], "Thread 1 should receive 3 chunks"
146
+ assert_equal 3, results[:t2], "Thread 2 should receive 3 chunks"
147
+ end
148
+
149
+ def test_thread_interrupt_connect
150
+ url = "http://10.255.255.1:12345/"
151
+ thread = Thread.new do
152
+ Wreq.get(url)
153
+ rescue => _
154
+ end
155
+
156
+ sleep 2
157
+ thread.kill
158
+ killed = thread.join(5)
159
+
160
+ assert killed, "Connect phase should be interruptible"
161
+ end
162
+
163
+ def test_thread_interrupt_connect_with_timeout
164
+ url = "http://10.255.255.1:12345/"
165
+ thread = Thread.new do
166
+ Wreq.get(url, timeout: 60)
167
+ rescue => _
168
+ end
169
+
170
+ sleep 2
171
+ thread.kill
172
+ killed = thread.join(5)
173
+
174
+ assert killed, "Connect+timeout phase should be interruptible"
175
+ end
176
+
177
+ def test_thread_interrupt_body_reading
178
+ url = "#{HTTPBIN_URL}/drip?duration=5&numbytes=5"
179
+ thread = Thread.new do
180
+ resp = Wreq.get(url)
181
+ resp.text
182
+ rescue => _
183
+ end
184
+
185
+ sleep 2
186
+ thread.kill
187
+ killed = thread.join(5)
188
+
189
+ assert killed, "Body reading should be interruptible"
190
+ end
191
+
192
+ def test_thread_interrupt_body_streaming
193
+ url = "#{HTTPBIN_URL}/drip?duration=5&numbytes=5"
194
+ thread = Thread.new do
195
+ resp = Wreq.get(url)
196
+ resp.chunks { |chunk| chunk }
197
+ rescue => _
198
+ end
199
+
200
+ sleep 2
201
+ thread.kill
202
+ killed = thread.join(5)
203
+
204
+ assert killed, "Body streaming should be interruptible"
205
+ end
206
+
207
+ def test_thread_interrupt_during_slow_stream_with_block_processing
208
+ url = "#{HTTPBIN_URL}/drip?duration=5&numbytes=5&delay=1"
209
+ thread = Thread.new do
210
+ resp = Wreq.get(url)
211
+ resp.chunks do |_chunk|
212
+ sleep 0.5
213
+ end
214
+ rescue => _
215
+ end
216
+
217
+ sleep 2
218
+ thread.kill
219
+ killed = thread.join(5)
220
+
221
+ assert killed, "Streaming with slow block processing should be interruptible"
222
+ end
223
+
224
+ def test_chunks_propagates_streaming_errors
225
+ client = Wreq::Client.new
226
+
227
+ with_truncated_chunked_response do |url|
228
+ resp = client.get(url)
229
+ error = assert_raises(Wreq::BodyError, Wreq::ConnectionResetError, Wreq::DecodingError) do
230
+ resp.chunks do |_chunk|
231
+ end
232
+ end
233
+
234
+ assert_match(/body|connection|decode|incomplete|closed|unexpected/i, error.message)
235
+ end
236
+ end
237
+
238
+ def test_exception_in_block_propagates
239
+ client = Wreq::Client.new
240
+ resp = client.get("#{HTTPBIN_URL}/stream/5")
241
+ error_raised = false
242
+ chunks_before_error = 0
243
+
244
+ begin
245
+ resp.chunks do |_chunk|
246
+ chunks_before_error += 1
247
+ raise "intentional error in block" if chunks_before_error == 2
248
+ end
249
+ rescue RuntimeError => e
250
+ error_raised = true
251
+ assert_equal "intentional error in block", e.message
252
+ end
253
+
254
+ assert error_raised, "Exception raised inside the block should propagate out"
255
+ assert_equal 2, chunks_before_error, "Should have processed 2 chunks before the error"
256
+ end
257
+
258
+ def test_chunks_called_twice_raises_error
259
+ client = Wreq::Client.new
260
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
261
+ resp.chunks { |_chunk| }
262
+ error_raised = false
263
+
264
+ begin
265
+ resp.chunks { |_chunk| }
266
+ rescue => e
267
+ error_raised = true
268
+ assert_instance_of Wreq::MemoryError, e,
269
+ "Second chunks call should raise MemoryError, got #{e.class}: #{e.message}"
270
+ end
271
+
272
+ assert error_raised, "Second chunks call should raise an error"
273
+ end
274
+
275
+ def test_text_after_chunks_raises_error
276
+ client = Wreq::Client.new
277
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
278
+ resp.chunks { |_chunk| }
279
+ error_raised = false
280
+
281
+ begin
282
+ resp.text
283
+ rescue => e
284
+ error_raised = true
285
+ assert_instance_of Wreq::MemoryError, e,
286
+ "Calling text after chunks should raise MemoryError, got #{e.class}: #{e.message}"
287
+ end
288
+
289
+ assert error_raised, "Calling text after chunks should raise an error"
290
+ end
291
+
292
+ def test_chunks_content_matches_full_body
293
+ client = Wreq::Client.new
294
+ resp_full = client.get("#{HTTPBIN_URL}/bytes/4096")
295
+ full_bytes = resp_full.bytes
296
+
297
+ resp_stream = client.get("#{HTTPBIN_URL}/bytes/4096")
298
+ streamed_bytes = "".b
299
+ resp_stream.chunks do |chunk|
300
+ streamed_bytes << chunk
301
+ end
302
+
303
+ assert_equal full_bytes.bytesize, streamed_bytes.bytesize,
304
+ "Streamed body size should match full body size"
305
+ end
306
+
307
+ def test_chunks_json_stream_content
308
+ client = Wreq::Client.new
309
+ resp = client.get("#{HTTPBIN_URL}/stream/5")
310
+ chunks = []
311
+
312
+ resp.chunks do |chunk|
313
+ chunks << chunk
314
+ end
315
+
316
+ chunks.each_with_index do |chunk, i|
317
+ assert_match(/\{.*\}/, chunk,
318
+ "Chunk #{i} should contain a JSON object, got: #{chunk[0..80]}")
319
+ end
320
+ end
321
+
322
+ def test_block_not_garbage_collected_during_streaming
323
+ client = Wreq::Client.new
324
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
325
+ chunks_received = 0
326
+
327
+ resp.chunks do |_chunk|
328
+ chunks_received += 1
329
+ GC.start
330
+ GC.start
331
+ end
332
+
333
+ assert_equal 3, chunks_received,
334
+ "All 3 chunks should be received even with forced GC between yields"
335
+ end
336
+
337
+ def test_close_after_streaming
338
+ client = Wreq::Client.new
339
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
340
+
341
+ resp.chunks { |_chunk| }
342
+ resp.close
343
+ end
344
+
345
+ def test_chunks_via_module_method
346
+ resp = Wreq.get("#{HTTPBIN_URL}/stream/3")
347
+ chunks = []
348
+
349
+ resp.chunks do |chunk|
350
+ chunks << chunk
351
+ end
352
+
353
+ assert_equal 3, chunks.size, "Module-level Wreq.get + chunks should work"
354
+ end
355
+
356
+ def test_chunks_via_client_instance
357
+ client = Wreq::Client.new
358
+ resp = client.get("#{HTTPBIN_URL}/stream/3")
359
+ chunks = []
360
+
361
+ resp.chunks do |chunk|
362
+ chunks << chunk
363
+ end
364
+
365
+ assert_equal 3, chunks.size, "Client instance get + chunks should work"
366
+ end
367
+
368
+ private
369
+
370
+ def with_truncated_chunked_response
371
+ server = TCPServer.new("127.0.0.1", 0)
372
+ port = server.addr[1]
373
+ thread = Thread.new do
374
+ socket = server.accept
375
+ begin
376
+ socket.readpartial(4096) if IO.select([socket], nil, nil, 5)
377
+ socket.write "HTTP/1.1 200 OK\r\n"
378
+ socket.write "Content-Type: text/plain\r\n"
379
+ socket.write "Transfer-Encoding: chunked\r\n"
380
+ socket.write "\r\n"
381
+ socket.write "5\r\nhello\r\n"
382
+ socket.write "A\r\nshort"
383
+ ensure
384
+ socket.close unless socket.closed?
385
+ end
386
+ rescue IOError, SystemCallError
387
+ ensure
388
+ server.close unless server.closed?
389
+ end
390
+ thread.report_on_exception = false
391
+
392
+ yield "http://127.0.0.1:#{port}/"
393
+ ensure
394
+ server&.close unless server&.closed?
395
+ thread&.join(5)
396
+ end
397
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
4
+ require "wreq"
5
+
6
+ HTTPBIN_URL = ENV.fetch("HTTPBIN_URL", "https://httpbin.io").delete_suffix("/")
7
+ MINITEST_RETRY_COUNT = Integer(ENV.fetch("MINITEST_RETRY_COUNT", "3"))
8
+ MINITEST_RETRY_DISPLAY_FAILURE_MESSAGES =
9
+ ENV.fetch("MINITEST_RETRY_DISPLAY_FAILURE_MESSAGES", "true") != "false"
10
+ MINITEST_RETRY_SLEEP_INTERVAL = Float(ENV.fetch("MINITEST_RETRY_SLEEP_INTERVAL", "1"))
11
+
12
+ require "minitest/autorun"
13
+ require "minitest/retry"
14
+
15
+ # httpbin.io is a shared external service, so the integration tests can see
16
+ # occasional network failures even when the client behavior is correct.
17
+ Minitest::Retry.use!(
18
+ retry_count: MINITEST_RETRY_COUNT,
19
+ verbose: false,
20
+ io: $stderr
21
+ )
22
+
23
+ Minitest::Retry.on_retry do |klass, test_name, attempt, result|
24
+ $stderr.puts "[MinitestRetry] retry #{klass}##{test_name} (#{attempt}/#{MINITEST_RETRY_COUNT})"
25
+
26
+ if MINITEST_RETRY_DISPLAY_FAILURE_MESSAGES
27
+ result.failures.each do |failure|
28
+ message = failure.message.to_s.strip
29
+ $stderr.puts message unless message.empty?
30
+ end
31
+ end
32
+
33
+ sleep MINITEST_RETRY_SLEEP_INTERVAL if MINITEST_RETRY_SLEEP_INTERVAL.positive?
34
+ end
35
+
36
+ module HttpbinHelpers
37
+ def httpbin_value(value)
38
+ (value.is_a?(Array) && value.length == 1) ? value.first : value
39
+ end
40
+
41
+ def httpbin_fetch(hash, key)
42
+ httpbin_value(hash.fetch(key))
43
+ end
44
+
45
+ def httpbin_cookies(json)
46
+ json.fetch("cookies", json)
47
+ end
48
+ end
49
+
50
+ class Minitest::Test
51
+ include HttpbinHelpers
52
+ end
data/wreq.gemspec ADDED
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "wreq"
7
+ # RubyGems integrates and expects `cargo`.
8
+ # Read more about
9
+ # [Gem::Ext::CargoBuilder](https://github.com/rubygems/rubygems/blob/v3.5.23/lib/rubygems/ext/cargo_builder.rb)
10
+ #
11
+ # wreq relies on "version" in `Cargo.toml` for the release process. You can read this gem spec with:
12
+ # `bundle exec ruby -e 'puts Gem::Specification.load("wreq.gemspec")'`
13
+ #
14
+ # keep in sync the key "wreq-ruby" with `Rakefile`.
15
+ #
16
+ # uses `cargo` to extract the version.
17
+ cargo_output = `cargo metadata --format-version 1`
18
+ cargo_output.force_encoding("UTF-8")
19
+ spec.version = JSON.parse(cargo_output.strip)
20
+ .fetch("packages")
21
+ .find { |p| p["name"] == "wreq-ruby" }
22
+ .fetch("version")
23
+ spec.authors = ["SearchApi"]
24
+ spec.email = ["support@searchapi.io"]
25
+ spec.summary = "Ruby bindings for wreq, an HTTP client with TLS/HTTP2 browser fingerprinting"
26
+ spec.description = "An easy and powerful Ruby HTTP client with advanced browser fingerprinting " \
27
+ "that accurately emulates Chrome, Edge, Firefox, Safari, Opera, and OkHttp " \
28
+ "with precise TLS/HTTP2 signatures. Powered by wreq (Rust) and BoringSSL."
29
+ spec.homepage = "https://github.com/SearchApi/wreq-ruby"
30
+ spec.license = "Apache-2.0"
31
+ spec.metadata = {
32
+ "bug_tracker_uri" => "https://github.com/SearchApi/wreq-ruby/issues",
33
+ "changelog_uri" => "https://github.com/SearchApi/wreq-ruby/releases",
34
+ "documentation_uri" => "https://github.com/SearchApi/wreq-ruby#readme",
35
+ "homepage_uri" => spec.homepage,
36
+ "source_code_uri" => "https://github.com/SearchApi/wreq-ruby",
37
+ "rubygems_mfa_required" => "true"
38
+ }
39
+
40
+ # Specify which files should be added to a source release gem when we release wreq Ruby gem.
41
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
42
+ spec.files = Dir.chdir(__dir__) do
43
+ git_output = `git ls-files -z`
44
+ git_output.force_encoding("UTF-8")
45
+ git_output.split("\x0").reject do |f|
46
+ f.start_with?(*%w[gems/ pkg/ target/ tmp/ .git]) ||
47
+ f.match?(/\.gem$/) || # Exclude gem files
48
+ f.match?(/^wreq-.*\.gem$/) # Exclude any wreq gem files
49
+ end
50
+ end
51
+
52
+ spec.require_paths = ["lib"]
53
+
54
+ spec.extensions = ["./extconf.rb"]
55
+
56
+ # Exclude non-Ruby files from RDoc to prevent parsing errors
57
+ spec.rdoc_options = ["--exclude", "Cargo\\..*", "--exclude", "\\.rs$"]
58
+
59
+ spec.requirements = ["Rust >= 1.85"]
60
+ # use a Ruby version which:
61
+ # - supports Rubygems with the ability of compilation of Rust gem
62
+ # - not end of life
63
+ #
64
+ # keep in sync with `Rakefile`.
65
+ spec.required_ruby_version = ">= 3.3"
66
+
67
+ # intentionally skipping rb_sys gem because newer Rubygems will be present
68
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wreq
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.3
5
+ platform: x64-mingw-ucrt
6
+ authors:
7
+ - SearchApi
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies: []
12
+ description: An easy and powerful Ruby HTTP client with advanced browser fingerprinting
13
+ that accurately emulates Chrome, Edge, Firefox, Safari, Opera, and OkHttp with precise
14
+ TLS/HTTP2 signatures. Powered by wreq (Rust) and BoringSSL.
15
+ email:
16
+ - support@searchapi.io
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - Cargo.lock
22
+ - Cargo.toml
23
+ - Gemfile
24
+ - LICENSE
25
+ - README.md
26
+ - Rakefile
27
+ - build.rs
28
+ - docs/windows-gnu-tokio-crash.md
29
+ - examples/body.rb
30
+ - examples/client.rb
31
+ - examples/cookie.rb
32
+ - examples/emulate_request.rb
33
+ - examples/headers.rb
34
+ - examples/proxy.rb
35
+ - examples/send_stream.rb
36
+ - examples/stream.rb
37
+ - examples/thread_interrupt.rb
38
+ - extconf.rb
39
+ - lib/wreq.rb
40
+ - lib/wreq_ruby/3.3/wreq_ruby.so
41
+ - lib/wreq_ruby/3.4/wreq_ruby.so
42
+ - lib/wreq_ruby/4.0/wreq_ruby.so
43
+ - lib/wreq_ruby/body.rb
44
+ - lib/wreq_ruby/client.rb
45
+ - lib/wreq_ruby/cookie.rb
46
+ - lib/wreq_ruby/emulate.rb
47
+ - lib/wreq_ruby/error.rb
48
+ - lib/wreq_ruby/header.rb
49
+ - lib/wreq_ruby/http.rb
50
+ - lib/wreq_ruby/response.rb
51
+ - script/build_platform_gem.rb
52
+ - script/build_windows_gnu.ps1
53
+ - src/arch.rs
54
+ - src/client.rs
55
+ - src/client/body.rs
56
+ - src/client/body/form.rs
57
+ - src/client/body/json.rs
58
+ - src/client/body/stream.rs
59
+ - src/client/param.rs
60
+ - src/client/query.rs
61
+ - src/client/req.rs
62
+ - src/client/resp.rs
63
+ - src/cookie.rs
64
+ - src/emulate.rs
65
+ - src/error.rs
66
+ - src/extractor.rs
67
+ - src/gvl.rs
68
+ - src/header.rs
69
+ - src/http.rs
70
+ - src/lib.rs
71
+ - src/macros.rs
72
+ - src/rt.rs
73
+ - test/client_cookie_test.rb
74
+ - test/client_test.rb
75
+ - test/cookie_test.rb
76
+ - test/emulation_test.rb
77
+ - test/error_handling_test.rb
78
+ - test/header_test.rb
79
+ - test/inspect_test.rb
80
+ - test/module_methods_test.rb
81
+ - test/orig_header_test.rb
82
+ - test/request_parameters_test.rb
83
+ - test/request_test.rb
84
+ - test/response_test.rb
85
+ - test/stream_test.rb
86
+ - test/test_helper.rb
87
+ - wreq.gemspec
88
+ homepage: https://github.com/SearchApi/wreq-ruby
89
+ licenses:
90
+ - Apache-2.0
91
+ metadata:
92
+ bug_tracker_uri: https://github.com/SearchApi/wreq-ruby/issues
93
+ changelog_uri: https://github.com/SearchApi/wreq-ruby/releases
94
+ documentation_uri: https://github.com/SearchApi/wreq-ruby#readme
95
+ homepage_uri: https://github.com/SearchApi/wreq-ruby
96
+ source_code_uri: https://github.com/SearchApi/wreq-ruby
97
+ rubygems_mfa_required: 'true'
98
+ rdoc_options:
99
+ - "--exclude"
100
+ - Cargo\..*
101
+ - "--exclude"
102
+ - "\\.rs$"
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '3.3'
110
+ - - "<"
111
+ - !ruby/object:Gem::Version
112
+ version: 4.1.dev
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements:
119
+ - Rust >= 1.85
120
+ rubygems_version: 4.0.10
121
+ specification_version: 4
122
+ summary: Ruby bindings for wreq, an HTTP client with TLS/HTTP2 browser fingerprinting
123
+ test_files: []