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
@@ -0,0 +1,290 @@
1
+ require "test_helper"
2
+
3
+ class HeadersTest < Minitest::Test
4
+ def setup
5
+ @response = Wreq.get("http://localhost:8080/response-headers",
6
+ query: {
7
+ "X-Custom-Header" => "custom-value",
8
+ "X-Multi-Header" => "value1"
9
+ })
10
+ @headers = @response.headers
11
+ end
12
+
13
+ def test_headers_class
14
+ assert_instance_of Wreq::Headers, @headers
15
+ end
16
+
17
+ def test_initialize
18
+ headers = Wreq::Headers.new
19
+ assert_instance_of Wreq::Headers, headers
20
+ assert headers.empty?
21
+ assert_equal 0, headers.length
22
+ end
23
+
24
+ def test_get_existing_header
25
+ # Content-Type should exist in response
26
+ content_type = @headers.get("Content-Type")
27
+ assert_instance_of String, content_type
28
+ refute_nil content_type
29
+ end
30
+
31
+ def test_get_case_insensitive
32
+ # Test case-insensitive lookup
33
+ value1 = @headers.get("content-type")
34
+ value2 = @headers.get("Content-Type")
35
+ value3 = @headers.get("CONTENT-TYPE")
36
+
37
+ assert_equal value1, value2
38
+ assert_equal value2, value3
39
+ end
40
+
41
+ def test_get_nonexistent_header
42
+ result = @headers.get("X-Nonexistent-Header-12345")
43
+ assert_nil result
44
+ end
45
+
46
+ def test_get_all_single_value
47
+ # Most headers have single values
48
+ values = @headers.get_all("Content-Type")
49
+ assert_instance_of Array, values
50
+ assert_equal 1, values.length
51
+ assert_equal @headers.get("Content-Type"), values.first
52
+ end
53
+
54
+ def test_get_all_nonexistent
55
+ values = @headers.get_all("X-Nonexistent-Header")
56
+ assert_instance_of Array, values
57
+ assert_equal 0, values.length
58
+ assert_empty values
59
+ end
60
+
61
+ def test_set_new_header
62
+ headers = Wreq::Headers.new
63
+ headers.set("X-Test-Header", "test-value")
64
+
65
+ assert_equal "test-value", headers.get("X-Test-Header")
66
+ assert_equal 1, headers.length
67
+ end
68
+
69
+ def test_set_replaces_existing
70
+ headers = Wreq::Headers.new
71
+ headers.set("X-Test", "value1")
72
+ headers.set("X-Test", "value2")
73
+
74
+ assert_equal "value2", headers.get("X-Test")
75
+ values = headers.get_all("X-Test")
76
+ assert_equal 1, values.length
77
+ assert_equal "value2", values.first
78
+ end
79
+
80
+ def test_append_to_new_header
81
+ headers = Wreq::Headers.new
82
+ headers.append("Accept", "application/json")
83
+
84
+ assert_equal "application/json", headers.get("Accept")
85
+ end
86
+
87
+ def test_append_to_existing_header
88
+ headers = Wreq::Headers.new
89
+ headers.set("Accept", "application/json")
90
+ headers.append("Accept", "text/html")
91
+ headers.append("Accept", "application/xml")
92
+
93
+ values = headers.get_all("Accept")
94
+ assert_equal 3, values.length
95
+ assert_includes values, "application/json"
96
+ assert_includes values, "text/html"
97
+ assert_includes values, "application/xml"
98
+ end
99
+
100
+ def test_remove_existing_header
101
+ headers = Wreq::Headers.new
102
+ headers.set("X-Remove-Me", "value")
103
+
104
+ removed_value = headers.remove("X-Remove-Me")
105
+ assert_equal "value", removed_value
106
+ assert_nil headers.get("X-Remove-Me")
107
+ end
108
+
109
+ def test_remove_nonexistent_header
110
+ headers = Wreq::Headers.new
111
+ result = headers.remove("X-Nonexistent")
112
+ assert_nil result
113
+ end
114
+
115
+ def test_delete_alias
116
+ headers = Wreq::Headers.new
117
+ headers.set("X-Delete-Me", "value")
118
+
119
+ removed_value = headers.remove("X-Delete-Me")
120
+ assert_equal "value", removed_value
121
+ assert_nil headers.get("X-Delete-Me")
122
+ end
123
+
124
+ def test_contains_existing
125
+ assert @headers.contains?("Content-Type")
126
+ end
127
+
128
+ def test_contains_nonexistent
129
+ refute @headers.contains?("X-Nonexistent-Header-12345")
130
+ end
131
+
132
+ def test_contains_case_insensitive
133
+ # If Content-Type exists
134
+ if @headers.contains?("Content-Type")
135
+ assert @headers.contains?("content-type")
136
+ assert @headers.contains?("CONTENT-TYPE")
137
+ end
138
+ end
139
+
140
+ def test_key_alias
141
+ # key? is an alias for contains?
142
+ assert_equal @headers.contains?("Content-Type"), @headers.key?("Content-Type")
143
+ end
144
+
145
+ def test_length
146
+ headers = Wreq::Headers.new
147
+ assert_equal 0, headers.length
148
+
149
+ headers.set("Header1", "value1")
150
+ assert_equal 1, headers.length
151
+
152
+ headers.set("Header2", "value2")
153
+ assert_equal 2, headers.length
154
+
155
+ # Setting same header shouldn't increase length
156
+ headers.set("Header1", "new-value")
157
+ assert_equal 2, headers.length
158
+ end
159
+
160
+ def test_empty_on_new_headers
161
+ headers = Wreq::Headers.new
162
+ assert headers.empty?
163
+ end
164
+
165
+ def test_empty_on_headers_with_data
166
+ refute @headers.empty?
167
+ end
168
+
169
+ def test_clear
170
+ headers = Wreq::Headers.new
171
+ headers.set("Header1", "value1")
172
+ headers.set("Header2", "value2")
173
+
174
+ refute headers.empty?
175
+ headers.clear
176
+ assert headers.empty?
177
+ assert_equal 0, headers.length
178
+ end
179
+
180
+ def test_keys
181
+ headers = Wreq::Headers.new
182
+ headers.set("Content-Type", "application/json")
183
+ headers.set("Authorization", "Bearer token")
184
+
185
+ keys = headers.keys
186
+ assert_instance_of Array, keys
187
+ assert_equal 2, keys.length
188
+ assert_includes keys, "content-type"
189
+ assert_includes keys, "authorization"
190
+ end
191
+
192
+ def test_keys_are_lowercase
193
+ headers = Wreq::Headers.new
194
+ headers.set("Content-Type", "text/html")
195
+ headers.set("X-Custom-Header", "value")
196
+
197
+ keys = headers.keys
198
+ keys.each do |key|
199
+ assert_equal key, key.downcase
200
+ end
201
+ end
202
+
203
+ def test_values
204
+ headers = Wreq::Headers.new
205
+ headers.set("Content-Type", "application/json")
206
+ headers.set("Authorization", "Bearer token")
207
+
208
+ values = headers.values
209
+ assert_instance_of Array, values
210
+ assert_equal 2, values.length
211
+ assert_includes values, "application/json"
212
+ assert_includes values, "Bearer token"
213
+ end
214
+
215
+ def test_each_with_block
216
+ headers = Wreq::Headers.new
217
+ headers.set("Header1", "value1")
218
+ headers.set("Header2", "value2")
219
+
220
+ collected = {}
221
+ headers.each do |name, value|
222
+ assert_instance_of String, name
223
+ assert_instance_of String, value
224
+ collected[name] = value
225
+ end
226
+
227
+ assert_equal 2, collected.length
228
+ assert_equal "value1", collected["header1"]
229
+ assert_equal "value2", collected["header2"]
230
+ end
231
+
232
+ def test_multiple_operations_sequence
233
+ headers = Wreq::Headers.new
234
+
235
+ # Add headers
236
+ headers.set("Content-Type", "application/json")
237
+ headers.set("Accept", "application/json")
238
+
239
+ assert_equal 2, headers.length
240
+
241
+ # Append to Accept
242
+ headers.append("Accept", "text/html")
243
+ assert_equal 2, headers.get_all("Accept").length
244
+
245
+ # Clear all
246
+ headers.clear
247
+ assert headers.empty?
248
+ end
249
+
250
+ def test_special_characters_in_header_values
251
+ headers = Wreq::Headers.new
252
+ special_value = "Bearer token-123_abc/xyz+456=789"
253
+ headers.set("Authorization", special_value)
254
+
255
+ assert_equal special_value, headers.get("Authorization")
256
+ end
257
+
258
+ def test_response_headers_integration
259
+ # Test that headers from actual HTTP response work correctly
260
+ assert_instance_of Wreq::Headers, @headers
261
+ refute @headers.empty?
262
+
263
+ # Should have common HTTP headers
264
+ assert @headers.length > 0
265
+ end
266
+
267
+ def test_response_headers_each
268
+ # Test iteration over real response headers
269
+ count = 0
270
+ @headers.each do |name, value|
271
+ assert_instance_of String, name
272
+ assert_instance_of String, value
273
+ count += 1
274
+ end
275
+
276
+ assert count > 0
277
+ assert_equal @headers.length, count
278
+ end
279
+
280
+ def test_headers_immutability_across_instances
281
+ headers1 = Wreq::Headers.new
282
+ headers2 = Wreq::Headers.new
283
+
284
+ headers1.set("X-Test", "value1")
285
+ headers2.set("X-Test", "value2")
286
+
287
+ assert_equal "value1", headers1.get("X-Test")
288
+ assert_equal "value2", headers2.get("X-Test")
289
+ end
290
+ end
@@ -0,0 +1,75 @@
1
+ require "test_helper"
2
+
3
+ class ModuleMethodsTest < Minitest::Test
4
+ def test_module_get
5
+ response = Wreq.get("http://localhost:8080/get")
6
+ refute_nil response
7
+ assert_equal 200, response.code
8
+ end
9
+
10
+ def test_module_post
11
+ response = Wreq.post("http://localhost:8080/post",
12
+ json: {module: "test"})
13
+ refute_nil response
14
+ assert_equal 200, response.code
15
+ end
16
+
17
+ def test_module_put
18
+ response = Wreq.put("http://localhost:8080/put",
19
+ json: {data: "test"})
20
+ refute_nil response
21
+ assert_equal 200, response.code
22
+ end
23
+
24
+ def test_module_delete
25
+ response = Wreq.delete("http://localhost:8080/delete")
26
+ refute_nil response
27
+ assert_equal 200, response.code
28
+ end
29
+
30
+ def test_module_patch
31
+ response = Wreq.patch("http://localhost:8080/patch",
32
+ json: {update: "field"})
33
+ refute_nil response
34
+ assert_equal 200, response.code
35
+ assert_includes response.text, "update"
36
+ assert_includes response.text, "field"
37
+ end
38
+
39
+ def test_module_request_method
40
+ response = Wreq.request(Wreq::Method::GET, "http://localhost:8080/get")
41
+ refute_nil response
42
+ assert_equal 200, response.code
43
+ end
44
+
45
+ def test_module_methods_with_parameters
46
+ response = Wreq.get("http://localhost:8080/get",
47
+ headers: {"Accept" => "application/json"},
48
+ query: {"test" => "module"})
49
+ refute_nil response
50
+ assert_equal response.url, "http://localhost:8080/get?test=module"
51
+ assert_includes response.text, "http://localhost:8080/get?test=module"
52
+ assert_equal 200, response.code
53
+ end
54
+
55
+ def test_module_post_with_json
56
+ response = Wreq.post("http://localhost:8080/post",
57
+ json: {
58
+ string: "test",
59
+ number: 123,
60
+ boolean: true,
61
+ array: [1, 2, 3]
62
+ })
63
+ refute_nil response
64
+ assert_equal 200, response.code
65
+ end
66
+
67
+ def test_module_post_with_form
68
+ response = Wreq.post("http://localhost:8080/post",
69
+ form: {"field1" => "value1", "field2" => "value2"})
70
+ refute_nil response
71
+ assert_equal 200, response.code
72
+ assert_includes response.text, "field1"
73
+ assert_includes response.text, "field2"
74
+ end
75
+ end
@@ -0,0 +1,175 @@
1
+ require "test_helper"
2
+
3
+ class RequestParametersTest < Minitest::Test
4
+ def test_query_parameters
5
+ response = Wreq.get("http://localhost:8080/get",
6
+ query: {
7
+ "string" => "value",
8
+ "number" => "123",
9
+ "boolean" => "true"
10
+ })
11
+ assert_equal 200, response.code
12
+
13
+ json_data = response.json
14
+ args = json_data["args"]
15
+ assert_equal "value", args["string"]
16
+ assert_equal "123", args["number"] # Query params are strings
17
+ assert_equal "true", args["boolean"]
18
+ end
19
+
20
+ def test_headers
21
+ custom_headers = {
22
+ "X-Custom-Header" => "custom-value",
23
+ "User-Agent" => "wreq-ruby-test/1.0",
24
+ "Accept" => "application/json"
25
+ }
26
+
27
+ response = Wreq.get("http://localhost:8080/get", headers: custom_headers)
28
+ assert_equal 200, response.code
29
+
30
+ json_data = response.json
31
+ request_headers = json_data["headers"]
32
+
33
+ assert_equal "custom-value", request_headers["X-Custom-Header"]
34
+ assert_equal "wreq-ruby-test/1.0", request_headers["User-Agent"]
35
+ assert_equal "application/json", request_headers["Accept"]
36
+ end
37
+
38
+ def test_json_body
39
+ json_data = {
40
+ "string" => "test",
41
+ "number" => 42,
42
+ "boolean" => true,
43
+ "array" => [1, 2, 3],
44
+ "object" => {"nested" => "value"}
45
+ }
46
+
47
+ response = Wreq.post("http://localhost:8080/post", json: json_data)
48
+ assert_equal 200, response.code
49
+
50
+ response_data = response.json
51
+ sent_data = response_data["json"]
52
+
53
+ assert_equal "test", sent_data["string"]
54
+ assert_equal 42, sent_data["number"]
55
+ assert_equal true, sent_data["boolean"]
56
+ assert_equal [1, 2, 3], sent_data["array"]
57
+ assert_equal({"nested" => "value"}, sent_data["object"])
58
+ end
59
+
60
+ def test_form_body
61
+ form_data = {
62
+ "field1" => "value1",
63
+ "field2" => "value2",
64
+ "number" => "123"
65
+ }
66
+
67
+ response = Wreq.post("http://localhost:8080/post", form: form_data)
68
+ assert_equal 200, response.code
69
+
70
+ response_data = response.json
71
+ sent_form = response_data["form"]
72
+
73
+ assert_equal "value1", sent_form["field1"]
74
+ assert_equal "value2", sent_form["field2"]
75
+ assert_equal "123", sent_form["number"]
76
+ end
77
+
78
+ def test_combined_parameters
79
+ response = Wreq.post("http://localhost:8080/post",
80
+ query: {"q" => "search"},
81
+ headers: {"X-Test" => "combined"},
82
+ json: {"data" => "payload"})
83
+
84
+ assert_equal 200, response.code
85
+
86
+ json_data = response.json
87
+
88
+ # Check query parameters
89
+ assert_equal "search", json_data["args"]["q"]
90
+
91
+ # Check headers
92
+ assert_equal "combined", json_data["headers"]["X-Test"]
93
+
94
+ # Check JSON body
95
+ assert_equal "payload", json_data["json"]["data"]
96
+ end
97
+
98
+ def test_empty_parameters
99
+ # Test with no additional parameters
100
+ response = Wreq.get("http://localhost:8080/get")
101
+ assert_equal 200, response.code
102
+
103
+ json_data = response.json
104
+ assert_instance_of Hash, json_data["args"]
105
+ assert json_data["args"].empty?
106
+ end
107
+
108
+ def test_special_characters_in_query
109
+ special_data = {
110
+ "space" => "value with spaces",
111
+ "symbols" => "!@#$%^&*()",
112
+ "unicode" => "测试中文",
113
+ "url_chars" => "a=b&c=d"
114
+ }
115
+
116
+ response = Wreq.get("http://localhost:8080/get", query: special_data)
117
+ assert_equal 200, response.code
118
+
119
+ json_data = response.json
120
+ args = json_data["args"]
121
+
122
+ assert_equal "value with spaces", args["space"]
123
+ assert_equal "!@#$%^&*()", args["symbols"]
124
+ assert_equal "测试中文", args["unicode"]
125
+ assert_equal "a=b&c=d", args["url_chars"]
126
+ end
127
+
128
+ def test_nested_json_data
129
+ nested_data = {
130
+ "level1" => {
131
+ "level2" => {
132
+ "level3" => {
133
+ "value" => "deep"
134
+ }
135
+ },
136
+ "array" => [
137
+ {"item" => 1},
138
+ {"item" => 2}
139
+ ]
140
+ }
141
+ }
142
+
143
+ response = Wreq.post("http://localhost:8080/post", json: nested_data)
144
+ assert_equal 200, response.code
145
+
146
+ response_data = response.json
147
+ sent_json = response_data["json"]
148
+
149
+ assert_equal "deep", sent_json["level1"]["level2"]["level3"]["value"]
150
+ assert_equal 1, sent_json["level1"]["array"][0]["item"]
151
+ assert_equal 2, sent_json["level1"]["array"][1]["item"]
152
+ end
153
+
154
+ def test_method_specific_parameters
155
+ methods_and_urls = {
156
+ get: "http://localhost:8080/get",
157
+ post: "http://localhost:8080/post",
158
+ put: "http://localhost:8080/put",
159
+ patch: "http://localhost:8080/patch",
160
+ delete: "http://localhost:8080/delete"
161
+ }
162
+
163
+ methods_and_urls.each do |method, url|
164
+ response = Wreq.send(method, url,
165
+ headers: {"X-Method" => method.to_s},
166
+ query: {"method" => method.to_s})
167
+
168
+ assert_equal 200, response.code, "#{method} request failed"
169
+
170
+ json_data = response.json
171
+ assert_equal method.to_s, json_data["headers"]["X-Method"]
172
+ assert_equal method.to_s, json_data["args"]["method"]
173
+ end
174
+ end
175
+ end