manticore 0.6.0-java → 0.7.0-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,6 +9,7 @@ module Manticore
9
9
  def async
10
10
  AsyncProxy.new(self)
11
11
  end
12
+
12
13
  alias_method :parallel, :async
13
14
  alias_method :batch, :async
14
15
 
@@ -20,6 +21,7 @@ module Manticore
20
21
 
21
22
  class BaseProxy
22
23
  include ProxiesInterface
24
+
23
25
  def initialize(client)
24
26
  @client = client
25
27
  end
@@ -55,4 +57,4 @@ module Manticore
55
57
  end
56
58
  end
57
59
  end
58
- end
60
+ end
@@ -36,7 +36,7 @@ module Manticore
36
36
  value: cookie.get_value,
37
37
  secure: cookie.is_secure,
38
38
  persistent: cookie.is_persistent,
39
- spec_version: cookie.get_version
39
+ spec_version: cookie.get_version,
40
40
  )
41
41
  end
42
42
 
@@ -63,16 +63,16 @@ module Manticore
63
63
  attr_reader :comment, :comment_url, :domain, :expires, :name, :path, :ports, :value, :spec_version
64
64
 
65
65
  def initialize(args)
66
- @comment = args.fetch(:comment, nil)
67
- @comment_url = args.fetch(:comment_url, nil)
68
- @domain = args.fetch(:domain, nil)
69
- @expires = args.fetch(:expires, nil)
70
- @name = args.fetch(:name, nil)
71
- @path = args.fetch(:path, nil)
72
- @ports = args.fetch(:ports, nil)
73
- @value = args.fetch(:value, nil)
74
- @secure = args.fetch(:secure, nil)
75
- @persistent = args.fetch(:persistent, nil)
66
+ @comment = args.fetch(:comment, nil)
67
+ @comment_url = args.fetch(:comment_url, nil)
68
+ @domain = args.fetch(:domain, nil)
69
+ @expires = args.fetch(:expires, nil)
70
+ @name = args.fetch(:name, nil)
71
+ @path = args.fetch(:path, nil)
72
+ @ports = args.fetch(:ports, nil)
73
+ @value = args.fetch(:value, nil)
74
+ @secure = args.fetch(:secure, nil)
75
+ @persistent = args.fetch(:persistent, nil)
76
76
  @spec_version = args.fetch(:spec_version, nil)
77
77
  end
78
78
 
@@ -104,4 +104,4 @@ module Manticore
104
104
  !@persistent
105
105
  end
106
106
  end
107
- end
107
+ end
@@ -1,4 +1,4 @@
1
- require 'forwardable'
1
+ require "forwardable"
2
2
 
3
3
  module Manticore
4
4
  # Mix-in that can be used to add Manticore functionality to arbitrary classes.
@@ -46,4 +46,4 @@ module Manticore
46
46
  end
47
47
  end
48
48
  end
49
- end
49
+ end
@@ -4,7 +4,7 @@ class Java::OrgApacheHttpClientMethods::HttpRequestBase
4
4
 
5
5
  # Provides an easy way to get the request headers from any request
6
6
  def headers
7
- Hash[*get_all_headers.flat_map {|h| [h.name, h.value] }]
7
+ Hash[*get_all_headers.flat_map { |h| [h.name, h.value] }]
8
8
  end
9
9
 
10
10
  # Get a single request header
@@ -3,7 +3,7 @@ module Manticore
3
3
  # as a Ruby proxy for HTTPClient responses.
4
4
  #
5
5
  # @!attribute [r] headers
6
- # @return [Hash] Headers from this response
6
+ # @return [Hash] Headers from this response. If a header is given more than once in a response, the value is an array of values. Otherwise, it is the header value.
7
7
  # @!attribute [r] code
8
8
  # @return [Integer] Response code from this response
9
9
  # @!attribute [r] context
@@ -15,7 +15,7 @@ module Manticore
15
15
  include_package "org.apache.http.util"
16
16
  include_package "org.apache.http.protocol"
17
17
  java_import "org.apache.http.client.protocol.HttpClientContext"
18
- java_import 'java.util.concurrent.Callable'
18
+ java_import "java.util.concurrent.Callable"
19
19
 
20
20
  include ResponseHandler
21
21
  include Callable
@@ -29,14 +29,14 @@ module Manticore
29
29
  # @param request [HttpRequestBase] The underlying request object
30
30
  # @param context [HttpContext] The underlying HttpContext
31
31
  def initialize(client, request, context, &block)
32
- @client = client
32
+ @client = client
33
33
  @request = request
34
34
  @context = context
35
35
  @handlers = {
36
- success: block || Proc.new {|resp| resp.body },
37
- failure: Proc.new {|ex| raise ex },
38
- cancelled: Proc.new {},
39
- complete: []
36
+ success: block || Proc.new { |resp| resp.body },
37
+ failure: Proc.new { |ex| raise ex },
38
+ cancelled: Proc.new { },
39
+ complete: [],
40
40
  }
