manticore 0.6.0-java → 0.6.1-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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +2 -0
- data/lib/manticore/client.rb +25 -9
- data/lib/manticore/response.rb +17 -4
- data/lib/manticore/version.rb +1 -1
- data/spec/manticore/client_spec.rb +48 -4
- data/spec/manticore/response_spec.rb +12 -0
- data/spec/spec_helper.rb +12 -2
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1e6b7d1ea5d4bb60011c89d4b3e7b10abff3b42
|
4
|
+
data.tar.gz: db35b3f276b9f5040cee58407a16858f291435d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e8a1d7749fd671e7f44970067dd67899d5485de989c320baa39ab6f05df886e34148a3ccdd05ec7513792138314d4d37421509a5a7fd6b47231c30f2f862acec
|
7
|
+
data.tar.gz: f83f8a304ad9c12d94c3b8fd8b5914fded62083a6b90ed61a67e80aa754683ec69fa122e802377f250cc6eaa40f79a09930bb482d5c337cabce3bc799271945c
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
### v0.6.1 (pending)
|
4
4
|
|
5
|
+
* Manticore will accept a URI object (which it calls #to_s on) as an alternate to a String for the URL in client#get(url)
|
6
|
+
|
5
7
|
### v0.6.0
|
6
8
|
|
7
9
|
* Dependent jars are now vendored, but managed with jar-dependencies. This solves issues installing manticore on platforms that have out-of-date root certs, and simplifies the install process.
|
data/lib/manticore/client.rb
CHANGED
@@ -446,6 +446,7 @@ module Manticore
|
|
446
446
|
end
|
447
447
|
|
448
448
|
def uri_from_url_and_options(url, options)
|
449
|
+
url = url.to_s if url.is_a?(URI)
|
449
450
|
builder = URIBuilder.new(url)
|
450
451
|
pairs = struct_to_name_value_pairs(options[:query])
|
451
452
|
builder.add_parameters pairs unless pairs.empty?
|
@@ -486,11 +487,18 @@ module Manticore
|
|
486
487
|
req.set_config config.build
|
487
488
|
end
|
488
489
|
|
489
|
-
|
490
|
-
options[:headers].each {|k, v| req[k] = v } if options.key?(:headers)
|
491
|
-
|
490
|
+
headers = []
|
492
491
|
# Support keepalive on HTTP/1.0 connections
|
493
|
-
|
492
|
+
headers.push BasicHeader.new("Connection", "Keep-Alive") if @keepalive
|
493
|
+
|
494
|
+
if options.key?(:headers)
|
495
|
+
options[:headers].each do |k, v|
|
496
|
+
Array(v).each do |_v|
|
497
|
+
headers.push BasicHeader.new(k, _v)
|
498
|
+
end
|
499
|
+
end
|
500
|
+
end
|
501
|
+
req.set_headers headers.to_java(BasicHeader) unless headers.empty?
|
494
502
|
|
495
503
|
context = HttpClientContext.new
|
496
504
|
proxy_user = req_options[:proxy].is_a?(Hash) && (req_options[:proxy][:user] || req_options[:proxy][:username])
|
@@ -529,7 +537,17 @@ module Manticore
|
|
529
537
|
|
530
538
|
def auth_from_options(req, options, context)
|
531
539
|
proxy = options.fetch(:proxy, {})
|
532
|
-
|
540
|
+
|
541
|
+
proxy_user, proxy_pass = if proxy.is_a?(String)
|
542
|
+
proxy_uri = URI.parse(proxy)
|
543
|
+
[proxy_uri.user, proxy_uri.password]
|
544
|
+
else
|
545
|
+
[(proxy[:user] || proxy[:username]),
|
546
|
+
(proxy[:pass] || proxy[:password])]
|
547
|
+
end
|
548
|
+
|
549
|
+
|
550
|
+
if options[:auth] || proxy_user
|
533
551
|
provider = BasicCredentialsProvider.new
|
534
552
|
if options[:auth]
|
535
553
|
username = options[:auth][:user] || options[:auth][:username]
|
@@ -547,10 +565,8 @@ module Manticore
|
|
547
565
|
end
|
548
566
|
end
|
549
567
|
|
550
|
-
if
|
551
|
-
|
552
|
-
password = proxy[:pass] || proxy[:password]
|
553
|
-
provider.set_credentials AuthScope.new(get_proxy_host(proxy)), UsernamePasswordCredentials.new(username, password)
|
568
|
+
if proxy_user
|
569
|
+
provider.set_credentials AuthScope.new(get_proxy_host(proxy)), UsernamePasswordCredentials.new(proxy_user, proxy_pass)
|
554
570
|
end
|
555
571
|
context.set_credentials_provider(provider)
|
556
572
|
end
|
data/lib/manticore/response.rb
CHANGED
@@ -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
|
@@ -140,10 +140,14 @@ module Manticore
|
|
140
140
|
end
|
141
141
|
|
142
142
|
# Return the value of a single response header. Will call the request if it has not been called yet.
|
143
|
+
# If the header was returned with multiple values, will only return the first value. If you need to get
|
144
|
+
# multiple values, use response#headers[lowercase_key]
|
143
145
|
#
|
144
|
-
# @
|
146
|
+
# @param key [String] Case-insensitive header key
|
147
|
+
# @return [String] Value of the header, or nil if not present
|
145
148
|
def [](key)
|
146
|
-
headers[key.downcase]
|
149
|
+
v = headers[key.downcase]
|
150
|
+
v.is_a?(Array) ? v.first : v
|
147
151
|
end
|
148
152
|
|
149
153
|
# Return the response code from this request as an integer. Will call the request if it has not been called yet.
|
@@ -246,7 +250,16 @@ module Manticore
|
|
246
250
|
@response = response
|
247
251
|
@code = response.get_status_line.get_status_code
|
248
252
|
@message = response.get_status_line.get_reason_phrase
|
249
|
-
@headers =
|
253
|
+
@headers = response.get_all_headers.each_with_object({}) do |h, o|
|
254
|
+
key = h.get_name.downcase
|
255
|
+
if o.key?(key)
|
256
|
+
o[key] = Array(o[key]) unless o[key].is_a?(Array)
|
257
|
+
o[key].push h.get_value
|
258
|
+
else
|
259
|
+
o[key] = h.get_value
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
250
263
|
@callback_result = @handlers[:success].call(self)
|
251
264
|
nil
|
252
265
|
end
|
data/lib/manticore/version.rb
CHANGED
@@ -24,6 +24,12 @@ describe Manticore::Client do
|
|
24
24
|
expect(json["headers"]["X-Custom-Header"]).to eq "Blaznotts"
|
25
25
|
end
|
26
26
|
|
27
|
+
it "accepts repeated header values" do
|
28
|
+
response = client.get(local_server, headers: {"X-Custom-Header" => ["Whizzles", "Blaznotts"]})
|
29
|
+
json = JSON.load(response.body)
|
30
|
+
expect(json["headers"]["X-Custom-Header"].sort).to eq ["Blaznotts", "Whizzles"]
|
31
|
+
end
|
32
|
+
|
27
33
|
it "enables compression" do
|
28
34
|
response = client.get(local_server)
|
29
35
|
json = JSON.load(response.body)
|
@@ -46,6 +52,35 @@ describe Manticore::Client do
|
|
46
52
|
expect(j["uri"]["port"]).to eq 55441
|
47
53
|
end
|
48
54
|
|
55
|
+
context "via an authenticated proxy" do
|
56
|
+
let(:proxy) { "http://localhost:55442" }
|
57
|
+
let(:auth) { nil }
|
58
|
+
let(:req) { client.get(local_server("/authproxy"), proxy: proxy, auth: auth) }
|
59
|
+
let(:j) { JSON.parse req.body }
|
60
|
+
|
61
|
+
context "with authentication as a hash" do
|
62
|
+
let(:auth) { {user: "user", pass: "pass"} }
|
63
|
+
|
64
|
+
it "proxies" do
|
65
|
+
expect(j["server_port"]).to eq 55442
|
66
|
+
expect(j["uri"]["port"]).to eq 55441
|
67
|
+
expect(j["headers"]["Proxy-Authorization"]).to eq "Basic dXNlcjpwYXNz"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "with authentication as a string" do
|
72
|
+
let(:proxy) { "http://user:pass@localhost:55442"}
|
73
|
+
|
74
|
+
it "proxies" do
|
75
|
+
expect(j["server_port"]).to eq 55442
|
76
|
+
expect(j["uri"]["port"]).to eq 55441
|
77
|
+
expect(j["headers"]["Proxy-Authorization"]).to eq "Basic dXNlcjpwYXNz"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
it "proxies with authentication as a hash" do
|
82
|
+
end
|
83
|
+
|
49
84
|
describe "with a custom user agent" do
|
50
85
|
let(:client) { Manticore::Client.new user_agent: "test-agent/1.0" }
|
51
86
|
|
@@ -368,6 +403,11 @@ describe Manticore::Client do
|
|
368
403
|
expect(JSON.load(response.body)["method"]).to eq "GET"
|
369
404
|
end
|
370
405
|
|
406
|
+
it "works with a URI object" do
|
407
|
+
response = client.get(URI.parse local_server)
|
408
|
+
expect(JSON.load(response.body)["method"]).to eq "GET"
|
409
|
+
end
|
410
|
+
|
371
411
|
it "send a query" do
|
372
412
|
response = client.get local_server, query: {foo: "bar"}
|
373
413
|
expect(CGI.parse(JSON.load(response.body)["uri"]["query"])["foo"]).to eq ["bar"]
|
@@ -438,10 +478,10 @@ describe Manticore::Client do
|
|
438
478
|
end
|
439
479
|
|
440
480
|
it "sends an arbitrary entity" do
|
441
|
-
f = open(__FILE__, "r").to_inputstream
|
481
|
+
f = open(File.expand_path(File.join(__FILE__, "..", "..", "spec_helper.rb")), "r").to_inputstream
|
442
482
|
multipart_entity = MultipartEntityBuilder.create.add_text_body("foo", "bar").add_binary_body("whatever", f , ContentType::TEXT_PLAIN, __FILE__)
|
443
483
|
response = client.post(local_server, entity: multipart_entity.build)
|
444
|
-
expect(response.body).to match "
|
484
|
+
expect(response.body).to match "RSpec.configure"
|
445
485
|
end
|
446
486
|
end
|
447
487
|
|
@@ -664,7 +704,7 @@ describe Manticore::Client do
|
|
664
704
|
"Hello!"
|
665
705
|
].join("\n"))
|
666
706
|
client.close
|
667
|
-
rescue
|
707
|
+
rescue IOError => e
|
668
708
|
end
|
669
709
|
end
|
670
710
|
end
|
@@ -714,7 +754,11 @@ describe Manticore::Client do
|
|
714
754
|
|
715
755
|
after do
|
716
756
|
Thread.kill @server
|
717
|
-
|
757
|
+
begin
|
758
|
+
@socket.close
|
759
|
+
rescue IOError
|
760
|
+
# pass
|
761
|
+
end
|
718
762
|
end
|
719
763
|
end
|
720
764
|
|
@@ -12,6 +12,18 @@ describe Manticore::Response do
|
|
12
12
|
expect(subject["Content-Type"]).to eq "text/plain"
|
13
13
|
end
|
14
14
|
|
15
|
+
context "when a response contains repeated headers" do
|
16
|
+
subject { client.get( local_server "/repeated_headers") }
|
17
|
+
|
18
|
+
it "returns an array of values for headers with multiple occurrances" do
|
19
|
+
expect(subject.headers["link"]).to eq ["foo", "bar"]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns only the first value when using response#[]" do
|
23
|
+
expect(subject["Link"]).to eq "foo"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
15
27
|
it "reads the body" do
|
16
28
|
expect(subject.body).to match "Manticore"
|
17
29
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -15,6 +15,7 @@ PORT = 55441
|
|
15
15
|
def local_server(path = "/", port = PORT)
|
16
16
|
URI.join("http://localhost:#{port}", path).to_s
|
17
17
|
end
|
18
|
+
Thread.abort_on_exception = true
|
18
19
|
|
19
20
|
def read_nonblock(socket)
|
20
21
|
buffer = ""
|
@@ -32,7 +33,7 @@ end
|
|
32
33
|
def start_server(port = PORT)
|
33
34
|
@servers ||= {}
|
34
35
|
@servers[port] = Thread.new {
|
35
|
-
Net::HTTP::Server.run(port: port, log:
|
36
|
+
Net::HTTP::Server.run(port: port, log: open("/dev/null", "a")) do |request, stream|
|
36
37
|
|
37
38
|
query = Rack::Utils.parse_query(request[:uri][:query].to_s)
|
38
39
|
if query["sleep"]
|
@@ -64,9 +65,19 @@ def start_server(port = PORT)
|
|
64
65
|
elsif request[:uri][:path] == "/proxy"
|
65
66
|
payload = JSON.dump(request.merge(server_port: port))
|
66
67
|
[200, {'Content-Type' => content_type, "Content-Length" => payload.length}, [payload]]
|
68
|
+
elsif request[:uri][:path] == "/authproxy"
|
69
|
+
payload = JSON.dump(request.merge(server_port: port))
|
70
|
+
if request[:headers]["Proxy-Authorization"] == "Basic dXNlcjpwYXNz"
|
71
|
+
[200, {'Content-Type' => content_type, "Content-Length" => payload.length}, [payload]]
|
72
|
+
else
|
73
|
+
[407, {'Proxy-Authenticate' => 'Basic realm="localhost'}, [payload]]
|
74
|
+
end
|
67
75
|
elsif request[:uri][:path] == "/keepalive"
|
68
76
|
payload = JSON.dump(request.merge(server_port: port))
|
69
77
|
[200, {'Content-Type' => content_type, "Content-Length" => payload.length, "Keep-Alive" => "timeout=60"}, [payload]]
|
78
|
+
elsif request[:uri][:path] == "/repeated_headers"
|
79
|
+
payload = JSON.dump(request.merge(server_port: port))
|
80
|
+
[200, {'Link' => ["foo", "bar"]}, [payload]]
|
70
81
|
elsif request[:headers]["X-Redirect"] && request[:uri][:path] != request[:headers]["X-Redirect"]
|
71
82
|
[301, {"Location" => local_server( request[:headers]["X-Redirect"] )}, [""]]
|
72
83
|
else
|
@@ -75,7 +86,6 @@ def start_server(port = PORT)
|
|
75
86
|
io = Zlib::GzipWriter.new(out, 2)
|
76
87
|
|
77
88
|
request[:body] = Base64.encode64(request[:body]) if request[:headers]["X-Base64"]
|
78
|
-
|
79
89
|
io.write JSON.dump(request)
|
80
90
|
io.close
|
81
91
|
payload = out.string
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manticore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Chris Heald
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ requirements:
|
|
122
122
|
- jar commons-codec:commons-codec, '~> 1.9'
|
123
123
|
- jar org.apache.httpcomponents:httpcore, '~> 4.4.4'
|
124
124
|
rubyforge_project:
|
125
|
-
rubygems_version: 2.4
|
125
|
+
rubygems_version: 2.6.4
|
126
126
|
signing_key:
|
127
127
|
specification_version: 4
|
128
128
|
summary: Manticore is an HTTP client built on the Apache HttpCore components
|