wreq 1.0.0

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 (59) hide show
  1. checksums.yaml +7 -0
  2. data/Cargo.toml +54 -0
  3. data/Gemfile +17 -0
  4. data/LICENSE +201 -0
  5. data/README.md +150 -0
  6. data/Rakefile +90 -0
  7. data/build.rs +9 -0
  8. data/examples/body.rb +42 -0
  9. data/examples/client.rb +33 -0
  10. data/examples/emulation_request.rb +37 -0
  11. data/examples/headers.rb +27 -0
  12. data/examples/proxy.rb +113 -0
  13. data/examples/send_stream.rb +85 -0
  14. data/examples/stream.rb +14 -0
  15. data/examples/thread_interrupt.rb +83 -0
  16. data/extconf.rb +7 -0
  17. data/lib/wreq.rb +313 -0
  18. data/lib/wreq_ruby/body.rb +36 -0
  19. data/lib/wreq_ruby/client.rb +516 -0
  20. data/lib/wreq_ruby/cookie.rb +144 -0
  21. data/lib/wreq_ruby/emulation.rb +186 -0
  22. data/lib/wreq_ruby/error.rb +159 -0
  23. data/lib/wreq_ruby/header.rb +197 -0
  24. data/lib/wreq_ruby/http.rb +132 -0
  25. data/lib/wreq_ruby/response.rb +208 -0
  26. data/script/build_platform_gem.rb +34 -0
  27. data/src/client/body/form.rs +2 -0
  28. data/src/client/body/json.rs +16 -0
  29. data/src/client/body/stream.rs +148 -0
  30. data/src/client/body.rs +57 -0
  31. data/src/client/param.rs +19 -0
  32. data/src/client/query.rs +2 -0
  33. data/src/client/req.rs +251 -0
  34. data/src/client/resp.rs +250 -0
  35. data/src/client.rs +392 -0
  36. data/src/cookie.rs +277 -0
  37. data/src/emulation.rs +317 -0
  38. data/src/error.rs +147 -0
  39. data/src/extractor.rs +199 -0
  40. data/src/gvl.rs +154 -0
  41. data/src/header.rs +177 -0
  42. data/src/http.rs +127 -0
  43. data/src/lib.rs +97 -0
  44. data/src/macros.rs +118 -0
  45. data/src/rt.rs +47 -0
  46. data/test/client_cookie_test.rb +46 -0
  47. data/test/client_test.rb +136 -0
  48. data/test/cookie_test.rb +166 -0
  49. data/test/emulation_test.rb +21 -0
  50. data/test/error_handling_test.rb +89 -0
  51. data/test/header_test.rb +290 -0
  52. data/test/module_methods_test.rb +75 -0
  53. data/test/request_parameters_test.rb +175 -0
  54. data/test/request_test.rb +234 -0
  55. data/test/response_test.rb +69 -0
  56. data/test/stream_test.rb +81 -0
  57. data/test/test_helper.rb +9 -0
  58. data/wreq.gemspec +68 -0
  59. metadata +112 -0