41
41
  end
42
42
 
@@ -91,9 +91,9 @@ module Manticore
91
91
  def final_url
92
92
  call_once
93
93
  last_request = context.get_attribute ExecutionContext.HTTP_REQUEST
94
- last_host = context.get_attribute ExecutionContext.HTTP_TARGET_HOST
95
- host = last_host.to_uri
96
- url = last_request.get_uri
94
+ last_host = context.get_attribute ExecutionContext.HTTP_TARGET_HOST
95
+ host = last_host.to_uri
96
+ url = last_request.get_uri
97
97
  URI.join(host, url.to_s)
98
98
  end
99
99
 
@@ -115,15 +115,16 @@ module Manticore
115
115
  def body(&block)
116
116
  call_once
117
117
  @body ||= begin
118
- if entity = @response.get_entity
119
- EntityConverter.new.read_entity(entity, &block)
120
- end
121
- rescue Java::JavaIo::IOException, Java::JavaNet::SocketException, IOError => e
122
- raise StreamClosedException.new("Could not read from stream: #{e.message}")
123
- # ensure
124
- # @request.release_connection
125
- end
118
+ if entity = @response.get_entity
119
+ EntityConverter.new.read_entity(entity, &block)
120
+ end
121
+ rescue Java::JavaIo::IOException, Java::JavaNet::SocketException, IOError => e
122
+ raise StreamClosedException.new("Could not read from stream: #{e.message}")
123
+ # ensure
124
+ # @request.release_connection
125
+ end
126
126
  end
127
+
127
128
  alias_method :read_body, :body
128
129
 
129
130
  # Returns true if this response has been called (requested and populated) yet
@@ -140,10 +141,14 @@ module Manticore
140
141
  end
141
142
 
142
143
  # Return the value of a single response header. Will call the request if it has not been called yet.
144
+ # If the header was returned with multiple values, will only return the first value. If you need to get
145
+ # multiple values, use response#headers[lowercase_key]
143
146
  #
144
- # @return [String] Value of the header, or nil if not present
147
+ # @param key [String] Case-insensitive header key
148
+ # @return [String] Value of the header, or nil if not present
145
149
  def [](key)
146
- headers[key.downcase]
150
+ v = headers[key.downcase]
151
+ v.is_a?(Array) ? v.first : v
147
152
  end
148
153
 
149
154
  # Return the response code from this request as an integer. Will call the request if it has not been called yet.
@@ -192,6 +197,7 @@ module Manticore
192
197
  @handlers[:success] = block
193
198
  self
194
199
  end
200
+
195
201
  alias_method :success, :on_success
196
202
 
197
203
  # Set handler for failure responses
@@ -202,8 +208,9 @@ module Manticore
202
208
  @handlers[:failure] = block
203
209
  self
204
210
  end
211
+
205
212
  alias_method :failure, :on_failure
206
- alias_method :fail, :on_failure
213
+ alias_method :fail, :on_failure
207
214
 
208
215
  # Set handler for cancelled requests. NB: Not actually used right now?
209
216
  # @param block Proc which will be invoked on a on a cancelled response.
@@ -213,8 +220,9 @@ module Manticore
213
220
  @handlers[:cancelled] = block
214
221
  self
215
222
  end
216
- alias_method :cancelled, :on_cancelled
217
- alias_method :cancellation, :on_cancelled
223
+
224
+ alias_method :cancelled, :on_cancelled
225
+ alias_method :cancellation, :on_cancelled
218
226
  alias_method :on_cancellation, :on_cancelled
219
227
 
220
228
  # Set handler for completed requests
@@ -225,8 +233,9 @@ module Manticore
225
233
  @handlers[:complete] = Array(@handlers[:complete]).compact + [block]
226
234
  self
227
235
  end
228
- alias_method :complete, :on_complete
229
- alias_method :completed, :on_complete
236
+
237
+ alias_method :complete, :on_complete
238
+ alias_method :completed, :on_complete
230
239
  alias_method :on_completed, :on_complete
231
240
 
232
241
  def times_retried
@@ -243,10 +252,19 @@ module Manticore
243
252
  # Implementation of {http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/client/ResponseHandler.html#handleResponse(org.apache.http.HttpResponse) ResponseHandler#handleResponse}
244
253
  # @param response [Response] The underlying Java Response object
245
254
  def handleResponse(response)
246
- @response = response
247
- @code = response.get_status_line.get_status_code
248
- @message = response.get_status_line.get_reason_phrase
249
- @headers = Hash[* response.get_all_headers.flat_map {|h| [h.get_name.downcase, h.get_value]} ]
255
+ @response = response
256
+ @code = response.get_status_line.get_status_code
257
+ @message = response.get_status_line.get_reason_phrase
258
+ @headers = response.get_all_headers.each_with_object({}) do |h, o|
259
+ key = h.get_name.downcase
260
+ if o.key?(key)
261
+ o[key] = Array(o[key]) unless o[key].is_a?(Array)
262
+ o[key].push h.get_value
263
+ else
264
+ o[key] = h.get_value
265
+ end
266
+ end
267
+
250
268
  @callback_result = @handlers[:success].call(self)
