manticore 0.2.1-java → 0.3.0-java

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.
@@ -37,6 +37,49 @@ describe Manticore::Client do
37
37
  j["uri"]["port"].should == 55441
38
38
  end
39
39
 
40
+ describe "lazy evaluation" do
41
+ it "should not call synchronous requests by default" do
42
+ req = client.get(local_server)
43
+ req.should_not be_called
44
+ end
45
+
46
+ context "given a lazy request" do
47
+ subject { client.get(local_server) }
48
+
49
+ before do
50
+ subject.should_not be_called
51
+ subject.should_receive(:call).once.and_call_original
52
+ end
53
+
54
+ specify { expect { subject.body }.to change { subject.called? } }
55
+ specify { expect { subject.headers }.to change { subject.called? } }
56
+ specify { expect { subject.final_url }.to change { subject.called? } }
57
+ specify { expect { subject.code }.to change { subject.called? } }
58
+ specify { expect { subject.length }.to change { subject.called? } }
59
+ specify { expect { subject.cookies }.to change { subject.called? } }
60
+ end
61
+
62
+ it "should automatically call synchronous requests that pass a handler block" do
63
+ req = client.get(local_server) {|r| }
64
+ req.should be_called
65
+ end
66
+
67
+ it "should not call asynchronous requests even if a block is passed" do
68
+ req = client.async.get(local_server) {|r| }
69
+ req.should_not be_called
70
+ end
71
+
72
+ it "should not call asynchronous requests when on_success is passed" do
73
+ req = client.async.get(local_server).on_success {|r| }
74
+ req.should_not be_called
75
+ end
76
+
77
+ it "should call async requests on client execution" do
78
+ req = client.async.get(local_server).on_success {|r| }
79
+ expect { client.execute! }.to change { req.called? }.from(false).to(true)
80
+ end
81
+ end
82
+
40
83
  context "when client-wide cookie management is disabled" do
41
84
  let(:client) { Manticore::Client.new cookies: false }
42
85
 
@@ -213,43 +256,12 @@ describe Manticore::Client do
213
256
  end
214
257
  end
215
258
 
216
- describe "async methods" do
217
- it "should not make a request until execute is called" do
218
- anchor = Time.now.to_f
219
- client.async_get("http://localhost:55441/?sleep=0.5")
220
- (Time.now.to_f - anchor).should < 0.4
221
-
222
- anchor = Time.now.to_f
223
- client.execute!
224
- (Time.now.to_f - anchor).should > 0.4
225
- end
226
-
227
- it "should return the response object, which may then have handlers attached" do
228
- response = client.async_get("http://localhost:55441/")
229
- success = false
230
- response.on_success do
231
- success = true
232
- end
233
-
234
- client.execute!
235
- success.should == true
236
- end
237
-
238
- it "can chain handlers" do
239
- client.async_get("http://localhost:55441/").on_success {|r| r.code }
240
- client.execute!.map(&:callback_result).should == [200]
241
- end
242
- end
243
-
244
259
  describe "#execute!" do
245
260
  it "should perform multiple concurrent requests" do
246
261
  @times = []
247
262
  [55441, 55442].each do |port|
248
- client.async_get("http://localhost:#{port}/?sleep=1") do |request|
249
- request.on_success do |response, request|
250
- @times << Time.now.to_f
251
- end
252
- end
263
+ client.async.get("http://localhost:#{port}/?sleep=1").
264
+ on_success {|response| @times << Time.now.to_f }
253
265
  end
254
266
 
255
267
  client.execute!
@@ -258,9 +270,8 @@ describe Manticore::Client do
258
270
 
259
271
  it "should return the results of the handler blocks" do
260
272
  [55441, 55442].each do |port|
261
- client.async_get("http://localhost:#{port}/") do |request|
262
- request.on_success {|response, request| "Result" }
263
- end
273
+ client.async.get("http://localhost:#{port}/").
274
+ on_success {|response, request| "Result" }
264
275
  end
265
276
 
266
277
  client.execute!.map(&:callback_result).should == ["Result", "Result"]
