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.
- checksums.yaml +7 -0
- data/Cargo.lock +1687 -0
- data/Cargo.toml +54 -0
- data/Gemfile +18 -0
- data/LICENSE +201 -0
- data/README.md +153 -0
- data/Rakefile +90 -0
- data/build.rs +16 -0
- data/docs/windows-gnu-tokio-crash.md +70 -0
- data/examples/body.rb +42 -0
- data/examples/client.rb +33 -0
- data/examples/cookie.rb +24 -0
- data/examples/emulate_request.rb +37 -0
- data/examples/headers.rb +27 -0
- data/examples/proxy.rb +113 -0
- data/examples/send_stream.rb +85 -0
- data/examples/stream.rb +14 -0
- data/examples/thread_interrupt.rb +83 -0
- data/extconf.rb +7 -0
- data/lib/wreq.rb +303 -0
- data/lib/wreq_ruby/3.3/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/3.4/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/4.0/wreq_ruby.so +0 -0
- data/lib/wreq_ruby/body.rb +36 -0
- data/lib/wreq_ruby/client.rb +526 -0
- data/lib/wreq_ruby/cookie.rb +156 -0
- data/lib/wreq_ruby/emulate.rb +232 -0
- data/lib/wreq_ruby/error.rb +157 -0
- data/lib/wreq_ruby/header.rb +205 -0
- data/lib/wreq_ruby/http.rb +160 -0
- data/lib/wreq_ruby/response.rb +209 -0
- data/script/build_platform_gem.rb +34 -0
- data/script/build_windows_gnu.ps1 +257 -0
- data/src/arch.rs +33 -0
- data/src/client/body/form.rs +2 -0
- data/src/client/body/json.rs +16 -0
- data/src/client/body/stream.rs +146 -0
- data/src/client/body.rs +57 -0
- data/src/client/param.rs +19 -0
- data/src/client/query.rs +2 -0
- data/src/client/req.rs +274 -0
- data/src/client/resp.rs +248 -0
- data/src/client.rs +413 -0
- data/src/cookie.rs +312 -0
- data/src/emulate.rs +376 -0
- data/src/error.rs +163 -0
- data/src/extractor.rs +117 -0
- data/src/gvl.rs +154 -0
- data/src/header.rs +245 -0
- data/src/http.rs +142 -0
- data/src/lib.rs +98 -0
- data/src/macros.rs +123 -0
- data/src/rt.rs +46 -0
- data/test/client_cookie_test.rb +46 -0
- data/test/client_test.rb +136 -0
- data/test/cookie_test.rb +182 -0
- data/test/emulation_test.rb +21 -0
- data/test/error_handling_test.rb +92 -0
- data/test/header_test.rb +290 -0
- data/test/inspect_test.rb +125 -0
- data/test/module_methods_test.rb +75 -0
- data/test/orig_header_test.rb +115 -0
- data/test/request_parameters_test.rb +175 -0
- data/test/request_test.rb +244 -0
- data/test/response_test.rb +69 -0
- data/test/stream_test.rb +397 -0
- data/test/test_helper.rb +52 -0
- data/wreq.gemspec +68 -0
- metadata +123 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class ModuleMethodsTest < Minitest::Test
|
|
4
|
+
def test_module_get
|
|
5
|
+
response = Wreq.get("#{HTTPBIN_URL}/get")
|
|
6
|
+
refute_nil response
|
|
7
|
+
assert_equal 200, response.code
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def test_module_post
|
|
11
|
+
response = Wreq.post("#{HTTPBIN_URL}/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("#{HTTPBIN_URL}/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("#{HTTPBIN_URL}/delete")
|
|
26
|
+
refute_nil response
|
|
27
|
+
assert_equal 200, response.code
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_module_patch
|
|
31
|
+
response = Wreq.patch("#{HTTPBIN_URL}/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, "#{HTTPBIN_URL}/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("#{HTTPBIN_URL}/get",
|
|
47
|
+
headers: {"Accept" => "application/json"},
|
|
48
|
+
query: {"test" => "module"})
|
|
49
|
+
refute_nil response
|
|
50
|
+
assert_equal "#{HTTPBIN_URL}/get?test=module", response.url
|
|
51
|
+
assert_equal "module", httpbin_fetch(response.json["args"], "test")
|
|
52
|
+
assert_equal 200, response.code
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_module_post_with_json
|
|
56
|
+
response = Wreq.post("#{HTTPBIN_URL}/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("#{HTTPBIN_URL}/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,115 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class OrigHeaderTest < Minitest::Test
|
|
4
|
+
URL = "https://tls.browserleaks.com/http1"
|
|
5
|
+
|
|
6
|
+
CASES = [
|
|
7
|
+
{
|
|
8
|
+
name: "mixed_case_descending",
|
|
9
|
+
headers: {
|
|
10
|
+
"X-Zeta-Token" => "zeta",
|
|
11
|
+
"x-alpha-key" => "alpha",
|
|
12
|
+
"X-MiXeD-CaSe" => "mixed"
|
|
13
|
+
},
|
|
14
|
+
orig_headers: ["X-Zeta-Token", "x-alpha-key", "X-MiXeD-CaSe"]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
name: "reverse_alpha_order",
|
|
18
|
+
headers: {
|
|
19
|
+
"X-Third" => "3",
|
|
20
|
+
"X-Second" => "2",
|
|
21
|
+
"X-First" => "1"
|
|
22
|
+
},
|
|
23
|
+
orig_headers: ["X-Third", "X-Second", "X-First"]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "preserve_weird_casing",
|
|
27
|
+
headers: {
|
|
28
|
+
"x-a" => "a",
|
|
29
|
+
"X-B" => "b",
|
|
30
|
+
"x-C" => "c"
|
|
31
|
+
},
|
|
32
|
+
orig_headers: ["x-C", "x-a", "X-B"]
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: "interleaved_tokens",
|
|
36
|
+
headers: {
|
|
37
|
+
"X-Token-3" => "v3",
|
|
38
|
+
"X-Token-1" => "v1",
|
|
39
|
+
"X-Token-2" => "v2"
|
|
40
|
+
},
|
|
41
|
+
orig_headers: ["X-Token-1", "X-Token-2", "X-Token-3"]
|
|
42
|
+
}
|
|
43
|
+
].freeze
|
|
44
|
+
|
|
45
|
+
def test_client_default_orig_headers_preserves_header_order_in_multiple_shuffled_cases
|
|
46
|
+
CASES.each do |kase|
|
|
47
|
+
client = Wreq::Client.new(
|
|
48
|
+
headers: kase[:headers],
|
|
49
|
+
orig_headers: kase[:orig_headers]
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
response = client.get(URL, version: Wreq::Version::HTTP_11)
|
|
53
|
+
assert_equal 200, response.code, "case=#{kase[:name]}"
|
|
54
|
+
|
|
55
|
+
echoed_headers = extract_http1_headers(response.json, kase[:name])
|
|
56
|
+
assert_header_order(echoed_headers, kase[:orig_headers], kase[:name])
|
|
57
|
+
assert_header_values(echoed_headers, kase[:headers], kase[:name])
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_module_request_orig_headers_preserves_header_order_in_multiple_shuffled_cases
|
|
62
|
+
CASES.each do |kase|
|
|
63
|
+
response = Wreq.get(
|
|
64
|
+
URL,
|
|
65
|
+
headers: kase[:headers],
|
|
66
|
+
orig_headers: kase[:orig_headers],
|
|
67
|
+
version: Wreq::Version::HTTP_11
|
|
68
|
+
)
|
|
69
|
+
assert_equal 200, response.code, "case=#{kase[:name]}"
|
|
70
|
+
|
|
71
|
+
echoed_headers = extract_http1_headers(response.json, kase[:name])
|
|
72
|
+
assert_header_order(echoed_headers, kase[:orig_headers], kase[:name])
|
|
73
|
+
assert_header_values(echoed_headers, kase[:headers], kase[:name])
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def extract_http1_headers(json, case_name)
|
|
80
|
+
http1 = fetch_by_name(json, "http1")
|
|
81
|
+
refute_nil http1, "case=#{case_name}: expected JSON key 'http1', got #{json.keys.inspect}"
|
|
82
|
+
|
|
83
|
+
headers = fetch_by_name(http1, "headers")
|
|
84
|
+
refute_nil headers, "case=#{case_name}: expected JSON key 'http1.headers'"
|
|
85
|
+
headers
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def fetch_by_name(hash_like, key_name)
|
|
89
|
+
return hash_like[key_name] if hash_like.respond_to?(:key?) && hash_like.key?(key_name)
|
|
90
|
+
return hash_like[key_name.to_sym] if hash_like.respond_to?(:key?) && hash_like.key?(key_name.to_sym)
|
|
91
|
+
|
|
92
|
+
pair = hash_like.find { |k, _| k.to_s == key_name }
|
|
93
|
+
pair&.last
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def assert_header_order(echoed_headers, ordered_names, case_name)
|
|
97
|
+
echoed_keys = echoed_headers.keys
|
|
98
|
+
positions = ordered_names.map do |expected_name|
|
|
99
|
+
index = echoed_keys.index(expected_name)
|
|
100
|
+
refute_nil index, "case=#{case_name}: expected header to exist in echo: #{expected_name}"
|
|
101
|
+
index
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
assert_equal positions.sort, positions,
|
|
105
|
+
"case=#{case_name}: expected header order #{ordered_names.inspect}, got keys #{echoed_keys.inspect}"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def assert_header_values(echoed_headers, expected_headers, case_name)
|
|
109
|
+
expected_headers.each do |name, expected_value|
|
|
110
|
+
assert echoed_headers.key?(name),
|
|
111
|
+
"case=#{case_name}: expected exact-case header name #{name}, got #{echoed_headers.keys.inspect}"
|
|
112
|
+
assert_equal expected_value, echoed_headers[name]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class RequestParametersTest < Minitest::Test
|
|
4
|
+
def test_query_parameters
|
|
5
|
+
response = Wreq.get("#{HTTPBIN_URL}/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", httpbin_fetch(args, "string")
|
|
16
|
+
assert_equal "123", httpbin_fetch(args, "number") # Query params are strings
|
|
17
|
+
assert_equal "true", httpbin_fetch(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("#{HTTPBIN_URL}/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", httpbin_fetch(request_headers, "X-Custom-Header")
|
|
34
|
+
assert_equal "wreq-ruby-test/1.0", httpbin_fetch(request_headers, "User-Agent")
|
|
35
|
+
assert_equal "application/json", httpbin_fetch(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("#{HTTPBIN_URL}/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("#{HTTPBIN_URL}/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", httpbin_fetch(sent_form, "field1")
|
|
74
|
+
assert_equal "value2", httpbin_fetch(sent_form, "field2")
|
|
75
|
+
assert_equal "123", httpbin_fetch(sent_form, "number")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_combined_parameters
|
|
79
|
+
response = Wreq.post("#{HTTPBIN_URL}/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", httpbin_fetch(json_data["args"], "q")
|
|
90
|
+
|
|
91
|
+
# Check headers
|
|
92
|
+
assert_equal "combined", httpbin_fetch(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("#{HTTPBIN_URL}/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("#{HTTPBIN_URL}/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", httpbin_fetch(args, "space")
|
|
123
|
+
assert_equal "!@#$%^&*()", httpbin_fetch(args, "symbols")
|
|
124
|
+
assert_equal "测试中文", httpbin_fetch(args, "unicode")
|
|
125
|
+
assert_equal "a=b&c=d", httpbin_fetch(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("#{HTTPBIN_URL}/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: "#{HTTPBIN_URL}/get",
|
|
157
|
+
post: "#{HTTPBIN_URL}/post",
|
|
158
|
+
put: "#{HTTPBIN_URL}/put",
|
|
159
|
+
patch: "#{HTTPBIN_URL}/patch",
|
|
160
|
+
delete: "#{HTTPBIN_URL}/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, httpbin_fetch(json_data["headers"], "X-Method")
|
|
172
|
+
assert_equal method.to_s, httpbin_fetch(json_data["args"], "method")
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class WreqHttpbinTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
# Ensure we have a working client
|
|
6
|
+
@client = Wreq::Client.new(timeout: 30)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def test_spec_http1_version
|
|
10
|
+
response = Wreq.get("https://tls.browserleaks.com", version: Wreq::Version::HTTP_11)
|
|
11
|
+
assert_equal response.version, Wreq::Version::HTTP_11
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_spec_http2_version
|
|
15
|
+
response = Wreq.get("https://tls.browserleaks.com", version: Wreq::Version::HTTP_2)
|
|
16
|
+
assert_equal response.version, Wreq::Version::HTTP_2
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_module_get_method
|
|
20
|
+
response = Wreq.get("#{HTTPBIN_URL}/get")
|
|
21
|
+
assert_equal 200, response.code
|
|
22
|
+
assert_respond_to response, :text
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_module_post_with_json
|
|
26
|
+
data = {name: "wreq-ruby", version: "0.1.0"}
|
|
27
|
+
response = Wreq.post("#{HTTPBIN_URL}/post", json: data)
|
|
28
|
+
assert_equal 200, response.code
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_client_instance_basic
|
|
32
|
+
response = @client.get("#{HTTPBIN_URL}/get")
|
|
33
|
+
assert_equal 200, response.code
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_client_with_custom_headers
|
|
37
|
+
headers = {"User-Agent" => "wreq-ruby/test", "Accept" => "application/json"}
|
|
38
|
+
response = @client.get("#{HTTPBIN_URL}/headers", headers: headers)
|
|
39
|
+
assert_equal 200, response.code
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_all_http_methods_client
|
|
43
|
+
methods = [
|
|
44
|
+
Wreq::Method::GET,
|
|
45
|
+
Wreq::Method::POST,
|
|
46
|
+
Wreq::Method::PUT,
|
|
47
|
+
Wreq::Method::DELETE,
|
|
48
|
+
Wreq::Method::PATCH,
|
|
49
|
+
Wreq::Method::HEAD,
|
|
50
|
+
Wreq::Method::OPTIONS
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
methods.each do |method|
|
|
54
|
+
response = @client.request(method, "#{HTTPBIN_URL}/anything")
|
|
55
|
+
assert [200, 405].include?(response.code), "client.#{method} failed with status #{response.code}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_request_with_query_params
|
|
60
|
+
params = {"param1" => "value1", "param2" => "value2", "param3" => 123, "param4" => true}
|
|
61
|
+
response = Wreq.get("#{HTTPBIN_URL}/get", query: params)
|
|
62
|
+
assert_equal 200, response.code
|
|
63
|
+
assert_includes response.text, "param1=value1"
|
|
64
|
+
assert_includes response.text, "param2=value2"
|
|
65
|
+
assert_includes response.text, "param3=123"
|
|
66
|
+
assert_includes response.text, "param4=true"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_post_with_form_data
|
|
70
|
+
data = {"field1" => "value1", "field2" => "value2", "field3" => 456, "field4" => false}
|
|
71
|
+
response = Wreq.post("#{HTTPBIN_URL}/post", form: data)
|
|
72
|
+
assert_equal 200, response.code
|
|
73
|
+
assert_includes response.text, "field1"
|
|
74
|
+
assert_includes response.text, "value1"
|
|
75
|
+
assert_includes response.text, "field2"
|
|
76
|
+
assert_includes response.text, "value2"
|
|
77
|
+
assert_includes response.text, "field3"
|
|
78
|
+
assert_includes response.text, "456"
|
|
79
|
+
assert_includes response.text, "field4"
|
|
80
|
+
assert_includes response.text, "false"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def test_post_with_raw_body
|
|
84
|
+
body = "This is raw body content"
|
|
85
|
+
headers = {"Content-Type" => "text/plain"}
|
|
86
|
+
response = Wreq.post("#{HTTPBIN_URL}/post", body: body, headers: headers)
|
|
87
|
+
assert_equal 200, response.code
|
|
88
|
+
assert_includes response.text, body
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_basic_authentication
|
|
92
|
+
response = Wreq.get("#{HTTPBIN_URL}/basic-auth/user/pass", basic_auth: ["user", "pass"])
|
|
93
|
+
assert_equal 200, response.code
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_bearer_authentication
|
|
97
|
+
response = Wreq.get("#{HTTPBIN_URL}/bearer", bearer_auth: "test-token")
|
|
98
|
+
assert_equal 200, response.code
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_redirect_following
|
|
102
|
+
response = Wreq.get("#{HTTPBIN_URL}/redirect/2", allow_redirects: true)
|
|
103
|
+
assert_equal 200, response.code
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_redirect_blocking
|
|
107
|
+
response = Wreq.get("#{HTTPBIN_URL}/redirect/1", allow_redirects: false)
|
|
108
|
+
assert_equal 302, response.code
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_response_status_methods
|
|
112
|
+
response = Wreq.get("#{HTTPBIN_URL}/status/200")
|
|
113
|
+
assert_equal 200, response.code
|
|
114
|
+
|
|
115
|
+
if response.status.respond_to?(:success?)
|
|
116
|
+
assert response.status.success?
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def test_404_response
|
|
121
|
+
response = Wreq.get("#{HTTPBIN_URL}/status/404")
|
|
122
|
+
assert_equal 404, response.code
|
|
123
|
+
|
|
124
|
+
if response.status.respond_to?(:client_error?)
|
|
125
|
+
assert response.status.client_error?
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def test_json_response_parsing
|
|
130
|
+
response = Wreq.get("#{HTTPBIN_URL}/json")
|
|
131
|
+
assert_equal 200, response.code
|
|
132
|
+
|
|
133
|
+
if response.respond_to?(:json)
|
|
134
|
+
json_data = response.json
|
|
135
|
+
assert json_data.is_a?(Hash)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def test_gzip_compression
|
|
140
|
+
response = Wreq.get("#{HTTPBIN_URL}/gzip", gzip: true)
|
|
141
|
+
assert_equal 200, response.code
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def test_headers_iteration
|
|
145
|
+
response = Wreq.get("#{HTTPBIN_URL}/get")
|
|
146
|
+
|
|
147
|
+
if response.respond_to?(:each_header)
|
|
148
|
+
count = 0
|
|
149
|
+
response.each_header do |name, value|
|
|
150
|
+
assert name.is_a?(String)
|
|
151
|
+
assert value.is_a?(String)
|
|
152
|
+
count += 1
|
|
153
|
+
break if count >= 5 # Just test first few
|
|
154
|
+
end
|
|
155
|
+
assert count > 0, "Should iterate over at least one header"
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_response_properties
|
|
160
|
+
response = Wreq.get("#{HTTPBIN_URL}/get")
|
|
161
|
+
|
|
162
|
+
assert_respond_to response, :code
|
|
163
|
+
assert_respond_to response, :status
|
|
164
|
+
assert_respond_to response, :version
|
|
165
|
+
assert_respond_to response, :url
|
|
166
|
+
|
|
167
|
+
assert response.code.is_a?(Integer)
|
|
168
|
+
assert response.url.is_a?(String)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_timeout_functionality
|
|
172
|
+
# Test that short timeouts properly raise exceptions
|
|
173
|
+
assert_raises(Wreq::TimeoutError) do
|
|
174
|
+
Wreq.get("#{HTTPBIN_URL}/delay/10", timeout: 1)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Test that reasonable timeouts work normally
|
|
178
|
+
start_time = Time.now
|
|
179
|
+
response = Wreq.get("#{HTTPBIN_URL}/delay/1", timeout: 5)
|
|
180
|
+
elapsed = Time.now - start_time
|
|
181
|
+
|
|
182
|
+
assert_equal 200, response.code
|
|
183
|
+
assert elapsed < 5, "Request should complete within timeout"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def test_multiple_requests_performance
|
|
187
|
+
start_time = Time.now
|
|
188
|
+
|
|
189
|
+
3.times do |i|
|
|
190
|
+
response = Wreq.get("#{HTTPBIN_URL}/get?request=#{i}")
|
|
191
|
+
assert_equal 200, response.code
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
elapsed = Time.now - start_time
|
|
195
|
+
assert elapsed < 30, "3 requests should complete within 30 seconds"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def test_error_handling
|
|
199
|
+
assert_raises do
|
|
200
|
+
Wreq.get("https://this-domain-does-not-exist-12345.com")
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def test_client_configuration
|
|
205
|
+
client = Wreq::Client.new(
|
|
206
|
+
timeout: 10,
|
|
207
|
+
headers: {"User-Agent" => "wreq-ruby-test"},
|
|
208
|
+
allow_redirects: false
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Test that client was created successfully
|
|
212
|
+
assert_instance_of Wreq::Client, client
|
|
213
|
+
|
|
214
|
+
# Test that it can make requests
|
|
215
|
+
response = client.get("#{HTTPBIN_URL}/get")
|
|
216
|
+
assert_equal 200, response.code
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def test_enum_constants
|
|
220
|
+
# Test Method enum
|
|
221
|
+
assert_const_defined "Wreq::Method"
|
|
222
|
+
if defined?(Wreq::Method)
|
|
223
|
+
%w[GET POST PUT DELETE HEAD PATCH OPTIONS].each do |method|
|
|
224
|
+
assert Wreq::Method.const_defined?(method), "Method::#{method} should be defined"
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Test Version enum
|
|
229
|
+
assert_const_defined "Wreq::Version"
|
|
230
|
+
if defined?(Wreq::Version)
|
|
231
|
+
%w[HTTP_11 HTTP_2].each do |version|
|
|
232
|
+
assert Wreq::Version.const_defined?(version), "Version::#{version} should be defined"
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
private
|
|
238
|
+
|
|
239
|
+
def assert_const_defined(const_name)
|
|
240
|
+
const_name.split("::").inject(Object) { |o, c| o.const_get(c) }
|
|
241
|
+
rescue NameError
|
|
242
|
+
flunk "#{const_name} should be defined"
|
|
243
|
+
end
|
|
244
|
+
end
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
require "test_helper"
|
|
2
|
+
|
|
3
|
+
class ResponseTest < Minitest::Test
|
|
4
|
+
def setup
|
|
5
|
+
@response = Wreq.get("#{HTTPBIN_URL}/json")
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_response_code
|
|
9
|
+
assert_respond_to @response, :code
|
|
10
|
+
assert_instance_of Integer, @response.code
|
|
11
|
+
assert_equal 200, @response.code
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_response_text
|
|
15
|
+
assert_respond_to @response, :text
|
|
16
|
+
assert_instance_of String, @response.text
|
|
17
|
+
assert @response.text.length > 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_response_json
|
|
21
|
+
assert_respond_to @response, :json
|
|
22
|
+
json_data = @response.json
|
|
23
|
+
assert_instance_of Hash, json_data
|
|
24
|
+
|
|
25
|
+
# httpbin.io/json returns a specific JSON structure
|
|
26
|
+
assert json_data.key?("slideshow")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_response_each_header
|
|
30
|
+
assert_respond_to @response, :headers
|
|
31
|
+
|
|
32
|
+
header_count = 0
|
|
33
|
+
@response.headers.each do |name, value|
|
|
34
|
+
assert_instance_of String, name
|
|
35
|
+
assert_instance_of String, value
|
|
36
|
+
header_count += 1
|
|
37
|
+
end
|
|
38
|
+
assert header_count > 0
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_response_with_non_json_content
|
|
42
|
+
response = Wreq.get("#{HTTPBIN_URL}/html")
|
|
43
|
+
assert_equal 200, response.code
|
|
44
|
+
assert_instance_of String, response.text
|
|
45
|
+
assert response.text.include?("<html>")
|
|
46
|
+
|
|
47
|
+
# JSON parsing should fail for HTML content
|
|
48
|
+
assert_raises(StandardError) { response.json }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_response_status_codes
|
|
52
|
+
# Test different status codes
|
|
53
|
+
[200, 404, 500].each do |status|
|
|
54
|
+
response = Wreq.get("#{HTTPBIN_URL}/status/#{status}")
|
|
55
|
+
assert_equal status, response.code
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_response_with_query_parameters
|
|
60
|
+
response = Wreq.get("#{HTTPBIN_URL}/get",
|
|
61
|
+
query: {"param1" => "value1", "param2" => "value2"})
|
|
62
|
+
assert_equal 200, response.code
|
|
63
|
+
|
|
64
|
+
json_data = response.json
|
|
65
|
+
args = json_data["args"]
|
|
66
|
+
assert_equal "value1", httpbin_fetch(args, "param1")
|
|
67
|
+
assert_equal "value2", httpbin_fetch(args, "param2")
|
|
68
|
+
end
|
|
69
|
+
end
|