251
269
  nil
252
270
  end
@@ -261,7 +279,7 @@ module Manticore
261
279
  end
262
280
 
263
281
  def execute_complete
264
- @handlers[:complete].each {|h| h.call(self) }
282
+ @handlers[:complete].each { |h| h.call(self) }
265
283
  end
266
284
  end
267
285
  end
@@ -33,12 +33,12 @@ module Manticore
33
33
  # @return [Manticore::StubbedResponse] self
34
34
  def stub(stubs)
35
35
  if stubs.key? :cookies
36
- stubs[:cookies].keys.each {|key| stubs[:cookies][key] = Array(stubs[:cookies][key]) }
36
+ stubs[:cookies].keys.each { |key| stubs[:cookies][key] = Array(stubs[:cookies][key]) }
37
37
  end
38
38
  stubs[:code] ||= 200
39
39
 
40
40
  stubs[:headers] ||= {}
41
- stubs[:headers] = Hash[*stubs[:headers].flat_map {|k, v| [k.downcase, v] }]
41
+ stubs[:headers] = Hash[*stubs[:headers].flat_map { |k, v| [k.downcase, v] }]
42
42
  stubs[:headers]["content-length"] ||= stubs[:body].length.to_s if stubs.key?(:body)
43
43
 
44
44
  @stubs = stubs
@@ -69,6 +69,7 @@ module Manticore
69
69
  @body
70
70
  end
71
71
  end
72
+
72
73
  alias_method :read_body, :body
73
74
 
74
75
  # Returns the stubbed cookies of this response. This is the union of cookies from the `:cookies`
@@ -82,8 +83,8 @@ module Manticore
82
83
 
83
84
  def handleResponse(response)
84
85
  raise response[:raises] if response.key?(:raises)
85
- @body = response[:body]
86
- @code = response[:code]
86
+ @body = response[:body]
87
+ @code = response[:code]
87
88
  @headers = response[:headers]
88
89
  @cookies = response[:cookies]
89
90
  Array(@headers["set-cookie"]).each do |cookie|
@@ -99,4 +100,4 @@ module Manticore
99
100
  call unless @called
100
101
  end
101
102
  end
102
- end
103
+ end
@@ -1,3 +1,3 @@
1
1
  module Manticore
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -1,8 +1,8 @@
1
1
  # this is a generated file, to avoid over-writing it just delete this comment
2
- require 'jar_dependencies'
2
+ require "jar_dependencies"
3
3
 
4
- require_jar( 'commons-logging', 'commons-logging', '1.2' )
5
- require_jar( 'org.apache.httpcomponents', 'httpmime', '4.5.2' )
6
- require_jar( 'commons-codec', 'commons-codec', '1.10' )
7
- require_jar( 'org.apache.httpcomponents', 'httpclient', '4.5.2' )
8
- require_jar( 'org.apache.httpcomponents', 'httpcore', '4.4.4' )
4
+ require_jar("commons-logging", "commons-logging", "1.2")
5
+ require_jar("org.apache.httpcomponents", "httpmime", "4.5.2")
6
+ require_jar("commons-codec", "commons-codec", "1.10")
7
+ require_jar("org.apache.httpcomponents", "httpclient", "4.5.2")
8
+ require_jar("org.apache.httpcomponents", "httpcore", "4.4.4")
@@ -25,9 +25,11 @@ Gem::Specification.new do |spec|
25
25
  spec.cert_chain = ['gem-public_cert.pem']
26
26
  end
27
27
 
28
- spec.add_development_dependency "bundler", "~> 1.3"
28
+ spec.add_dependency "openssl_pkcs8_pure"
29
+
30
+ spec.add_development_dependency "bundler"
29
31
  spec.add_development_dependency "rake"
30
- spec.add_development_dependency "jar-dependencies"
32
+ spec.add_development_dependency "jar-dependencies", "~> 0.4.1"
31
33
 
32
34
  spec.requirements << "jar org.apache.httpcomponents:httpclient, '~> 4.5.0'"
33
35
  spec.requirements << "jar org.apache.httpcomponents:httpmime, '~> 4.5.0'"
@@ -1,4 +1,5 @@
1
- require 'spec_helper'
1
+ # encoding: utf-8
2
+ require "spec_helper"
2
3
  describe Manticore::Client do
3
4
  let(:client) { Manticore::Client.new }
4
5
 
@@ -29,7 +30,7 @@ describe Manticore::Client do
29
30
  stub.async.get(local_server)
30
31
  stub.async.get(local_server)
31
32
 