@@ -270,10 +281,84 @@ describe Manticore::Client do
270
281
  describe "#clear_pending" do
271
282
  it "should remove pending requests" do
272
283
  ran = false
273
- client.async_get("http://google.com").on_success {|r| ran = true }
284
+ client.async.get("http://google.com").on_success {|r| ran = true }
274
285
  client.clear_pending
275
286
  client.execute!.should be_empty
276
287
  ran.should be_false
277
288
  end
278
289
  end
290
+
291
+ describe "#stub" do
292
+ it "should respond with a stubbed response until it is unstubbed" do
293
+ client.stub(local_server, body: "body", code: 200)
294
+
295
+ called = false
296
+ 2.times {
297
+ client.get(local_server) do |response|
298
+ called = true
299
+ response.should be_a Manticore::StubbedResponse
300
+ response.body.should == "body"
301
+ response.code.should == 200
302
+ end
303
+ }
304
+
305
+ called.should be_true
306
+
307
+ client.clear_stubs!
308
+ client.get(local_server) do |response|
309
+ response.should be_a Manticore::Response
310
+ response.body.should match(/Manticore/)
311
+ response.code.should == 200
312
+ end
313
+ end
314
+
315
+ it "stubs only the provided URLs" do
316
+ client.stub local_server, body: "body"
317
+ client.async.get(local_server).on_success {|r| r.should be_a Manticore::StubbedResponse }
318
+ client.async.get(local_server("/other")).on_success {|r| r.should be_a Manticore::Response }
319
+ client.execute!
320
+ end
321
+ end
322
+
323
+ describe "keepalive" do
324
+ let(:url) { "http://www.facebook.com/" }
325
+
326
+ context "with keepalive" do
327
+ let(:client) { Manticore::Client.new keepalive: true, pool_max: 1 }
328
+
329
+ it "should keep the connection open after a request" do
330
+ pending
331
+ response = client.get(url).call
332
+ get_connection(client, url) do |conn|
333
+ conn.is_open.should be_true
334
+ end
335
+ end
336
+ end
337
+
338
+ context "without keepalive" do
339
+ let(:client) { Manticore::Client.new keepalive: false, pool_max: 1 }
340
+
341
+ it "should close the connection after a request" do
342
+ pending
343
+ response = client.get(url).call
344
+ puts `netstat -apn`
345
+ # get_connection(client, url) do |conn|
346
+ # conn.is_open.should be_false
347
+ # end
348
+ end
349
+ end
350
+ end
351
+
352
+ def get_connection(client, uri, &block)
353
+ java_import "java.util.concurrent.TimeUnit"
354
+ host = URI.parse(uri).host
355
+ pool = client.instance_variable_get("@pool")
356
+ req = pool.requestConnection(Java::OrgApacheHttpConnRouting::HttpRoute.new( Java::OrgApacheHttp::HttpHost.new(host) ), nil)
357
+ conn = req.get(3, TimeUnit::SECONDS)
358
+ begin
359
+ yield conn
360
+ ensure
361
+ pool.releaseConnection(conn, nil, 0, TimeUnit::SECONDS)
362
+ end
363
+ end
279
364
  end
@@ -9,9 +9,28 @@ describe Manticore::Cookie do
9
9
  response.cookies["x"].first
10
10
  }
11
11
 
12
- its(:name) { should be_a String }
13
- its(:value) { should be_a String }
14
- its(:path) { should be_a String }
15
- its(:domain) { should be_a String }
12
+ its(:name) { should == "x" }
13
+ its(:value) { should == "2" }
14
+ its(:path) { should == "/" }
15
+ its(:domain) { should == "localhost" }
16
+ end
17
+
18
+
19
+ let(:opts) {{}}
20
+ subject {
21
+ Manticore::Cookie.new({name: "foo", value: "bar"}.merge(opts))
22
+ }
23
+
24
+ its(:secure?) { should be_false }
25
+ its(:persistent?) { should be_false }
26
+
27
+ context "created as secure" do
28
+ let(:opts) {{ secure: true }}
29
+ its(:secure?) { should be_true }
30
+ end
31
+
32
+ context "created as persistent" do
33
+ let(:opts) {{ persistent: true }}
34
+ its(:persistent?) { should be_true }
16
35
  end