data/examples/proxy.rb ADDED
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/wreq"
4
+
5
+ # Proxy templates:
6
+ # HTTP/HTTPS proxy: http://127.0.0.1:6152
7
+ # SOCKS5 proxy: socks5://127.0.0.1:6153
8
+
9
+ puts "=" * 60
10
+ puts "Wreq Ruby Proxy Examples"
11
+ puts "=" * 60
12
+
13
+ # ==============================================================================
14
+ # Example 1: Basic HTTP Proxy
15
+ # ==============================================================================
16
+ puts "\n--- Example 1: Basic HTTP Proxy ---"
17
+ begin
18
+ client = Wreq::Client.new(
19
+ user_agent: "WreqClient/1.0",
20
+ proxy: "http://127.0.0.1:6152"
21
+ )
22
+ puts "✅ Client with HTTP proxy created"
23
+
24
+ response = client.get("https://httpbin.io/ip")
25
+ puts "Status: #{response.code}"
26
+ puts "Response: #{response.text}"
27
+ rescue Wreq::RequestError => e
28
+ puts "❌ Request failed: #{e.message}"
29
+ rescue => e
30
+ puts "❌ Error: #{e.class} - #{e.message}"
31
+ end
32
+
33
+ # ==============================================================================
34
+ # Example 2: SOCKS5 Proxy
35
+ # ==============================================================================
36
+ puts "\n--- Example 2: SOCKS5 Proxy ---"
37
+ begin
38
+ client = Wreq::Client.new(
39
+ user_agent: "WreqClient/1.0",
40
+ proxy: "socks5://127.0.0.1:6153"
41
+ )
42
+ puts "✅ Client with SOCKS5 proxy created"
43
+
44
+ response = client.get("https://httpbin.io/ip")
45
+ puts "Status: #{response.code}"
46
+ puts "Response: #{response.text}"
47
+ rescue Wreq::RequestError => e
48
+ puts "❌ Request failed: #{e.message}"
49
+ rescue => e
50
+ puts "❌ Error: #{e.class} - #{e.message}"
51
+ end
52
+
53
+ # ==============================================================================
54
+ # Example 3: SOCKS5h Proxy (DNS resolution through proxy)
55
+ # ==============================================================================
56
+ puts "\n--- Example 3: SOCKS5h Proxy (Remote DNS) ---"
57
+ begin
58
+ client = Wreq::Client.new(
59
+ user_agent: "WreqClient/1.0",
60
+ proxy: "socks5h://127.0.0.1:6153"
61
+ )
62
+ puts "✅ Client with SOCKS5h proxy created (DNS resolved by proxy)"
63
+
64
+ response = client.get("https://httpbin.io/ip")
65
+ puts "Status: #{response.code}"
66
+ puts "Response: #{response.text}"
67
+ rescue Wreq::RequestError => e
68
+ puts "❌ Request failed: #{e.message}"
69
+ rescue => e
70
+ puts "❌ Error: #{e.class} - #{e.message}"
71
+ end
72
+
73
+ # ==============================================================================
74
+ # Example 4: HTTP Proxy with Authentication
75
+ # ==============================================================================
76
+ puts "\n--- Example 4: HTTP Proxy with Authentication ---"
77
+ begin
78
+ # Format: http://username:password@host:port
79
+ client = Wreq::Client.new(
80
+ user_agent: "WreqClient/1.0",
81
+ proxy: "http://user:pass@127.0.0.1:6152"
82
+ )
83
+ puts "✅ Client with authenticated HTTP proxy created"
84
+
85
+ response = client.get("https://httpbin.io/ip")
86
+ puts "Status: #{response.code}"
87
+ puts "Response: #{response.text}"
88
+ rescue Wreq::RequestError => e
89
+ puts "❌ Request failed: #{e.message}"
90
+ rescue => e
91
+ puts "❌ Error: #{e.class} - #{e.message}"
92
+ end
93
+
94
+ # ==============================================================================
95
+ # Example 5: SOCKS5 Proxy with Authentication
96
+ # ==============================================================================
97
+ puts "\n--- Example 5: SOCKS5 Proxy with Authentication ---"
98
+ begin
99
+ # Format: socks5://username:password@host:port
100
+ client = Wreq::Client.new(
101
+ user_agent: "WreqClient/1.0",
102
+ proxy: "socks5://user:pass@127.0.0.1:6153"
103
+ )
104
+ puts "✅ Client with authenticated SOCKS5 proxy created"
105
+
106
+ response = client.get("https://httpbin.io/ip")
107
+ puts "Status: #{response.code}"
108
+ puts "Response: #{response.text}"
109
+ rescue Wreq::RequestError => e
110
+ puts "❌ Request failed: #{e.message}"
111
+ rescue => e
112
+ puts "❌ Error: #{e.class} - #{e.message}"
113
+ end
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/wreq"
4
+ require "json"
5
+ require "tmpdir"
6
+
7
+ # Helpers
8
+ ENDPOINT = ENV["WREQ_ECHO_URL"] || "https://httpbin.io/post"
9
+ CHUNK = 64 * 1024
10
+
11
+ def example1_simple_push
12
+ puts "\n=== Example 1: Simple push ==="
13
+ client = Wreq::Client.new
14
+ us = Wreq::BodySender.new(8)
15
+
16
+ producer = Thread.new do
17
+ 5.times do |i|
18
+ us.push("chunk-#{i}\n")
19
+ sleep 0.05
20
+ end
21
+ us.close
22
+ end
23
+
24
+ resp = client.post(ENDPOINT, body: us, headers: {"Content-Type" => "text/plain"})
25
+ body = resp.json
26
+ data = body["data"] || body["json"].to_json
27
+ puts "Echoed bytes: #{data.bytesize}"
28
+ producer.join
29
+ end
30
+
31
+ def example2_file_stream
32
+ puts "\n=== Example 2: File streaming ==="
33
+ client = Wreq::Client.new
34
+ us = Wreq::BodySender.new(16)
35
+
36
+ # Prepare a temp file (~250KB)
37
+ path = File.join(Dir.tmpdir, "wreq_upload_sample.bin")
38
+ File.binwrite(path, Random.new.bytes(2_500_00))
39
+
40
+ total = 0
41
+ producer = Thread.new do
42
+ File.open(path, "rb") do |f|
43
+ while (chunk = f.read(CHUNK))
44
+ total += chunk.bytesize
45
+ us.push(chunk)
46
+ end
47
+ end
48
+ us.close
49
+ end
50
+
51
+ resp = client.post(ENDPOINT, body: us, headers: {"Content-Type" => "application/octet-stream"})
52
+ json = resp.json
53
+ echoed = (json["headers"] && json["headers"]["Content-Length"]) || (json["data"] || "").bytesize
54
+ puts "Sent bytes ~#{total}, echoed length: #{echoed}"
55
+ producer.join
56
+ ensure
57
+ File.delete(path) if path && File.exist?(path)
58
+ end
59
+
60
+ def example3_background_producer
61
+ puts "\n=== Example 3: Background thread producer ==="
62
+ client = Wreq::Client.new
63
+ us = Wreq::BodySender.new(4)
64
+
65
+ # Simulate streaming generation
66
+ producer = Thread.new do
67
+ (1..20).each do |i|
68
+ us.push("data-#{i},")
69
+ sleep 0.01
70
+ end
71
+ us.close
72
+ end
73
+
74
+ resp = client.post(ENDPOINT, body: us)
75
+ json = resp.json
76
+ data = json["data"] || ""
77
+ puts "Received length: #{data.bytesize}"
78
+ producer.join
79
+ end
80
+
81
+ if __FILE__ == $0
82
+ example1_simple_push
83
+ example2_file_stream
84
+ example3_background_producer
85
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/wreq"
4
+
5
+ # Make a request
6
+ client = Wreq::Client.new
7
+ response = client.get("https://httpbin.io/stream/20")
8
+
9
+ # Get the streaming body receiver
10
+ puts "\n=== Streaming Response Body ==="
11
+ response.chunks do |chunk|
12
+ puts chunk
13
+ sleep 0.1 # Simulate processing time
14
+ end
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Tests Thread.kill interrupt support for wreq HTTP operations.
4
+ # All blocking operations should respond to thread interruption.
5
+
6
+ require_relative "../lib/wreq"
7
+
8
+ HANGING_URL = "http://10.255.255.1:12345/" # Non-routable, hangs forever
9
+ SLOW_BODY_URL = "https://httpbin.io/drip?duration=5&numbytes=5" # 5s slow body
10
+
11
+ def test_interrupt(name, kill_after: 2, max_wait: 5)
12
+ print "#{name}: "
13
+
14
+ start = Time.now
15
+ thread = Thread.new { yield }
16
+
17
+ sleep kill_after
18
+ thread.kill
19
+ killed = thread.join(max_wait)
20
+
21
+ elapsed = Time.now - start
22
+
23
+ if killed && elapsed < (kill_after + max_wait)
24
+ puts "PASS (killed in #{elapsed.round(1)}s)"
25
+ :pass
26
+ else
27
+ puts "FAIL (still alive after #{elapsed.round(1)}s)"
28
+ begin
29
+ Thread.kill(thread)
30
+ rescue
31
+ nil
32
+ end
33
+ :fail
34
+ end
35
+ end
36
+
37
+ puts "Thread Interrupt Test"
38
+ puts "=" * 40
39
+
40
+ results = []
41
+
42
+ # Test 1: Connection phase (non-routable IP)
43
+ results << test_interrupt("Connect phase") {
44
+ begin
45
+ Wreq.get(HANGING_URL)
46
+ rescue
47
+ nil
48
+ end
49
+ }
50
+
51
+ # Test 2: Connection phase with timeout
52
+ results << test_interrupt("Connect + timeout") {
53
+ begin
54
+ Wreq.get(HANGING_URL, timeout: 60)
55
+ rescue
56
+ nil
57
+ end
58
+ }
59
+
60
+ # Test 3: Body reading phase (slow drip endpoint)
61
+ results << test_interrupt("Body reading") {
62
+ resp = Wreq.get(SLOW_BODY_URL)
63
+ begin
64
+ resp.text
65
+ rescue
66
+ nil
67
+ end
68
+ }
69
+
70
+ # Test 4: Body streaming phase
71
+ results << test_interrupt("Body streaming") {
72
+ resp = Wreq.get(SLOW_BODY_URL)
73
+ begin
74
+ resp.chunks { |chunk| chunk }
75
+ rescue
76
+ nil
77
+ end
78
+ }
79
+
80
+ puts "=" * 40
81
+ passed = results.count(:pass)
82
+ puts "#{passed}/#{results.size} tests passed"
83
+ exit(results.all?(:pass) ? 0 : 1)
data/extconf.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "mkmf"
2
+ # We use rb_sys for makefile generation only.
3
+ # We can use `RB_SYS_CARGO_PROFILE` to choose Cargo profile
4
+ # Read more https://github.com/oxidize-rb/rb-sys/blob/main/gem/README.md
5
+ require "rb_sys/mkmf"
6
+
7
+ create_rust_makefile("wreq_ruby/wreq_ruby")
data/lib/wreq.rb ADDED
@@ -0,0 +1,313 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ RUBY_VERSION =~ /(\d+\.\d+)/
5
+ require_relative "wreq_ruby/#{$1}/wreq_ruby"
6
+ rescue LoadError
7
+ require_relative "wreq_ruby/wreq_ruby"
8
+ end
9
+
10
+ # Load type hint definitions
11
+ require_relative "wreq_ruby/http"
12
+ require_relative "wreq_ruby/client"
13
+ require_relative "wreq_ruby/response"
14
+ require_relative "wreq_ruby/body"
15
+ require_relative "wreq_ruby/header"
16
+ require_relative "wreq_ruby/error"
17
+ require_relative "wreq_ruby/cookie"
18
+
19
+ unless defined?(Wreq)
20
+ module Wreq
21
+ VERSION = nil
22
+
23
+ # Send an HTTP request.
24
+ #
25
+ # @param method [Wreq::Method] HTTP method to use
26
+ # @param url [String] Target URL
27
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
28
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
29
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
30
+ # @param query [Hash, nil] URL query parameters
31
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
32
+ # @param json [Object, nil] JSON body (will be serialized)
33
+ # @param body [String, IO, nil] Raw request body (string or stream)
34
+ # @param auth [String, nil] Authorization header value
35
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
36
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
37
+ # @param cookies [Array<String>, nil] Cookies to send
38
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
39
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
40
+ # @param gzip [Boolean, nil] Enable gzip compression
41
+ # @param brotli [Boolean, nil] Enable Brotli compression
42
+ # @param deflate [Boolean, nil] Enable deflate compression
43
+ # @param zstd [Boolean, nil] Enable Zstandard compression
44
+ # @param timeout [Integer, nil] Total request timeout (seconds)
45
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
46
+ # @param proxy [String, nil] Proxy server URI
47
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
48
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
49
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
50
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
51
+ # @param version [Wreq::Version, nil] HTTP version to use
52
+ # @return [Wreq::Response] HTTP response
53
+ def self.request(method, url, **options)
54
+ end
55
+
56
+ # Send an HTTP GET request.
57
+ #
58
+ # @param url [String] Target URL
59
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
60
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
61
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
62
+ # @param query [Hash, nil] URL query parameters
63
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
64
+ # @param json [Object, nil] JSON body (will be serialized)
65
+ # @param body [String, IO, nil] Raw request body (string or stream)
66
+ # @param auth [String, nil] Authorization header value
67
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
68
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
69
+ # @param cookies [Array<String>, nil] Cookies to send
70
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
71
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
72
+ # @param gzip [Boolean, nil] Enable gzip compression
73
+ # @param brotli [Boolean, nil] Enable Brotli compression
74
+ # @param deflate [Boolean, nil] Enable deflate compression
75
+ # @param zstd [Boolean, nil] Enable Zstandard compression
76
+ # @param timeout [Integer, nil] Total request timeout (seconds)
77
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
78
+ # @param proxy [String, nil] Proxy server URI
79
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
80
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
81
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
82
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
83
+ # @param version [Wreq::Version, nil] HTTP version to use
84
+ # @return [Wreq::Response] HTTP response
85
+ def self.get(url, **options)
86
+ end
87
+
88
+ # Send an HTTP HEAD request.
89
+ #
90
+ # @param url [String] Target URL
91
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
92
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
93
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
94
+ # @param query [Hash, nil] URL query parameters
95
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
96
+ # @param json [Object, nil] JSON body (will be serialized)
97
+ # @param body [String, IO, nil] Raw request body (string or stream)
98
+ # @param auth [String, nil] Authorization header value
99
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
100
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
101
+ # @param cookies [Array<String>, nil] Cookies to send
102
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
103
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
104
+
105
+ # @param gzip [Boolean, nil] Enable gzip compression
106
+ # @param brotli [Boolean, nil] Enable Brotli compression
107
+ # @param deflate [Boolean, nil] Enable deflate compression
108
+ # @param zstd [Boolean, nil] Enable Zstandard compression
109
+ # @param timeout [Integer, nil] Total request timeout (seconds)
110
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
111
+ # @param proxy [String, nil] Proxy server URI
112
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
113
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
114
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
115
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
116
+ # @param version [Wreq::Version, nil] HTTP version to use
117
+ # @return [Wreq::Response] HTTP response
118
+ def self.head(url, **options)
119
+ end
120
+
121
+ # Send an HTTP POST request.
122
+ #
123
+ # @param url [String] Target URL
124
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
125
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
126
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
127
+ # @param query [Hash, nil] URL query parameters
128
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
129
+ # @param json [Object, nil] JSON body (will be serialized)
130
+ # @param body [String, IO, nil] Raw request body (string or stream)
131
+ # @param auth [String, nil] Authorization header value
132
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
133
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
134
+ # @param cookies [Array<String>, nil] Cookies to send
135
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
136
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
137
+ # @param gzip [Boolean, nil] Enable gzip compression
138
+ # @param brotli [Boolean, nil] Enable Brotli compression
139
+ # @param deflate [Boolean, nil] Enable deflate compression
140
+ # @param zstd [Boolean, nil] Enable Zstandard compression
141
+ # @param timeout [Integer, nil] Total request timeout (seconds)
142
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
143
+ # @param proxy [String, nil] Proxy server URI
144
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
145
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
146
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
147
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
148
+ # @param version [Wreq::Version, nil] HTTP version to use
149
+ # @return [Wreq::Response] HTTP response
150
+ def self.post(url, **options)
151
+ end
152
+
153
+ # Send an HTTP PUT request.
154
+ #
155
+ # @param url [String] Target URL
156
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
157
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
158
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
159
+ # @param query [Hash, nil] URL query parameters
160
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
161
+ # @param json [Object, nil] JSON body (will be serialized)
162
+ # @param body [String, IO, nil] Raw request body (string or stream)
163
+ # @param auth [String, nil] Authorization header value
164
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
165
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
166
+ # @param cookies [Array<String>, nil] Cookies to send
167
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
168
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
169
+ # @param gzip [Boolean, nil] Enable gzip compression
170
+ # @param brotli [Boolean, nil] Enable Brotli compression
171
+ # @param deflate [Boolean, nil] Enable deflate compression
172
+ # @param zstd [Boolean, nil] Enable Zstandard compression
173
+ # @param timeout [Integer, nil] Total request timeout (seconds)
174
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
175
+ # @param proxy [String, nil] Proxy server URI
176
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
177
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
178
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
179
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
180
+ # @param version [Wreq::Version, nil] HTTP version to use
181
+ # @return [Wreq::Response] HTTP response
182
+ def self.put(url, **options)
183
+ end
184
+
185
+ # Send an HTTP DELETE request.
186
+ #
187
+ # @param url [String] Target URL
188
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
189
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
190
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
191
+ # @param query [Hash, nil] URL query parameters
192
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
193
+ # @param json [Object, nil] JSON body (will be serialized)
194
+ # @param body [String, IO, nil] Raw request body (string or stream)
195
+ # @param auth [String, nil] Authorization header value
196
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
197
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
198
+ # @param cookies [Array<String>, nil] Cookies to send
199
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
200
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
201
+ # @param gzip [Boolean, nil] Enable gzip compression
202
+ # @param brotli [Boolean, nil] Enable Brotli compression
203
+ # @param deflate [Boolean, nil] Enable deflate compression
204
+ # @param zstd [Boolean, nil] Enable Zstandard compression
205
+ # @param timeout [Integer, nil] Total request timeout (seconds)
206
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
207
+ # @param proxy [String, nil] Proxy server URI
208
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
209
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
210
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
211
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
212
+ # @param version [Wreq::Version, nil] HTTP version to use
213
+ # @return [Wreq::Response] HTTP response
214
+ def self.delete(url, **options)
215
+ end
216
+
217
+ # Send an HTTP OPTIONS request.
218
+ #
219
+ # @param url [String] Target URL
220
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
221
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
222
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
223
+ # @param query [Hash, nil] URL query parameters
224
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
225
+ # @param json [Object, nil] JSON body (will be serialized)
226
+ # @param body [String, IO, nil] Raw request body (string or stream)
227
+ # @param auth [String, nil] Authorization header value
228
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
229
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
230
+ # @param cookies [Array<String>, nil] Cookies to send
231
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
232
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
233
+ # @param gzip [Boolean, nil] Enable gzip compression
234
+ # @param brotli [Boolean, nil] Enable Brotli compression
235
+ # @param deflate [Boolean, nil] Enable deflate compression
236
+ # @param zstd [Boolean, nil] Enable Zstandard compression
237
+ # @param timeout [Integer, nil] Total request timeout (seconds)
238
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
239
+ # @param proxy [String, nil] Proxy server URI
240
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
241
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
242
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
243
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
244
+ # @param version [Wreq::Version, nil] HTTP version to use
245
+ # @return [Wreq::Response] HTTP response
246
+ def self.options(url, **options)
247
+ end
248
+
249
+ # Send an HTTP TRACE request.
250
+ #
251
+ # @param url [String] Target URL
252
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
253
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
254
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
255
+ # @param query [Hash, nil] URL query parameters
256
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
257
+ # @param json [Object, nil] JSON body (will be serialized)
258
+ # @param body [String, IO, nil] Raw request body (string or stream)
259
+ # @param auth [String, nil] Authorization header value
260
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
261
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
262
+ # @param cookies [Array<String>, nil] Cookies to send
263
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
264
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
265
+ # @param gzip [Boolean, nil] Enable gzip compression
266
+ # @param brotli [Boolean, nil] Enable Brotli compression
267
+ # @param deflate [Boolean, nil] Enable deflate compression
268
+ # @param zstd [Boolean, nil] Enable Zstandard compression
269
+ # @param timeout [Integer, nil] Total request timeout (seconds)
270
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
271
+ # @param proxy [String, nil] Proxy server URI
272
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
273
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
274
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
275
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
276
+ # @param version [Wreq::Version, nil] HTTP version to use
277
+ # @return [Wreq::Response] HTTP response
278
+ def self.trace(url, **options)
279
+ end
280
+
281
+ # Send an HTTP PATCH request.
282
+ #
283
+ # @param url [String] Target URL
284
+ # @param headers [Hash{String=>String}, nil] Custom headers for this request
285
+ # @param orig_headers [Hash{String=>String}, nil] Original headers (raw, unmodified)
286
+ # @param default_headers [Hash{String=>String}, nil] Default headers to merge
287
+ # @param query [Hash, nil] URL query parameters
288
+ # @param form [Hash{String=>String}, nil] Form data (application/x-www-form-urlencoded)
289
+ # @param json [Object, nil] JSON body (will be serialized)
290
+ # @param body [String, IO, nil] Raw request body (string or stream)
291
+ # @param auth [String, nil] Authorization header value
292
+ # @param bearer_auth [String, nil] Bearer token for Authorization header
293
+ # @param basic_auth [Array<String>, nil] Username and password for basic auth
294
+ # @param cookies [Array<String>, nil] Cookies to send
295
+ # @param allow_redirects [Boolean, nil] Whether to follow redirects
296
+ # @param max_redirects [Integer, nil] Maximum number of redirects to follow
297
+ # @param gzip [Boolean, nil] Enable gzip compression
298
+ # @param brotli [Boolean, nil] Enable Brotli compression
299
+ # @param deflate [Boolean, nil] Enable deflate compression
300
+ # @param zstd [Boolean, nil] Enable Zstandard compression
301
+ # @param timeout [Integer, nil] Total request timeout (seconds)
302
+ # @param read_timeout [Integer, nil] Per-chunk read timeout (seconds)
303
+ # @param proxy [String, nil] Proxy server URI
304
+ # @param no_proxy [Boolean, nil] Disable proxy for this request
305
+ # @param local_address [String, nil] Bind the client's local source IP address (IPv4/IPv6). Useful on multi-homed hosts to originate connections from a specific address or enforce source routing. Examples: "192.168.1.10", "10.0.0.5", "2001:db8::1". The address must exist on the host and be routable or the connection may fail.
306
+ # @param interface [String, nil] Bind the socket to a specific network interface via `SO_BINDTODEVICE` (e.g., "eth0", "wlan0", "tun0"). Effective only on systems that support the option (Linux/Android/Fuchsia) and typically requires privileges (root or CAP_NET_ADMIN).
307
+ # @param emulation [Wreq::Emulation, nil] Device/OS emulation for this request
308
+ # @param version [Wreq::Version, nil] HTTP version to use
309
+ # @return [Wreq::Response] HTTP response
310
+ def self.patch(url, **options)
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ unless defined?(Wreq)
4
+ module Wreq
5
+ # BodySender: for streaming request bodies, allowing thread-safe chunked data push.
6
+ # Backed by a Rust channel, avoids buffering the entire payload in memory.
7
+ #
8
+ # Supports multi-threaded chunk push: you can safely call `push` from multiple threads.
9
+ #
10
+ # Usage:
11
+ # sender = Wreq::BodySender.new(8)
12
+ # Thread.new do
13
+ # File.open('big.bin', 'rb') { |f| while (chunk = f.read(65536)); sender.push(chunk); end }
14
+ # sender.close
15
+ # end
16
+ # resp = client.post(url, body: sender)
17
+ #
18
+ # Note:
19
+ # - Sender is for request upload only, not for response reading.
20
+ # - Each BodySender instance can only be used once (single-use):
21
+ # after being consumed by a request, further push or reuse is not allowed.
22
+ class BodySender
23
+ # @param capacity [Integer] channel buffer size, default 8
24
+ def self.new(capacity = 8)
25
+ end
26
+
27
+ # @param data [String] binary chunk
28
+ def push(data)
29
+ end
30
+
31
+ # Close the sender, signaling end of data.
32
+ def close
33
+ end
34
+ end
35
+ end
36
+ end