32
- expect( client.execute!.map(&:class) ).to eq [Manticore::StubbedResponse, Manticore::StubbedResponse]
33
+ expect(client.execute!.map(&:class)).to eq [Manticore::StubbedResponse, Manticore::StubbedResponse]
33
34
  end
34
35
  end
35
36
  end
@@ -58,7 +59,7 @@ describe Manticore::Client do
58
59
  end
59
60
 
60
61
  it "can chain handlers" do
61
- client.async.get("http://localhost:55441/").on_success {|r| r.code }
62
+ client.async.get("http://localhost:55441/").on_success { |r| r.code }
62
63
  expect(client.execute!.map(&:callback_result)).to eq [200]
63
64
  end
64
65
  end
@@ -95,4 +96,4 @@ describe Manticore::Client do
95
96
  end
96
97
  end
97
98
  end
98
- end
99
+ end
@@ -1,11 +1,10 @@
1
1
  # encoding: utf-8
2
- require 'spec_helper'
2
+ require "spec_helper"
3
3
 
4
- java_import 'org.apache.http.entity.mime.MultipartEntityBuilder'
5
- java_import 'org.apache.http.entity.ContentType'
4
+ java_import "org.apache.http.entity.mime.MultipartEntityBuilder"
5
+ java_import "org.apache.http.entity.ContentType"
6
6
 
7
7
  describe Manticore::Client do
8
-
9
8
  let(:client) { Manticore::Client.new }
10
9
 
11
10
  it "fetches a URL and return a response" do
@@ -24,6 +23,12 @@ describe Manticore::Client do
24
23
  expect(json["headers"]["X-Custom-Header"]).to eq "Blaznotts"
25
24
  end
26
25
 
26
+ it "accepts repeated header values" do
27
+ response = client.get(local_server, headers: {"X-Custom-Header" => ["Whizzles", "Blaznotts"]})
28
+ json = JSON.load(response.body)
29
+ expect(json["headers"]["X-Custom-Header"].sort).to eq ["Blaznotts", "Whizzles"]
30
+ end
31
+
27
32
  it "enables compression" do
28
33
  response = client.get(local_server)
29
34
  json = JSON.load(response.body)
@@ -46,6 +51,39 @@ describe Manticore::Client do
46
51
  expect(j["uri"]["port"]).to eq 55441
47
52
  end
48
53
 
54
+ it "automatically decodes application/JSON as UTF-8" do
55
+ j = JSON.parse client.get(local_server("/json_utf8")).body
56
+ expect(j["last_name"]).to eq "Töger"
57
+ end
58
+
59
+ context "via an authenticated proxy" do
60
+ let(:proxy) { "http://localhost:55442" }
61
+ let(:auth) { nil }
62
+ let(:j) { JSON.parse req.body }
63
+
64
+ context "with authentication as a hash" do
65
+ let(:auth) { {user: "user", pass: "pass"} }
66
+ let(:req) { client.get(local_server("/authproxy"), proxy: proxy, auth: auth) }
67
+
68
+ it "proxies" do
69
+ expect(j["server_port"]).to eq 55442
70
+ expect(j["uri"]["port"]).to eq 55441
71
+ expect(j["headers"]["Proxy-Authorization"]).to eq "Basic dXNlcjpwYXNz"
72
+ end
73
+ end
74
+
75
+ context "with authentication as a string" do
76
+ let(:proxy) { "http://user:pass@localhost:55442" }
77
+ let(:req) { client.get(local_server("/authproxy"), proxy: proxy) }
78
+
79
+ it "proxies" do
80
+ expect(j["server_port"]).to eq 55442
81
+ expect(j["uri"]["port"]).to eq 55441
82
+ expect(j["headers"]["Proxy-Authorization"]).to eq "Basic dXNlcjpwYXNz"
83
+ end
84
+ end
85
+ end
86
+
49
87
  describe "with a custom user agent" do
50
88
  let(:client) { Manticore::Client.new user_agent: "test-agent/1.0" }
51
89
 
@@ -74,17 +112,21 @@ describe Manticore::Client do
74
112
  end
75
113
  end
76
114
 
77
- describe 'ssl settings' do
78
- describe 'verify' do
79
- context 'default' do
115
+ describe "ssl settings" do
116
+ describe "verify" do
117
+ context "default" do
80
118
  let(:client) { Manticore::Client.new }
81
119
 
82
120
  it "breaks on SSL validation errors" do
83
121
  expect { client.get("https://localhost:55444/").call }.to raise_exception(Manticore::ClientProtocolException)
84
122
  end
123
+
124
+ it "breaks on SSL expiry errors" do
125
+ expect { client.get("https://localhost:55446/").call }.to raise_exception(Manticore::ClientProtocolException)
126
+ end
85
127
  end
86
128
 
87
- context 'when on and no trust store is given' do
129
+ context "when on and no trust store is given" do
88
130
  let(:client) { Manticore::Client.new :ssl => {:verify => :strict} }