17
36
  end
@@ -26,4 +26,12 @@ describe Manticore::Response do
26
26
  expect { response.body }.to raise_exception(Manticore::StreamClosedException)
27
27
  end
28
28
  end
29
+
30
+ context "when an entity fails to read" do
31
+ it "releases the connection" do
32
+ stats_before = client.pool_stats
33
+ Manticore::EntityConverter.any_instance.should_receive(:read_entity).and_raise(Manticore::StreamClosedException)
34
+ expect { client.get(local_server).call rescue nil }.to_not change { client.pool_stats[:available] }
35
+ end
36
+ end
29
37
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ describe Manticore::StubbedResponse do
4
+ subject {
5
+ Manticore::StubbedResponse.stub(
6
+ body: "test body",
7
+ code: 200,
8
+ headers: {
9
+ "Content-Type" => "text/plain",
10
+ "Set-Cookie" => ["k=v; path=/; domain=localhost", "k=v; path=/sub; domain=sub.localhost", "k2=v2;2 path=/; domain=localhost"]
11
+ },
12
+ cookies: {"test" => Manticore::Cookie.new(name: "test", value: "something", path: "/")}
13
+ ).call
14
+ }
15
+
16
+ it { should be_a Manticore::Response }
17
+ its(:body) { should == "test body" }
18
+ its(:code) { should == 200 }
19
+
20
+ it "should persist the set headers" do
21
+ subject.headers["content-type"].should == "text/plain"
22
+ end
23
+
24
+ it "should set content-length from the body" do
25
+ subject.headers["content-length"].should == 9
26
+ end
27
+
28
+ it "should persist cookies passed as explicit cookie objects" do
29
+ subject.cookies["test"].first.value.should == "something"
30
+ end
31
+
32
+ it "should call on_success handlers" do
33
+ called = false
34
+ Manticore::StubbedResponse.stub.on_success {|resp| called = true }.call
35
+ called.should be_true
36
+ end
37
+
38
+ it "should persist cookies passed in set-cookie" do
39
+ subject.cookies["k"].map(&:value).should =~ ["v", "v"]
40
+ subject.cookies["k"].map(&:path).should =~ ["/", "/sub"]
41
+ subject.cookies["k"].map(&:domain).should =~ ["localhost", "sub.localhost"]
42
+ subject.cookies["k2"].first.value.should == "v2"
43
+ end
44
+ end
data/spec/spec_helper.rb CHANGED
@@ -56,6 +56,9 @@ def start_server(port = PORT)
56
56
  elsif request[:uri][:path] == "/proxy"
57
57
  payload = JSON.dump(request.merge(server_port: port))
58
58
  [200, {'Content-Type' => content_type, "Content-Length" => payload.length}, [payload]]
59
+ elsif request[:uri][:path] == "/keepalive"
60
+ payload = JSON.dump(request.merge(server_port: port))
61
+ [200, {'Content-Type' => content_type, "Content-Length" => payload.length, "Keep-Alive" => "timeout=60"}, [payload]]
59
62
  elsif request[:headers]["X-Redirect"] && request[:uri][:path] != request[:headers]["X-Redirect"]
60
63
  [301, {"Location" => local_server( request[:headers]["X-Redirect"] )}, [""]]
61
64
  else
data.tar.gz.sig ADDED
Binary file
metadata CHANGED
@@ -1,14 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manticore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: java
6
6
  authors:
7
7
  - Chris Heald
8
8
  autorequire:
9
9
  bindir: bin
