manticore 0.6.0-java → 0.7.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.
@@ -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