89
131
 
90
132
  it "breaks on SSL validation errors" do
@@ -92,7 +134,7 @@ describe Manticore::Client do
92
134
  end
93
135
  end
94
136
 
95
- context 'when on and custom trust store is given' do
137
+ context "when on and custom trust store is given" do
96
138
  let(:client) { Manticore::Client.new :ssl => {verify: :strict, truststore: File.expand_path("../../ssl/truststore.jks", __FILE__), truststore_password: "test123"} }
97
139
 
98
140
  it "verifies the request and succeed" do
@@ -108,7 +150,7 @@ describe Manticore::Client do
108
150
  end
109
151
  end
110
152
 
111
- context 'when on and custom trust store is given with the wrong password' do
153
+ context "when on and custom trust store is given with the wrong password" do
112
154
  let(:client) { Manticore::Client.new :ssl => {verify: :strict, truststore: File.expand_path("../../ssl/truststore.jks", __FILE__), truststore_password: "wrongpass"} }
113
155
 
114
156
  it "fails to load the keystore" do
@@ -116,22 +158,58 @@ describe Manticore::Client do
116
158
  end
117
159
  end
118
160
 
119
- context 'when ca_file is given' do
120
- let(:client) { Manticore::Client.new :ssl => {verify: :strict, ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__) } }
161
+ context "when ca_file is given" do
162
+ let(:client) { Manticore::Client.new :ssl => {verify: :strict, ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__)} }
121
163
 
122
164
  it "verifies the request and succeed" do
123
165
  expect { client.get("https://localhost:55444/").body }.to_not raise_exception
124
166
  end
125
167
  end
126
168
 
127
- context 'when client_cert and client_key are given' do
128
- let(:client) { Manticore::Client.new(
129
- :ssl => {
130
- verify: :strict,
131
- ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__),
132
- client_cert: File.expand_path("../../ssl/client.crt", __FILE__),
133
- client_key: File.expand_path("../../ssl/client.key", __FILE__)
134
- })
169
+ context "when client_cert and client_key are given as file paths" do
170
+ let(:client) {
171
+ Manticore::Client.new(
172
+ :ssl => {
173
+ verify: :strict,
174
+ ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__),
175
+ client_cert: File.expand_path("../../ssl/client.crt", __FILE__),
176
+ client_key: File.expand_path("../../ssl/client.key", __FILE__),
177
+ },
178
+ )
179
+ }
180
+
181
+ it "successfully auths requests" do
182
+ expect(client.get("https://localhost:55445/").body).to match("hello")
183
+ end
184
+ end
185
+
186
+ context "when client_cert and client_key are given as OpenSSL::X509::Certificate" do
187
+ let(:client) {
188
+ Manticore::Client.new(
189
+ :ssl => {
190
+ verify: :strict,
191
+ ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__),
192
+ client_cert: OpenSSL::X509::Certificate.new(File.read(File.expand_path("../../ssl/client.crt", __FILE__))),
193
+ client_key: OpenSSL::PKey::RSA.new(File.read(File.expand_path("../../ssl/client.key", __FILE__))),
194
+ },
195
+ )
196
+ }
197
+
198
+ it "successfully auths requests" do
199
+ expect(client.get("https://localhost:55445/").body).to match("hello")
200
+ end
201
+ end
202
+
203
+ context "when client_cert and client_key are given as strings" do
204
+ let(:client) {
205
+ Manticore::Client.new(
206
+ :ssl => {
207
+ verify: :strict,
208
+ ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__),
209
+ client_cert: File.read(File.expand_path("../../ssl/client.crt", __FILE__)),
210
+ client_key: File.read(File.expand_path("../../ssl/client.key", __FILE__)),
211
+ },
212
+ )
135
213
  }
136
214
 
137
215
  it "successfully auths requests" do
@@ -139,12 +217,16 @@ describe Manticore::Client do
139
217
  end
140
218
  end
141
219
 
142
- context 'when off' do
143
- let(:client) { Manticore::Client.new :ssl => {:verify => :none} }
220
+ context "when off" do
221
+ let(:client) { Manticore::Client.new :ssl => {:verify => :disable} }
144
222
 
145
223
  it "does not break on SSL validation errors" do
146
224
  expect { client.get("https://localhost:55444/").body }.to_not raise_exception
147
225
  end
226
+
227
+ it "does not break on expired SSL certificates" do
228
+ expect { client.get("https://localhost:55446/").body }.to_not raise_exception
229
+ end
148
230
  end
149
231
 
150
232
  context "against a server that verifies clients" do
@@ -155,7 +237,7 @@ describe Manticore::Client do
155
237
  truststore_password: "test123",
156
238
  keystore: File.expand_path("../../ssl/client.p12", __FILE__),
157
239
  keystore_password: "test123",
158
- verify: :strict
240
+ verify: :strict,
159
241
  }
160
242
  Manticore::Client.new :ssl => options
161
243
  }