10
- cert_chain: []
11
- date: 2014-02-23 00:00:00.000000000 Z
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIDaDCCAlCgAwIBAgIBATANBgkqhkiG9w0BAQUFADA9MQ8wDQYDVQQDDAZjaGVh
14
+ bGQxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2NvbTAe
15
+ Fw0xNDAzMDEyMTE4MzJaFw0xNTAzMDEyMTE4MzJaMD0xDzANBgNVBAMMBmNoZWFs
16
+ ZDEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29tMIIB
17
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwcnX2yl+rbjUztC4V+iUJgWv
18
+ NPxqU4bQBaL+w00wVABWr04Hjg+cEkqiJ6A0kXxZIz5uXKhhvsaO50NvHfplVcUf
19
+ BxQabIfCS79xdvexXN0or3F5saatGaGa4cj/0uUHjX7w+K5MpEVfbjJp0uAKp62B
20
+ wUU2ilmn7EvZhEUPOMQi01t8z8OsOGc8kF2UtU1kGCxLV7eThWqu8CdXrux5E140
21
+ 7SnFnPlnXNeHqwZdOMZzQ9PiTQAPCKO3AY0aBFQeG3wlFPqkcEjOrtV1h7werUwz
22
+ aNb4t5sAuu0f/9B646BOjiMgj1WeUlhgiAsaF5kVvLFNCxwS/xpcN3X01M2KdQID
23
+ AQABo3MwcTAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUtFVpwfEG
24
+ 78mBd2ulzsS+SlffdOcwGwYDVR0RBBQwEoEQY2hlYWxkQGdtYWlsLmNvbTAbBgNV
25
+ HRIEFDASgRBjaGVhbGRAZ21haWwuY29tMA0GCSqGSIb3DQEBBQUAA4IBAQANcBIJ
26
+ vIk27iNu4Ic6awNRy4Rd2YchzW4DaMhfpTXxtYWgAE502OdqUTFtmihd2PmnVRIP
27
+ xdP5K2SpbCLuLKFCZ825qp8R02JSNMdgi2d4Btl0vHSO8O3lQ1ZAOM1BZPn2+Kbn
28
+ KsiSURg3SnDXItcoedMsS+CQdNyBSdqvpkQ5gn22dN4BSwJg5ApwEYJ9tTuTpRXt
29
+ 1KCQFe5hamoenfoHO6uUXPEs24PUHnXl8QibWCLbt1FIBpTrJYNGiMHHnB7ip+zv
30
+ E7PWS50D9moUJ6xWcemf0qKYC87qBFh0ng73awjG9uf+13lMslqJRMtek8C92cvh
31
+ +R9zgQlbeNjy9O1i
32
+ -----END CERTIFICATE-----
33
+ date: 2014-03-28 00:00:00.000000000 Z
12
34
  dependencies:
13
35
  - !ruby/object:Gem::Dependency
14
36
  name: addressable
@@ -62,11 +84,13 @@ files:
62
84
  - .gitignore
63
85
  - .travis.yml
64
86
  - APACHE-LICENSE-2.0.txt
87
+ - CHANGELOG.md
65
88
  - Gemfile
66
89
  - LICENSE.txt
67
90
  - README.md
68
91
  - Rakefile
69
92
  - ext/manticore/org/manticore/Manticore.java
93
+ - gem-public_cert.pem
70
94
  - lib/jar/commons-codec-1.6.jar
71
95
  - lib/jar/commons-logging-1.1.3.jar
72
96
  - lib/jar/httpclient-4.3.2-patched.jar
@@ -74,17 +98,20 @@ files:
74
98
  - lib/jar/lazy_decompressing_stream.patch
75
99
  - lib/jar/manticore-ext.jar
76
100
  - lib/manticore.rb
77
- - lib/manticore/async_response.rb
78
101
  - lib/manticore/client.rb
102
+ - lib/manticore/client/proxies.rb
79
103
  - lib/manticore/cookie.rb
80
104
  - lib/manticore/facade.rb
81
105
  - lib/manticore/response.rb
106
+ - lib/manticore/stubbed_response.rb
82
107
  - lib/manticore/version.rb
83
108
  - manticore.gemspec
109
+ - spec/manticore/client_proxy_spec.rb
84
110
  - spec/manticore/client_spec.rb
85
111
  - spec/manticore/cookie_spec.rb
86
112
  - spec/manticore/facade_spec.rb
87
113
  - spec/manticore/response_spec.rb
114
+ - spec/manticore/stubbed_response_spec.rb
88
115
  - spec/spec_helper.rb
