httpi 2.4.3 → 2.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +3 -3
- data/lib/httpi/adapter/curb.rb +3 -2
- data/lib/httpi/adapter/em_http.rb +5 -4
- data/lib/httpi/adapter/excon.rb +2 -1
- data/lib/httpi/adapter/http.rb +6 -0
- data/lib/httpi/adapter/httpclient.rb +1 -0
- data/lib/httpi/adapter/net_http.rb +7 -0
- data/lib/httpi/adapter/net_http_persistent.rb +1 -0
- data/lib/httpi/auth/ssl.rb +1 -1
- data/lib/httpi/request.rb +2 -2
- data/lib/httpi/version.rb +1 -1
- data/spec/httpi/adapter/curb_spec.rb +14 -7
- data/spec/httpi/adapter/em_http_spec.rb +21 -13
- data/spec/httpi/adapter/excon_spec.rb +23 -119
- data/spec/httpi/adapter/http_spec.rb +23 -96
- data/spec/httpi/adapter/httpclient_spec.rb +14 -0
- data/spec/httpi/adapter/net_http_persistent_spec.rb +31 -81
- data/spec/httpi/adapter/net_http_spec.rb +37 -181
- data/spec/integration/curb_spec.rb +11 -0
- data/spec/integration/em_http_spec.rb +17 -0
- data/spec/integration/excon_spec.rb +47 -0
- data/spec/integration/http_spec.rb +28 -0
- data/spec/integration/httpclient_spec.rb +11 -0
- data/spec/integration/net_http_persistent_spec.rb +21 -2
- data/spec/integration/net_http_spec.rb +117 -1
- data/spec/integration/support/application.rb +3 -2
- metadata +3 -3
@@ -100,6 +100,20 @@ describe HTTPI::Adapter::HTTPClient do
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
+
describe "send_timeout" do
|
104
|
+
it "is not set unless specified" do
|
105
|
+
httpclient.expects(:send_timeout=).never
|
106
|
+
adapter.request(:get)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "is set if specified" do
|
110
|
+
request.write_timeout = 30
|
111
|
+
|
112
|
+
httpclient.expects(:send_timeout=).with(30)
|
113
|
+
adapter.request(:get)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
103
117
|
describe "set_auth" do
|
104
118
|
it "is set for HTTP basic auth" do
|
105
119
|
request.auth.basic "username", "password"
|
@@ -1,96 +1,46 @@
|
|
1
1
|
require "spec_helper"
|
2
|
-
require "
|
2
|
+
require "httpi/adapter/net_http_persistent"
|
3
|
+
require "httpi/request"
|
3
4
|
|
4
|
-
|
5
|
+
begin
|
6
|
+
HTTPI::Adapter.load_adapter(:net_http_persistent)
|
5
7
|
|
6
|
-
|
8
|
+
describe HTTPI::Adapter::NetHTTPPersistent do
|
9
|
+
let(:adapter) { HTTPI::Adapter::NetHTTPPersistent.new(request) }
|
10
|
+
let(:request) { HTTPI::Request.new("http://example.com") }
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
it "sends and receives HTTP headers" do
|
18
|
-
request = HTTPI::Request.new(@server.url + "x-header")
|
19
|
-
request.headers["X-Header"] = "HTTPI"
|
20
|
-
|
21
|
-
response = HTTPI.get(request, adapter)
|
22
|
-
expect(response.body).to include("HTTPI")
|
23
|
-
end
|
24
|
-
|
25
|
-
it "executes GET requests" do
|
26
|
-
response = HTTPI.get(@server.url, adapter)
|
27
|
-
expect(response.body).to eq("get")
|
28
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
29
|
-
end
|
30
|
-
|
31
|
-
it "executes POST requests" do
|
32
|
-
response = HTTPI.post(@server.url, "<some>xml</some>", adapter)
|
33
|
-
expect(response.body).to eq("post")
|
34
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
35
|
-
end
|
36
|
-
|
37
|
-
it "executes HEAD requests" do
|
38
|
-
response = HTTPI.head(@server.url, adapter)
|
39
|
-
expect(response.code).to eq(200)
|
40
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
41
|
-
end
|
42
|
-
|
43
|
-
it "executes PUT requests" do
|
44
|
-
response = HTTPI.put(@server.url, "<some>xml</some>", adapter)
|
45
|
-
expect(response.body).to eq("put")
|
46
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
47
|
-
end
|
48
|
-
|
49
|
-
it "executes DELETE requests" do
|
50
|
-
response = HTTPI.delete(@server.url, adapter)
|
51
|
-
expect(response.body).to eq("delete")
|
52
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
53
|
-
end
|
54
|
-
|
55
|
-
it "supports basic authentication" do
|
56
|
-
request = HTTPI::Request.new(@server.url + "basic-auth")
|
57
|
-
request.auth.basic("admin", "secret")
|
12
|
+
let(:response) {
|
13
|
+
Object.new.tap do |r|
|
14
|
+
r.stubs(:code).returns(200)
|
15
|
+
r.stubs(:body).returns("abc")
|
16
|
+
r.stubs(:to_hash).returns({"Content-Length" => "3"})
|
17
|
+
end
|
18
|
+
}
|
58
19
|
|
59
|
-
|
60
|
-
|
20
|
+
before do
|
21
|
+
Net::HTTP::Persistent.any_instance.stubs(:start).returns(response)
|
61
22
|
end
|
62
23
|
|
63
|
-
|
64
|
-
|
65
|
-
|
24
|
+
describe "settings" do
|
25
|
+
describe "open_timeout, read_timeout" do
|
26
|
+
it "are being set on the client" do
|
27
|
+
request.open_timeout = 30
|
28
|
+
request.read_timeout = 40
|
66
29
|
|
67
|
-
|
68
|
-
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# it does not support digest auth
|
30
|
+
adapter.client.expects(:open_timeout=).with(30)
|
31
|
+
adapter.client.expects(:read_timeout=).with(40)
|
73
32
|
|
74
|
-
|
75
|
-
|
76
|
-
else
|
77
|
-
context "https requests" do
|
78
|
-
before :all do
|
79
|
-
@server = IntegrationServer.run(:ssl => true)
|
33
|
+
adapter.request(:get)
|
34
|
+
end
|
80
35
|
end
|
81
|
-
after :all do
|
82
|
-
@server.stop
|
83
|
-
end
|
84
|
-
|
85
|
-
# it does not raise when no certificate was set up
|
86
|
-
it "works when set up properly" do
|
87
|
-
request = HTTPI::Request.new(@server.url)
|
88
|
-
request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
|
89
36
|
|
90
|
-
|
91
|
-
|
37
|
+
describe "write_timeout" do
|
38
|
+
it "is not supported" do
|
39
|
+
request.write_timeout = 50
|
40
|
+
expect { adapter.request(:get) }
|
41
|
+
.to raise_error(HTTPI::NotSupportedError, /write_timeout/)
|
42
|
+
end
|
92
43
|
end
|
93
44
|
end
|
94
45
|
end
|
95
|
-
|
96
46
|
end
|
@@ -1,198 +1,54 @@
|
|
1
1
|
require "spec_helper"
|
2
|
-
require "
|
2
|
+
require "httpi/adapter/net_http"
|
3
|
+
require "httpi/request"
|
3
4
|
|
4
|
-
|
5
|
+
begin
|
6
|
+
HTTPI::Adapter.load_adapter(:net_http)
|
5
7
|
|
6
|
-
|
8
|
+
describe HTTPI::Adapter::NetHTTP do
|
9
|
+
let(:adapter) { HTTPI::Adapter::NetHTTP.new(request) }
|
10
|
+
let(:request) { HTTPI::Request.new("http://example.com") }
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
after :all do
|
14
|
-
@server.stop
|
15
|
-
end
|
16
|
-
|
17
|
-
context 'when socks is specified' do
|
18
|
-
|
19
|
-
let(:socks_client) { mock('socks_client') }
|
20
|
-
let(:request){HTTPI::Request.new(@server.url)}
|
21
|
-
|
22
|
-
it 'uses Net::HTTP.SOCKSProxy as client' do
|
23
|
-
socks_client.expects(:new).with(URI(@server.url).host, URI(@server.url).port).returns(:socks_client_instance)
|
24
|
-
Net::HTTP.expects(:SOCKSProxy).with('localhost', 8080).returns socks_client
|
25
|
-
|
26
|
-
request.proxy = 'socks://localhost:8080'
|
27
|
-
adapter = HTTPI::Adapter::NetHTTP.new(request)
|
28
|
-
|
29
|
-
expect(adapter.client).to eq(:socks_client_instance)
|
12
|
+
let(:response) {
|
13
|
+
Object.new.tap do |r|
|
14
|
+
r.stubs(:code).returns(200)
|
15
|
+
r.stubs(:body).returns("abc")
|
16
|
+
r.stubs(:to_hash).returns({"Content-Length" => "3"})
|
30
17
|
end
|
31
|
-
|
32
|
-
|
33
|
-
it "sends and receives HTTP headers" do
|
34
|
-
request = HTTPI::Request.new(@server.url + "x-header")
|
35
|
-
request.headers["X-Header"] = "HTTPI"
|
36
|
-
|
37
|
-
response = HTTPI.get(request, adapter)
|
38
|
-
expect(response.body).to include("HTTPI")
|
39
|
-
end
|
18
|
+
}
|
40
19
|
|
41
|
-
|
42
|
-
|
43
|
-
expect(response.body).to eq("get")
|
44
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
20
|
+
before do
|
21
|
+
Net::HTTP.any_instance.stubs(:start).returns(response)
|
45
22
|
end
|
46
23
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
it "executes HEAD requests" do
|
54
|
-
response = HTTPI.head(@server.url, adapter)
|
55
|
-
expect(response.code).to eq(200)
|
56
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
57
|
-
end
|
24
|
+
describe "settings" do
|
25
|
+
describe "open_timeout, read_timeout" do
|
26
|
+
it "are being set on the client" do
|
27
|
+
request.open_timeout = 30
|
28
|
+
request.read_timeout = 40
|
58
29
|
|
59
|
-
|
60
|
-
|
61
|
-
expect(response.body).to eq("put")
|
62
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
63
|
-
end
|
30
|
+
adapter.client.expects(:open_timeout=).with(30)
|
31
|
+
adapter.client.expects(:read_timeout=).with(40)
|
64
32
|
|
65
|
-
|
66
|
-
response = HTTPI.delete(@server.url, adapter)
|
67
|
-
expect(response.body).to eq("delete")
|
68
|
-
expect(response.headers["Content-Type"]).to eq("text/plain")
|
69
|
-
end
|
70
|
-
|
71
|
-
context "supports custom methods supported by Net::HTTP" do
|
72
|
-
let(:request) do
|
73
|
-
HTTPI::Request.new(@server.url).tap do|r|
|
74
|
-
r.body = request_body if request_body
|
33
|
+
adapter.request(:get)
|
75
34
|
end
|
76
35
|
end
|
77
36
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
context 'UNSUPPORTED method' do
|
95
|
-
let(:http_method) { :unsupported }
|
96
|
-
|
97
|
-
specify { expect { response }.to raise_error HTTPI::NotSupportedError }
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
it "supports basic authentication" do
|
102
|
-
request = HTTPI::Request.new(@server.url + "basic-auth")
|
103
|
-
request.auth.basic("admin", "secret")
|
104
|
-
|
105
|
-
response = HTTPI.get(request, adapter)
|
106
|
-
expect(response.body).to eq("basic-auth")
|
107
|
-
end
|
108
|
-
|
109
|
-
it "does not support digest authentication" do
|
110
|
-
request = HTTPI::Request.new(@server.url + "digest-auth")
|
111
|
-
request.auth.digest("admin", "secret")
|
112
|
-
|
113
|
-
expect { HTTPI.get(request, adapter) }.
|
114
|
-
to raise_error(HTTPI::NotSupportedError, /does not support HTTP digest authentication/)
|
115
|
-
end
|
116
|
-
|
117
|
-
it "supports ntlm authentication" do
|
118
|
-
request = HTTPI::Request.new(@server.url + "ntlm-auth")
|
119
|
-
request.auth.ntlm("tester", "vReqSoafRe5O")
|
120
|
-
|
121
|
-
response = HTTPI.get(request, adapter)
|
122
|
-
expect(response.body).to eq("ntlm-auth")
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'does not support ntlm authentication when Net::NTLM is not available' do
|
126
|
-
Net.expects(:const_defined?).with(:NTLM).returns false
|
127
|
-
|
128
|
-
request = HTTPI::Request.new(@server.url + 'ntlm-auth')
|
129
|
-
request.auth.ntlm("testing", "failures")
|
130
|
-
|
131
|
-
expect { HTTPI.get(request, adapter) }.
|
132
|
-
to raise_error(HTTPI::NotSupportedError, /Net::NTLM is not available/)
|
133
|
-
end
|
134
|
-
|
135
|
-
it 'does not require ntlm when ntlm authenication is not requested' do
|
136
|
-
HTTPI::Adapter::NetHTTP.any_instance.stubs(:check_net_ntlm_version!).raises(RuntimeError)
|
137
|
-
request = HTTPI::Request.new(@server.url)
|
138
|
-
expect(request.auth.ntlm?).to be false
|
139
|
-
|
140
|
-
# make sure a request doesn't call ntlm check if we don't ask for it.
|
141
|
-
expect { HTTPI.get(request, adapter) }.not_to raise_error
|
142
|
-
HTTPI::Adapter::NetHTTP.any_instance.unstub(:check_net_ntlm_version!)
|
143
|
-
end
|
144
|
-
|
145
|
-
it 'does check ntlm when ntlm authentication is requested' do
|
146
|
-
request = HTTPI::Request.new(@server.url + "ntlm-auth")
|
147
|
-
request.auth.ntlm("tester", "vReqSoafRe5O")
|
148
|
-
|
149
|
-
expect { HTTPI.get(request, adapter) }.not_to raise_error
|
150
|
-
|
151
|
-
# the check should also verify that the version of ntlm is supported and still fail if it isn't
|
152
|
-
HTTPI::Adapter::NetHTTP.any_instance.stubs(:ntlm_version).returns("0.1.1")
|
153
|
-
|
154
|
-
request = HTTPI::Request.new(@server.url + "ntlm-auth")
|
155
|
-
request.auth.ntlm("tester", "vReqSoafRe5O")
|
156
|
-
|
157
|
-
expect { HTTPI.get(request, adapter) }.to raise_error(ArgumentError, /Invalid version/)
|
158
|
-
|
159
|
-
HTTPI::Adapter::NetHTTP.any_instance.unstub(:ntlm_version)
|
160
|
-
end
|
161
|
-
|
162
|
-
it "does not crash when authenticate header is missing (on second request)" do
|
163
|
-
request = HTTPI::Request.new(@server.url + 'ntlm-auth')
|
164
|
-
request.auth.ntlm("tester", "vReqSoafRe5O")
|
165
|
-
|
166
|
-
expect { HTTPI.get(request, adapter) }.
|
167
|
-
to_not raise_error
|
168
|
-
|
169
|
-
expect { HTTPI.get(request, adapter) }.
|
170
|
-
to_not raise_error
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
# it does not support digest auth
|
175
|
-
|
176
|
-
if RUBY_PLATFORM =~ /java/
|
177
|
-
pending "Puma Server complains: SSL not supported on JRuby"
|
178
|
-
else
|
179
|
-
context "https requests" do
|
180
|
-
before :all do
|
181
|
-
@server = IntegrationServer.run(:ssl => true)
|
182
|
-
end
|
183
|
-
after :all do
|
184
|
-
@server.stop
|
185
|
-
end
|
186
|
-
|
187
|
-
# it does not raise when no certificate was set up
|
188
|
-
it "works when set up properly" do
|
189
|
-
request = HTTPI::Request.new(@server.url)
|
190
|
-
request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
|
191
|
-
|
192
|
-
response = HTTPI.get(request, adapter)
|
193
|
-
expect(response.body).to eq("get")
|
37
|
+
describe "write_timeout" do
|
38
|
+
if Net::HTTP.method_defined?(:write_timeout=)
|
39
|
+
it "is being set on the client" do
|
40
|
+
request.write_timeout = 50
|
41
|
+
adapter.client.expects(:write_timeout=).with(50)
|
42
|
+
adapter.request(:get)
|
43
|
+
end
|
44
|
+
else
|
45
|
+
it "can not be set on the client" do
|
46
|
+
request.write_timeout = 50
|
47
|
+
expect { adapter.request(:get) }
|
48
|
+
.to raise_error(HTTPI::NotSupportedError, /write_timeout/)
|
49
|
+
end
|
50
|
+
end
|
194
51
|
end
|
195
52
|
end
|
196
53
|
end
|
197
|
-
|
198
54
|
end
|
@@ -33,6 +33,17 @@ describe HTTPI::Adapter::Curb do
|
|
33
33
|
expect(response.headers["Set-Cookie"]).to eq(cookies)
|
34
34
|
end
|
35
35
|
|
36
|
+
it "it supports read timeout" do
|
37
|
+
require "curb"
|
38
|
+
|
39
|
+
request = HTTPI::Request.new(@server.url + "timeout")
|
40
|
+
request.read_timeout = 0.5 # seconds
|
41
|
+
|
42
|
+
expect do
|
43
|
+
HTTPI.get(request, adapter)
|
44
|
+
end.to raise_exception(Curl::Err::TimeoutError)
|
45
|
+
end
|
46
|
+
|
36
47
|
it "executes GET requests" do
|
37
48
|
response = HTTPI.get(@server.url, adapter)
|
38
49
|
expect(response.body).to eq("get")
|
@@ -42,6 +42,23 @@ describe HTTPI::Adapter::EmHttpRequest do
|
|
42
42
|
expect(response.headers["Set-Cookie"]).to eq(cookies)
|
43
43
|
end
|
44
44
|
|
45
|
+
if RUBY_PLATFORM =~ /java/
|
46
|
+
pending <<-MSG
|
47
|
+
It seems like JRuby is missing support for inactivity timeout! See related issues on GitHub:
|
48
|
+
- https://github.com/eventmachine/eventmachine/issues/155
|
49
|
+
- https://github.com/eventmachine/eventmachine/pull/312
|
50
|
+
MSG
|
51
|
+
else
|
52
|
+
it "it supports read timeout" do
|
53
|
+
request = HTTPI::Request.new(@server.url + "timeout")
|
54
|
+
request.read_timeout = 0.5 # seconds
|
55
|
+
|
56
|
+
expect do
|
57
|
+
HTTPI.get(request, adapter)
|
58
|
+
end.to raise_exception(HTTPI::TimeoutError)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
45
62
|
it "executes GET requests" do
|
46
63
|
response = HTTPI.get(@server.url, adapter)
|
47
64
|
expect(response.body).to eq("get")
|
@@ -30,6 +30,17 @@ describe HTTPI::Adapter::HTTPClient do
|
|
30
30
|
expect(response.headers["Set-Cookie"]).to eq(cookies)
|
31
31
|
end
|
32
32
|
|
33
|
+
it "it supports read timeout" do
|
34
|
+
require "excon"
|
35
|
+
|
36
|
+
request = HTTPI::Request.new(@server.url + "timeout")
|
37
|
+
request.read_timeout = 0.5 # seconds
|
38
|
+
|
39
|
+
expect do
|
40
|
+
HTTPI.get(request, adapter)
|
41
|
+
end.to raise_exception(Excon::Error::Timeout)
|
42
|
+
end
|
43
|
+
|
33
44
|
it "executes GET requests" do
|
34
45
|
response = HTTPI.get(@server.url, adapter)
|
35
46
|
expect(response.body).to eq("get")
|
@@ -68,6 +79,21 @@ describe HTTPI::Adapter::HTTPClient do
|
|
68
79
|
expect(response.body).to eq("basic-auth")
|
69
80
|
end
|
70
81
|
|
82
|
+
it "does not support ntlm authentication" do
|
83
|
+
request = HTTPI::Request.new(@server.url + "ntlm-auth")
|
84
|
+
request.auth.ntlm("tester", "vReqSoafRe5O")
|
85
|
+
|
86
|
+
expect { HTTPI.get(request, adapter) }.
|
87
|
+
to raise_error(HTTPI::NotSupportedError, /does not support NTLM authentication/)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "supports disabling verify mode" do
|
91
|
+
request = HTTPI::Request.new(@server.url)
|
92
|
+
request.auth.ssl.verify_mode = :none
|
93
|
+
adapter_class = HTTPI::Adapter.load(adapter).new(request)
|
94
|
+
expect(adapter_class.client.data[:ssl_verify_peer]).to eq(false)
|
95
|
+
end
|
96
|
+
|
71
97
|
it "supports chunked response" do
|
72
98
|
request = HTTPI::Request.new(@server.url)
|
73
99
|
res = ""
|
@@ -102,6 +128,27 @@ describe HTTPI::Adapter::HTTPClient do
|
|
102
128
|
response = HTTPI.get(request, adapter)
|
103
129
|
expect(response.body).to eq("get")
|
104
130
|
end
|
131
|
+
|
132
|
+
it "works with client cert and key provided as file path" do
|
133
|
+
request = HTTPI::Request.new(@server.url)
|
134
|
+
request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
|
135
|
+
request.auth.ssl.cert_file = "spec/fixtures/client_cert.pem"
|
136
|
+
request.auth.ssl.cert_key_file = "spec/fixtures/client_key.pem"
|
137
|
+
|
138
|
+
response = HTTPI.get(request, adapter)
|
139
|
+
expect(response.body).to eq("get")
|
140
|
+
end
|
141
|
+
|
142
|
+
it "works with client cert and key set directly" do
|
143
|
+
request = HTTPI::Request.new(@server.url)
|
144
|
+
|
145
|
+
request.auth.ssl.ca_cert_file = IntegrationServer.ssl_ca_file
|
146
|
+
request.auth.ssl.cert = OpenSSL::X509::Certificate.new File.open("spec/fixtures/client_cert.pem").read
|
147
|
+
request.auth.ssl.cert_key = OpenSSL::PKey.read File.open("spec/fixtures/client_key.pem").read
|
148
|
+
|
149
|
+
response = HTTPI.get(request, adapter)
|
150
|
+
expect(response.body).to eq("get")
|
151
|
+
end
|
105
152
|
end
|
106
153
|
end
|
107
154
|
|