@@ -170,7 +252,7 @@ describe Manticore::Client do
170
252
  options = {
171
253
  truststore: File.expand_path("../../ssl/truststore.jks", __FILE__),
172
254
  truststore_password: "test123",
173
- verify: :strict
255
+ verify: :strict,
174
256
  }
175
257
  Manticore::Client.new :ssl => options
176
258
  }
@@ -206,40 +288,39 @@ describe Manticore::Client do
206
288
  expect(subject).to receive(:call).once.and_call_original
207
289
  end
208
290
 
209
- specify { expect { subject.body }.to change { subject.called? } }
210
- specify { expect { subject.headers }.to change { subject.called? } }
291
+ specify { expect { subject.body }.to change { subject.called? } }
292
+ specify { expect { subject.headers }.to change { subject.called? } }
211
293
  specify { expect { subject.final_url }.to change { subject.called? } }
212
- specify { expect { subject.code }.to change { subject.called? } }
213
- specify { expect { subject.length }.to change { subject.called? } }
214
- specify { expect { subject.cookies }.to change { subject.called? } }
294
+ specify { expect { subject.code }.to change { subject.called? } }
295
+ specify { expect { subject.length }.to change { subject.called? } }
296
+ specify { expect { subject.cookies }.to change { subject.called? } }
215
297
  end
216
298
 
217
299
  it "automatically calls synchronous requests that pass a handler block" do
218
- req = client.get(local_server) {|r| }
300
+ req = client.get(local_server) { |r| }
219
301
  expect(req).to be_called
220
302
  end
221
303
 
222
304
  it "does not call asynchronous requests even if a block is passed" do
223
- req = client.async.get(local_server) {|r| }
305
+ req = client.async.get(local_server) { |r| }
224
306
  expect(req).to_not be_called
225
307
  end
226
308
 
227
309
  it "does not call asynchronous requests when on_success is passed" do
228
- req = client.async.get(local_server).on_success {|r| }
310
+ req = client.async.get(local_server).on_success { |r| }
229
311
  expect(req).to_not be_called
230
312
  end
231
313
 
232
314
  it "calls async requests on client execution" do
233
- req = client.async.get(local_server).on_success {|r| }
315
+ req = client.async.get(local_server).on_success { |r| }
234
316
  expect { client.execute! }.to change { req.called? }.from(false).to(true)
235
317
  end
236
318
 
237
-
238
319
  describe "with a bad port number" do
239
320
  it "returns a Manticore::InvalidArgumentException" do
240
321
  failure = nil
241
322
  client.async.get(local_server("/", 65536)).
242
- on_failure {|f| failure = f }
323
+ on_failure { |f| failure = f }
243
324
  client.execute!
244
325
  expect(failure).to be_a(Manticore::InvalidArgumentException)
245
326
  end
@@ -251,7 +332,7 @@ describe Manticore::Client do
251
332
  # I'm not crazy about reaching into the client via instance_variable_get here, but it works.
252
333
  expect(client.instance_variable_get("@client")).to receive(:execute).and_raise(StandardError.new("Uh oh"))
253
334
  client.async.get(local_server).
254
- on_failure {|f| failure = f }
335
+ on_failure { |f| failure = f }
255
336
  client.execute!
256
337
  expect(failure).to be_a(StandardError)
257
338
  end
@@ -368,6 +449,11 @@ describe Manticore::Client do
368
449
  expect(JSON.load(response.body)["method"]).to eq "GET"
369
450
  end
370
451
 
452
+ it "works with a URI object" do
453
+ response = client.get(URI.parse local_server)
454
+ expect(JSON.load(response.body)["method"]).to eq "GET"
455
+ end
456
+
371
457
  it "send a query" do
372
458
  response = client.get local_server, query: {foo: "bar"}
373
459
  expect(CGI.parse(JSON.load(response.body)["uri"]["query"])["foo"]).to eq ["bar"]
@@ -438,10 +524,10 @@ describe Manticore::Client do
438
524
  end
439
525
 
440
526
  it "sends an arbitrary entity" do
441
- f = open(__FILE__, "r").to_inputstream
442
- multipart_entity = MultipartEntityBuilder.create.add_text_body("foo", "bar").add_binary_body("whatever", f , ContentType::TEXT_PLAIN, __FILE__)
527
+ f = open(File.expand_path(File.join(__FILE__, "..", "..", "spec_helper.rb")), "r").to_inputstream
528
+ multipart_entity = MultipartEntityBuilder.create.add_text_body("foo", "bar").add_binary_body("whatever", f, ContentType::TEXT_PLAIN, __FILE__)
443
529
  response = client.post(local_server, entity: multipart_entity.build)
444
- expect(response.body).to match "sends an arbitrary entity"
530
+ expect(response.body).to match "RSpec.configure"
445
531
  end
446
532
  end
447
533
 
@@ -477,7 +563,7 @@ describe Manticore::Client do
477
563
  describe "#head" do