89
116
  homepage: https://github.com/cheald/manticore
90
117
  licenses:
@@ -111,8 +138,10 @@ signing_key:
111
138
  specification_version: 4
112
139
  summary: Manticore is an HTTP client built on the Apache HttpCore components
113
140
  test_files:
141
+ - spec/manticore/client_proxy_spec.rb
114
142
  - spec/manticore/client_spec.rb
115
143
  - spec/manticore/cookie_spec.rb
116
144
  - spec/manticore/facade_spec.rb
117
145
  - spec/manticore/response_spec.rb
146
+ - spec/manticore/stubbed_response_spec.rb
118
147
  - spec/spec_helper.rb
metadata.gz.sig ADDED
Binary file
@@ -1,88 +0,0 @@
1
- module Manticore
2
- # AsyncResponse is a runnable/future that encapsulates a request to be run asynchronously. It is created by Client#async_* calls.
3
- class AsyncResponse < Response
4
- java_import 'java.util.concurrent.Callable'
5
-
6
- include Callable
7
-
8
- # Creates a new AsyncResponse. The response is not realized until the client associated
9
- # with this response calls #execute!
10
- def initialize(client, request, context, body_handler_block)
11
- @client = client
12
- @handlers = {
13
- success: Proc.new {|resp| resp.body },
14
- failure: Proc.new {},
15
- cancelled: Proc.new {}
16
- }
17
- body_handler_block.call(self) if body_handler_block
18
- super request, context, nil
19
- end
20
-
21
- # @private
22
- # Implementation of Callable#call
23
- def call
24
- ex = nil
25
- begin
26
- @client.execute @request, self, @context
27
- return self
28
- rescue Java::JavaNet::SocketTimeoutException, Java::OrgApacheHttpConn::ConnectTimeoutException, Java::OrgApacheHttp::NoHttpResponseException => e
29
- ex = Manticore::Timeout.new(e.get_cause)
30
- rescue Java::JavaNet::SocketException => e
31
- ex = Manticore::SocketException.new(e.get_cause)
32
- rescue Java::OrgApacheHttpClient::ClientProtocolException, Java::JavaxNetSsl::SSLHandshakeException, Java::OrgApacheHttpConn::HttpHostConnectException => e
33
- ex = Manticore::ClientProtocolException.new(e.get_cause)
34
- rescue Java::JavaNet::UnknownHostException => e
35
- ex = Manticore::ResolutionFailure.new(e.get_cause)
36
- end
37
- @handlers[:failure].call ex
38
- end
39
-
40
- # Set handler for success responses
41
- # @param block Proc which will be invoked on a successful response. Block will receive |response, request|
42
- #
43
- # @return self
44
- def on_success(&block)
45
- @handlers[:success] = block
46
- self
47
- end
48
- alias_method :success, :on_success
49
-
50
- # Set handler for failure responses
51
- # @param block Proc which will be invoked on a on a failed response. Block will receive an exception object.
52
- #
53
- # @return self
54
- def on_failure(&block)
55
- @handlers[:failure] = block
56
- self
57
- end
58
- alias_method :failure, :on_failure
59
- alias_method :fail, :on_failure
60
-
61
- # Set handler for cancelled requests
62
- # @param block Proc which will be invoked on a on a cancelled response.
63
- #
64
- # @return self
65
- def on_cancelled(&block)
66
- @handlers[:cancelled] = block
67
- self
68
- end
69
- alias_method :cancelled, :on_cancelled
70
- alias_method :cancellation, :on_cancelled
71
- alias_method :on_cancellation, :on_cancelled
72
-
73
- private
74
-
75
- # @private
76
- def handle_response(response)
77
- begin
78
- @response = response
79
- @code = response.get_status_line.get_status_code
80
- @headers = Hash[* response.get_all_headers.flat_map {|h| [h.get_name.downcase, h.get_value]} ]
81
- @callback_result = @handlers[:success].call(self)
82
- nil
83
- rescue => e
84
- @exception = e
85
- end
86
- end
87
- end
88
- end