478
564
  it "works" do
479
565
  response = client.head(local_server)
480
- expect(JSON.load(response.body)).to be_nil
566
+ expect(response.body).to be_nil
481
567
  end
482
568
  end
483
569
 
@@ -510,8 +596,8 @@ describe Manticore::Client do
510
596
  futures = [55441, 55442].map do |port|
511
597
  client.async.get("http://localhost:#{port}/?sleep=1").
512
598
  on_success do |response|
513
- Time.now.to_f
514
- end
599
+ Time.now.to_f
600
+ end
515
601
  end
516
602
 
517
603
  client.execute!
@@ -522,7 +608,7 @@ describe Manticore::Client do
522
608
  it "returns the results of the handler blocks" do
523
609
  [55441, 55442].each do |port|
524
610
  client.async.get("http://localhost:#{port}/").
525
- on_success {|response, request| "Result" }
611
+ on_success { |response, request| "Result" }
526
612
  end
527
613
 
528
614
  expect(client.execute!.map(&:callback_result)).to eq ["Result", "Result"]
@@ -532,7 +618,7 @@ describe Manticore::Client do
532
618
  describe "#clear_pending" do
533
619
  it "removes pending requests" do
534
620
  ran = false
535
- client.async.get("http://google.com").on_success {|r| ran = true }
621
+ client.async.get("http://google.com").on_success { |r| ran = true }
536
622
  client.clear_pending
537
623
  expect(client.execute!).to be_empty
538
624
  expect(ran).to be false
@@ -563,25 +649,25 @@ describe Manticore::Client do
563
649
  end
564
650
  end
565
651
 
566
- context 'stubbing' do
652
+ context "stubbing" do
567
653
  it "only the provided URLs" do
568
654
  client.stub local_server, body: "body"
569
- client.async.get(local_server).on_success {|r| expect(r).to be_a Manticore::StubbedResponse }
570
- client.async.get(local_server("/other")).on_success {|r| expect(r).to_not be_a Manticore::StubbedResponse }
655
+ client.async.get(local_server).on_success { |r| expect(r).to be_a Manticore::StubbedResponse }
656
+ client.async.get(local_server("/other")).on_success { |r| expect(r).to_not be_a Manticore::StubbedResponse }
571
657
  client.execute!
572
658
  end
573
659
 
574
660
  it "by regex matching" do
575
661
  client.stub %r{#{local_server("/foo")}}, body: "body"
576
- client.async.get(local_server("/foo")).on_success {|r| expect(r).to be_a Manticore::StubbedResponse }
577
- client.async.get(local_server("/bar")).on_success {|r| expect(r).to_not be_a Manticore::StubbedResponse }
662
+ client.async.get(local_server("/foo")).on_success { |r| expect(r).to be_a Manticore::StubbedResponse }
663
+ client.async.get(local_server("/bar")).on_success { |r| expect(r).to_not be_a Manticore::StubbedResponse }
578
664
  client.execute!
579
665
  end
580
666
 
581
667
  it "strictly matches string stubs" do
582
668
  client.stub local_server("/foo"), body: "body"
583
- client.async.get(local_server("/foo")).on_success {|r| expect(r).to be_a Manticore::StubbedResponse }
584
- client.async.get(local_server("/other")).on_success {|r| expect(r).to_not be_a Manticore::StubbedResponse }
669
+ client.async.get(local_server("/foo")).on_success { |r| expect(r).to be_a Manticore::StubbedResponse }
670
+ client.async.get(local_server("/other")).on_success { |r| expect(r).to_not be_a Manticore::StubbedResponse }
585
671
  client.execute!
586
672
  end
587
673
 
@@ -613,10 +699,9 @@ describe Manticore::Client do
613
699
  describe "keepalive" do
614
700
  let(:url) { "http://www.facebook.com/" }
615
701
 
616
-
617
702
  context "with keepalive" do
618
703
  it "adds the Connection: Keep-Alive header for http/1.0" do
619
- expect( client.get(url).request["Connection"] ).to eq "Keep-Alive"
704
+ expect(client.get(url).request["Connection"]).to eq "Keep-Alive"
620
705
  end
621
706
 
622
707
  let(:client) { Manticore::Client.new keepalive: true, pool_max: 1 }
@@ -634,7 +719,7 @@ describe Manticore::Client do
634
719
  let(:client) { Manticore::Client.new keepalive: false, pool_max: 1 }
635
720
 
636
721
  it "does not add the Connection: Keep-Alive header for http/1.0" do
637
- expect( client.get(url).request["Connection"] ).to be_nil
722
+ expect(client.get(url).request["Connection"]).to be_nil
638
723
  end
639
724
 
640
725
  it "closes the connection after a request" do
@@ -649,35 +734,54 @@ describe Manticore::Client do
649
734
  end
650
735
 
651
736
  context "with a misbehaving endpoint" do
737
+ let(:port) do
738
+ p = 4000
739
+ server = nil
740
+ begin
741
+ server = TCPServer.new p
742
+ rescue Errno::EADDRINUSE
743
+ p += 1
744
+ retry
745
+ ensure
746
+ server.close
747
+ end
748
+ p
749
+ end
750
+
652
751
  before do
653
- @socket = TCPServer.new 4567
752
+ @socket = TCPServer.new port
654
753
  @server = Thread.new do
655
754
  loop do
656
- client = @socket.accept
657
755
  begin
756
+ client = @socket.accept
658
757
  client.puts([
659
758
  "HTTP/1.1 200 OK",
660
759
  "Keep-Alive: timeout=3000",
661
760
  "Connection: Keep-Alive",
662
761
  "Content-Length: 6",
663
762
  "",
664
- "Hello!"
763
+ "Hello!",
665
764
  ].join("\n"))
666
765
  client.close
667
- rescue StandardError => e
766
+ rescue IOError => e
767
+ break
668
768
  end
669
769
  end
670
770
  end
671
771
  end
672
772
 
773
+ after do
774
+ @server.kill
775
+ end
776
+
673
777
  let(:client) { Manticore::Client.new keepalive: true, pool_max: 1 }
674
778
 
675
779
  it "retries 3 times by default" do
676
780
  # The first time, reply with keepalive, then close the connection
677
781
  # The second connection should succeed
678
782
 
679
- request1 = client.get("http://localhost:4567/")
680
- request2 = client.get("http://localhost:4567/")
783
+ request1 = client.get("http://localhost:#{port}/")
784
+ request2 = client.get("http://localhost:#{port}/")
681
785
  expect { request1.call }.to_not raise_exception
682
786
  expect { request2.call }.to_not raise_exception
683
787
 
@@ -691,8 +795,8 @@ describe Manticore::Client do
691
795
  it "retries 0 times and fail on the second request" do
692
796
  # The first time, reply with keepalive, then close the connection
693
797
  # The second connection should succeed
694
- expect { client.get("http://localhost:4567/").call }.to_not raise_exception
695
- expect { client.get("http://localhost:4567/").call }.to raise_exception(Manticore::SocketException)
798
+ expect { client.get("http://localhost:#{port}/").call }.to_not raise_exception
799
+ expect { client.get("http://localhost:#{port}/").call }.to raise_exception(Manticore::SocketException)
696
800
  end
697
801
  end
698
802
 
@@ -702,8 +806,8 @@ describe Manticore::Client do
702
806
  it "succeeds without any retries" do
703
807
  # The first time, reply with keepalive, then close the connection
704
808
  # The second connection should succeed
705
- request1 = client.get("http://localhost:4567/")
706
- request2 = client.get("http://localhost:4567/")
809
+ request1 = client.get("http://localhost:#{port}/")
810
+ request2 = client.get("http://localhost:#{port}/")
707
811
  expect { request1.call }.to_not raise_exception
708
812
  expect { request2.call }.to_not raise_exception
709
813
 
@@ -714,7 +818,11 @@ describe Manticore::Client do
714
818
 
715
819
  after do
716
820
  Thread.kill @server
717
- @socket.close
821
+ begin
822
+ @socket.close
823
+ rescue IOError
824
+ # pass
825
+ end
718
826
  end
719
827
  end
720
828
 
@@ -771,15 +879,15 @@ describe Manticore::Client do
771
879
 
772
880
  describe "background" do
773
881
  it "returns a response" do
774
- expect( client.background.get(local_server) ).to be_a Manticore::Response
882
+ expect(client.background.get(local_server)).to be_a Manticore::Response
775
883
  end
776
884
 
777
885
  it "has the background flag set" do
778
- expect( client.background.get(local_server).background ).to eq true
886
+ expect(client.background.get(local_server).background).to eq true
779
887
  end
780
888
 
781
889
  it "returns a future when called" do
782
- expect( client.background.get(local_server).call ).to be_a Java::JavaUtilConcurrent::FutureTask
890
+ expect(client.background.get(local_server).call).to be_a Java::JavaUtilConcurrent::FutureTask
783
891
  end
784
892
 
785
893
  it "evaluates immediately when given a block" do
@@ -798,7 +906,7 @@ describe Manticore::Client do
798
906
  java_import "java.util.concurrent.TimeUnit"
799
907
  host = URI.parse(uri).host
800
908
  pool = client.instance_variable_get("@pool")
801
- req = pool.requestConnection(Java::OrgApacheHttpConnRouting::HttpRoute.new( Java::OrgApacheHttp::HttpHost.new(host) ), nil)
909
+ req = pool.requestConnection(Java::OrgApacheHttpConnRouting::HttpRoute.new(Java::OrgApacheHttp::HttpHost.new(host)), nil)
802
910
  conn = req.get(3, TimeUnit::SECONDS)
803
911
  begin
804
912
  yield conn