manticore 0.6.3-java → 0.8.0-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8b96d1eb1f7f1e5b6885a5f08e24ba394ac9fac0
4
- data.tar.gz: 1ff15070f745905119d536ae7df328ce845990a6
2
+ SHA256:
3
+ metadata.gz: 063b0fd32e3dfbee4335d04293e098e8b1bc054ecd727ff51011e6eef3675c4b
4
+ data.tar.gz: 8a5da3e5e6433d7d57e388069e95393fbc66220f1695ab7b1443f9dc49f84d11
5
5
  SHA512:
6
- metadata.gz: 1f08d3632cbe683ce2456e4cde41d05545bdf5926992067f06f25af1477d9a31bac90d797a88a4f4d4a7a56477afd9f725981958ac3082e501c18199da4875b3
7
- data.tar.gz: d2231b58a53b86bd77af5c2f27f79d9a4ece0d72cffbace8c1a830fefcd33a84f5c710f93d1e55e76637ab48d5966c79f466ee40c911418a59e4ce440576a8c7
6
+ metadata.gz: db22357ef64973e1452bb970dbb2d7a6c960c895db7d0afe1ae96339f414a06dba8c1039b7f5d3d0ce493443317a9d72c7dce04e7c7fbab98704e55e124d2766
7
+ data.tar.gz: 6744d52a35f0e94d23db237b9f364353eeec4bb3667eb35a06620cf16b676e5b49bd76bb12ba7296f6924b2b7ae052cb4f1d443a6f1e87b00d32b9d1af60c507
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,42 @@
1
+ .default: &default
2
+ variables:
3
+ TERM: xterm-256color
4
+ JRUBY_OPTS: --debug
5
+ cache:
6
+ paths:
7
+ - bundler --path vendor/bundle
8
+ - $HOME/.m2
9
+ before_script:
10
+ - apt update && apt install -y git
11
+ - gem install ruby-maven
12
+ - bundle install --path vendor/bundle
13
+ script:
14
+ - bundle exec rake
15
+
16
+ test jruby-9.2:
17
+ <<: *default
18
+ image: jruby:9.2
19
+ artifacts:
20
+ expire_in: 3 days
21
+ paths:
22
+ - coverage
23
+
24
+ test jruby-9.1:
25
+ <<: *default
26
+ image: jruby:9.1
27
+
28
+ test jruby-1.7:
29
+ <<: *default
30
+ image: jruby:1.7
31
+
32
+ pages:
33
+ stage: deploy
34
+ only:
35
+ - master
36
+ artifacts:
37
+ expire_in: 3 days
38
+ paths:
39
+ - public
40
+ script:
41
+ - mkdir -p public
42
+ - mv coverage/ public/coverage/
data/.travis.yml CHANGED
@@ -1,23 +1,22 @@
1
+ dist: trusty # due Oracle JDK
1
2
  language: ruby
2
- sudo: false
3
3
  cache:
4
4
  - bundler
5
5
  - directories:
6
6
  - $HOME/.m2
7
7
  rvm:
8
- - jruby-1.7
9
- - jruby-9.0.5.0
8
+ - jruby-9.2.19.0 # Ruby 2.5
10
9
  jdk:
11
10
  - oraclejdk8
12
- - openjdk7
11
+ - openjdk8
12
+ - openjdk11
13
13
  before_install:
14
- - gem install ruby-maven bundler
15
- - bundle install
14
+ - gem install bundler -v 1.17.3
16
15
  matrix:
17
16
  include:
18
- - rvm: jruby-9.2.0.0
19
- jdk: oraclejdk8
20
17
  - rvm: jruby-head
21
- jdk: oraclejdk8
18
+ jdk: openjdk11
19
+ - rvm: jruby-9.1.17.0 # Ruby 2.3
20
+ jdk: openjdk8
22
21
  allow_failures:
23
22
  - rvm: jruby-head
data/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
+ ### v0.8.0
2
+
3
+ * [feat] restore compat with (legacy) verify: false (#102)
4
+ * Accept untrusted certs when SSL verify is disabled (#100)
5
+ * [deps] update http-client to 4.5.13 (#99)
6
+
7
+ ## v0.7
8
+
9
+ ### v0.7.1
10
+
11
+ * Don't override certificates with same Subject (#93)
12
+ * Set Java cause for ManticoreException types (#96)
13
+ * Fix SSL handshake hang indefinitely (#98)
14
+
15
+ ### v0.7.0
16
+
17
+ * Drop support for JRuby 1.7. It probably still works, but we don't test against it anymore
18
+ * Fix a thread safety issue with regards to adding requests to the parallel execution queue while the client is already processing a queue (#80)
19
+
1
20
  ## v0.6
2
21
 
22
+ ### v0.6.4
23
+
24
+ * client_cert and client_key now take the literal keys as strings, OpenSSL::X509::Certificate/OpenSSL::PKey::Pkey instances, or key file paths. (#77)
25
+ * Reduced unnecessary string copying (!78 - thanks @kares)
26
+
27
+ ### v0.6.2-v0.6.3
28
+
29
+ * Fixed the use of authentication information in proxy URLs (#71)
30
+ * Changed the default encoding to UTF-8 when a response MIME is application/json (#70)
31
+
3
32
  ### v0.6.1
4
33
 
5
34
  * 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)
data/Gemfile CHANGED
@@ -8,7 +8,9 @@ group :development, :test do
8
8
  gem "rspec", "~> 3.0"
9
9
  gem "rspec-its"
10
10
  gem "httpclient", "~> 2.3"
11
- gem "rack", "~> 1.5"
11
+ gem "rack", ">= 2.1.4"
12
12
  gem "rake-compiler"
13
13
  gem "gserver"
14
- end
14
+ gem "simplecov"
15
+ gem "json"
16
+ end
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Manticore
2
2
 
3
- [![Build Status](https://travis-ci.org/cheald/manticore.svg?branch=master)](https://travis-ci.org/cheald/manticore)
3
+ **Note**: While I'll continue to maintain the library here, I've moved the canonical copy to Gitlab at https://gitlab.com/cheald/manticore - it is preferred that you submit issues and PRs there.
4
+
5
+ [![Build Status](https://app.travis-ci.com/cheald/manticore.svg?branch=master)](https://app.travis-ci.com/cheald/manticore)
4
6
 
5
7
  Manticore is a fast, robust HTTP client built on the Apache HTTPClient libraries. It is only compatible with JRuby.
6
8
 
@@ -88,7 +90,11 @@ For detailed documentation, see the [full Manticore::Client documentation](http:
88
90
  Rather than using the Facade, you can create your own standalone Client instances. When you create a `Client`, you will pass various parameters that it will use to set up the pool.
89
91
 
90
92
  ```ruby
91
- client = Manticore::Client.new(request_timeout: 5, connect_timeout: 5, socket_timeout: 5, pool_max: 10, pool_max_per_route: 2)
93
+ client = Manticore::Client.new(request_timeout: 5,
94
+ connect_timeout: 5,
95
+ socket_timeout: 5,
96
+ pool_max: 10,
97
+ pool_max_per_route: 2)
92
98
  ```
93
99
 
94
100
  Then, you can make requests from the client. Pooling and route maximum constraints are automatically managed:
@@ -120,11 +126,20 @@ per-route concurrency limits, and other neat things. In general, you should crea
120
126
  To set this up, you might create 2 pools, each configured for the task:
121
127
 
122
128
  ```ruby
123
- general_http_client = Manticore::Client.new connect_timeout: 10, socket_timeout: 10, request_timeout: 10, follow_redirects: true, max_per_route: 2
129
+ general_http_client = Manticore::Client.new(connect_timeout: 10,
130
+ socket_timeout: 10,
131
+ request_timeout: 10,
132
+ follow_redirects: true,
133
+ max_per_route: 2)
124
134
  # With an OpenSSL CA store
125
- proxied_backend_client = Manticore::Client.new proxy: "https://backend.internal:4242", ssl: {ca_file: "my_certs.pem"}
135
+ proxied_backend_client = Manticore::Client.new(proxy: "https://backend.internal:4242",
136
+ ssl: { ca_file: "my_certs.pem" })
126
137
  # Or with a .jks truststore
127
- # proxied_backend_client = Manticore::Client.new proxy: "https://backend.internal:4242", ssl: {truststore: "./truststore.jks", truststore_password: "s3cr3t"}
138
+ proxied_backend_client = Manticore::Client.new(proxy: "https://backend.internal:4242",
139
+ ssl: {
140
+ truststore: "./truststore.jks",
141
+ truststore_password: "s3cr3t"
142
+ })
128
143
  ```
129
144
 
130
145
  This would create 2 separate request pools; the first would be configured with generous timeouts and redirect following, and would use the system
data/Rakefile CHANGED
@@ -36,6 +36,7 @@ task :generate_certs do
36
36
  # Create the CA
37
37
  "#{openssl} genrsa 4096 | #{openssl} pkcs8 -topk8 -nocrypt -out #{root}/root-ca.key",
38
38
  "#{openssl} req -sha256 -x509 -newkey rsa:4096 -nodes -key #{root}/root-ca.key -sha256 -days 365 -out #{root}/root-ca.crt -subj \"/C=US/ST=The Internet/L=The Internet/O=Manticore CA/OU=Manticore/CN=localhost\"",
39
+ "#{openssl} req -sha256 -x509 -newkey rsa:4096 -nodes -key #{root}/root-ca.key -sha256 -days 365 -out #{root}/root-untrusted-ca.crt -subj \"/C=US/ST=The Darknet/L=The Darknet/O=Manticore CA/OU=Manticore/CN=localhost\"",
39
40
 
40
41
  # Create the client CSR, key, and signed cert
41
42
  "#{openssl} genrsa 4096 | #{openssl} pkcs8 -topk8 -nocrypt -out #{root}/client.key",
@@ -48,6 +49,7 @@ task :generate_certs do
48
49
  "#{openssl} req -sha256 -key #{root}/host.key -newkey rsa:4096 -out #{root}/host.csr -subj \"/C=US/ST=The Internet/L=The Internet/O=Manticore Host/OU=Manticore/CN=localhost\"",
49
50
  "#{openssl} x509 -req -in #{root}/host.csr -CA #{root}/root-ca.crt -CAkey #{root}/root-ca.key -CAcreateserial -out #{root}/host.crt -sha256 -days 1",
50
51
  "#{openssl} x509 -req -in #{root}/host.csr -CA #{root}/root-ca.crt -CAkey #{root}/root-ca.key -CAcreateserial -out #{root}/host-expired.crt -sha256 -days -7",
52
+ "#{openssl} x509 -req -in #{root}/host.csr -CA #{root}/root-untrusted-ca.crt -CAkey #{root}/root-ca.key -CAcreateserial -out #{root}/host-untrusted.crt -sha256 -days 1",
51
53
 
52
54
  "#{keytool} -import -file #{root}/root-ca.crt -alias rootCA -keystore #{root}/truststore.jks -noprompt -storepass test123",
53
55
  "#{openssl} pkcs12 -export -clcerts -out #{root}/client.p12 -inkey #{root}/client.key -in #{root}/client.crt -certfile #{root}/root-ca.crt -password pass:test123",
@@ -66,7 +66,7 @@ public class Manticore implements Library {
66
66
 
67
67
  private IRubyObject readWholeEntity(ThreadContext context, HttpEntity entity, Encoding encoding) throws IOException {
68
68
  ByteList bl = new ByteList(EntityUtils.toByteArray(entity), false);
69
- return RubyString.newStringShared(context.getRuntime(), bl, encoding);
69
+ return RubyString.newString(context.getRuntime(), bl, encoding);
70
70
  }
71
71
 
72
72
  private IRubyObject streamEntity(ThreadContext context, HttpEntity entity, Encoding encoding, Block block) throws IOException {
@@ -86,7 +86,7 @@ public class Manticore implements Library {
86
86
  byte[] tmp = new byte[4096];
87
87
  int l;
88
88
  while((l = instream.read(tmp)) != -1) {
89
- block.call( context, RubyString.newString(context.getRuntime(), new ByteList(tmp, 0, l, true), encoding) );
89
+ block.call( context, RubyString.newStringShared(context.getRuntime(), new ByteList(tmp, 0, l, false), encoding) );
90
90
  }
91
91
  } finally {
92
92
  instream.close();
@@ -94,4 +94,4 @@ public class Manticore implements Library {
94
94
  return context.nil;
95
95
  }
96
96
  }
97
- }
97
+ }
@@ -20,17 +20,12 @@ module Faraday
20
20
  ParallelManager.new
21
21
  end
22
22
 
23
- def initialize(app, connection_options = {})
24
- @connection_options = connection_options
25
- super(app)
26
- end
27
-
28
23
  def client(env)
29
24
  @client ||= begin
30
25
  opts = {}
31
26
  if ssl = env[:ssl].to_hash
32
27
  opts[:ssl] = {}
33
- opts[:ssl][:verify] = :disable if ssl[:verify] == false
28
+ opts[:ssl][:verify] = ssl[:verify] unless ssl[:verify].nil?
34
29
  opts[:ssl][:ca_file] = ssl[:ca_file]
35
30
  opts[:ssl][:client_cert] = ssl[:client_cert]
36
31
  opts[:ssl][:client_key] = ssl[:client_key]
@@ -1,6 +1,7 @@
1
1
  require "thread"
2
2
  require "base64"
3
3
  require "weakref"
4
+ require "openssl_pkcs8_pure"
4
5
 
5
6
  module Manticore
6
7
  # @!macro [new] http_method_shared
@@ -68,10 +69,8 @@ module Manticore
68
69
  include_package "org.apache.http.client.config"
69
70
  include_package "org.apache.http.config"
70
71
  include_package "org.apache.http.conn.socket"
71
- include_package "org.apache.http.impl"
72
72
  include_package "org.apache.http.impl.client"
73
73
  include_package "org.apache.http.impl.conn"
74
- include_package "org.apache.http.impl.auth"
75
74
  include_package "org.apache.http.entity"
76
75
  include_package "org.apache.http.message"
77
76
  include_package "org.apache.http.params"
@@ -79,16 +78,21 @@ module Manticore
79
78
  include_package "org.apache.http.auth"
80
79
  include_package "java.util.concurrent"
81
80
  include_package "org.apache.http.client.protocol"
82
- include_package "org.apache.http.conn.ssl"
83
81
  include_package "java.security.cert"
84
82
  include_package "java.security.spec"
85
83
  include_package "java.security"
86
- include_package "org.apache.http.client.utils"
87
84
  java_import "org.apache.http.HttpHost"
88
85
  java_import "javax.net.ssl.SSLContext"
89
86
  java_import "org.manticore.HttpGetWithEntity"
90
87
  java_import "org.manticore.HttpDeleteWithEntity"
91
88
  java_import "org.apache.http.auth.UsernamePasswordCredentials"
89
+ java_import "org.apache.http.conn.ssl.SSLConnectionSocketFactory"
90
+ java_import "org.apache.http.conn.ssl.SSLContextBuilder"
91
+ java_import "org.apache.http.conn.ssl.TrustAllStrategy"
92
+ java_import "org.apache.http.conn.ssl.TrustSelfSignedStrategy"
93
+ java_import "org.apache.http.client.utils.URIBuilder"
94
+ java_import "org.apache.http.impl.DefaultConnectionReuseStrategy"
95
+ java_import "org.apache.http.impl.auth.BasicScheme"
92
96
 
93
97
  # This is a class rather than a proc because the proc holds a closure around
94
98
  # the instance of the Client that creates it.
@@ -169,8 +173,8 @@ module Manticore
169
173
  # @option options [String] ssl[:keystore_password] (nil) Password used for decrypting the client auth key store
170
174
  # @option options [String] ssl[:keystore_type] (nil) Format of the key store, ie "JKS" or "PKCS12". If left nil, the type will be inferred from the keystore filename.
171
175
  # @option options [String] ssl[:ca_file] (nil) OpenSSL-style path to an X.509 certificate to use to validate SSL certificates
172
- # @option options [String] ssl[:client_cert] (nil) OpenSSL-style path to an X.509 certificate to use for client authentication
173
- # @option options [String] ssl[:client_key] (nil) OpenSSL-style path to an RSA key to use for client authentication
176
+ # @option options [String|OpenSSL::X509::Certificate] ssl[:client_cert] (nil) A string containing a base64-encoded X.509 certificate, OR a path to an OpenSSL-style X.509 certificate, OR an instance of OpenSSL::X509::Certificate
177
+ # @option options [String|OpenSSL::PKey::Pkey] ssl[:client_key] (nil) A string containing a base64-encoded RSA key to use for client authentication, OR a path to an OpenSSL-style RSA key, OR an instance of OpenSSL::PKey::PKey
174
178
  # @option options [boolean] ssl[:track_state] (false) Turn on or off connection state tracking. This helps prevent SSL information from leaking across threads, but means that connections
175
179
  # can't be shared across those threads. This should generally be left off unless you know what you're doing.
176
180
  def initialize(options = {})
@@ -200,11 +204,7 @@ module Manticore
200
204
  builder.set_connection_reuse_strategy DefaultConnectionReuseStrategy.new
201
205
  end
202
206
 
203
- socket_config_builder = SocketConfig.custom
204
- socket_config_builder.set_so_timeout(options.fetch(:socket_timeout, DEFAULT_SOCKET_TIMEOUT) * 1000)
205
- socket_config_builder.set_tcp_no_delay(options.fetch(:tcp_no_delay, true))
206
- builder.set_default_socket_config socket_config_builder.build
207
-
207
+ builder.set_default_socket_config socket_config_from_options(options)
208
208
  builder.set_connection_manager pool(options)
209
209
 
210
210
  request_config = RequestConfig.custom
@@ -222,7 +222,7 @@ module Manticore
222
222
  @client = builder.build
223
223
  finalize @client, :close
224
224
  @options = options
225
- @async_requests = []
225
+ @async_requests = Queue.new
226
226
  @stubs = {}
227
227
  end
228
228
 
@@ -333,8 +333,9 @@ module Manticore
333
333
  # @return [Array] An array of the responses from the requests executed.
334
334
  def execute!
335
335
  method = executor.java_method(:submit, [java.util.concurrent.Callable.java_class])
336
- result = @async_requests.map { |r| method.call r }
337
- @async_requests.clear
336
+
337
+ result = []
338
+ result << method.call(@async_requests.pop) until @async_requests.empty?
338
339
  result.map do |future|
339
340
  begin
340
341
  future.get
@@ -385,11 +386,13 @@ module Manticore
385
386
  def pool_builder(options)
386
387
  http_sf = PlainConnectionSocketFactory.new
387
388
 
389
+ # :nocov:
388
390
  if options[:ignore_ssl_validation]
389
391
  $stderr.puts "The options[:ignore_ssl_validation] setting is deprecated in favor of options[:ssl][:verify]"
390
392
  options[:ssl] ||= {}
391
393
  options[:ssl] = {:verify => !options.delete(:ignore_ssl_validation)}.merge(options[:ssl])
392
394
  end
395
+ # :nocov:
393
396
 
394
397
  https_sf = ssl_socket_factory_from_options options.fetch(:ssl, {})
395
398
  registry = RegistryBuilder.create.register("http", http_sf).register("https", https_sf).build
@@ -403,10 +406,19 @@ module Manticore
403
406
  cm.set_validate_after_inactivity options.fetch(:check_connection_timeout, 2_000)
404
407
  cm.set_default_max_per_route options.fetch(:pool_max_per_route, @max_pool_size)
405
408
  cm.set_max_total @max_pool_size
409
+ cm.set_default_socket_config socket_config_from_options(options)
410
+
406
411
  finalize cm, :shutdown
407
412
  end
408
413
  end
409
414
  end
415
+
416
+ def socket_config_from_options(options)
417
+ socket_config_builder = SocketConfig.custom
418
+ socket_config_builder.set_so_timeout(options.fetch(:socket_timeout, DEFAULT_SOCKET_TIMEOUT) * 1000)
419
+ socket_config_builder.set_tcp_no_delay(options.fetch(:tcp_no_delay, true))
420
+ socket_config_builder.build
421
+ end
410
422
 
411
423
  def create_executor_if_needed
412
424
  return @executor if @executor
@@ -506,7 +518,7 @@ module Manticore
506
518
 
507
519
  if @use_cookies == :per_request
508
520
  store = BasicCookieStore.new
509
- context.setAttribute(ClientContext.COOKIE_STORE, store)
521
+ context.setAttribute(ClientContext::COOKIE_STORE, store)
510
522
  end
511
523
 
512
524
  return req, context
@@ -600,11 +612,14 @@ module Manticore
600
612
  def ssl_socket_factory_from_options(ssl_options)
601
613
  trust_store = trust_strategy = nil
602
614
 
603
- verifier = SSLConnectionSocketFactory::STRICT_HOSTNAME_VERIFIER
604
615
  case ssl_options.fetch(:verify, :strict)
605
- when false, :disable, :none
616
+ when false
617
+ trust_store = nil
618
+ trust_strategy = TrustSelfSignedStrategy::INSTANCE
619
+ verifier = SSLConnectionSocketFactory::ALLOW_ALL_HOSTNAME_VERIFIER
620
+ when :disable, :none
606
621
  trust_store = nil
607
- trust_strategy = TrustSelfSignedStrategy.new
622
+ trust_strategy = TrustAllStrategy::INSTANCE
608
623
  verifier = SSLConnectionSocketFactory::ALLOW_ALL_HOSTNAME_VERIFIER
609
624
  when :browser
610
625
  verifier = SSLConnectionSocketFactory::BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
@@ -614,7 +629,7 @@ module Manticore
614
629
  raise "Invalid value for :verify. Valid values are (:all, :browser, :default)"
615
630
  end
616
631
 
617
- context = SSLContexts.custom
632
+ context = SSLContextBuilder.new
618
633
  setup_trust_store ssl_options, context, trust_strategy
619
634
  setup_key_store ssl_options, context
620
635
 
@@ -629,8 +644,8 @@ module Manticore
629
644
  trust_store ||= blank_keystore
630
645
  open(ssl_options[:ca_file]) do |fp|
631
646
  cert_collection = CertificateFactory.get_instance("X509").generate_certificates(fp.to_inputstream).to_a
632
- cert_collection.each do |cert|
633
- trust_store.set_certificate_entry(cert.getSubjectX500Principal.name, cert)
647
+ cert_collection.each_with_index do |cert, i|
648
+ trust_store.set_certificate_entry("#{i}#" + cert.getSubjectX500Principal.name, cert)
634
649
  end
635
650
  end
636
651
  end
@@ -645,39 +660,44 @@ module Manticore
645
660
  keystore_password = (ssl_options[:keystore_password] || "").to_java.toCharArray
646
661
 
647
662
  # Support OpenSSL-style bare X.509 certs with an RSA key
648
- # This is really dumb - we have to b64-decode the key ourselves, and we can only support PKCS8
649
663
  if ssl_options[:client_cert] && ssl_options[:client_key]
650
664
  key_store ||= blank_keystore
651
665
  certs, key = nil, nil
652
- open(ssl_options[:client_cert]) do |fp|
653
- certs = CertificateFactory.get_instance("X509").generate_certificates(fp.to_inputstream).to_array([].to_java(Certificate))
654
- end
666
+
667
+ cert_str = if ssl_options[:client_cert].is_a?(OpenSSL::X509::Certificate)
668
+ ssl_options[:client_cert].to_s
669
+ elsif ssl_options[:client_cert].is_a?(String) && File.exists?(ssl_options[:client_cert])
670
+ File.read(ssl_options[:client_cert])
671
+ else
672
+ ssl_options[:client_cert].to_s
673
+ end
674
+
675
+ cert_stream = java.io.ByteArrayInputStream.new(cert_str.strip.to_java_bytes)
676
+ certs = CertificateFactory.get_instance("X509").generate_certificates(cert_stream).to_array([].to_java(Certificate))
677
+
678
+ key_str = if ssl_options[:client_key].is_a?(OpenSSL::PKey::PKey)
679
+ ssl_options[:client_key].to_pem_pkcs8
680
+ elsif ssl_options[:client_key].is_a?(String) && File.exists?(ssl_options[:client_key])
681
+ File.read(ssl_options[:client_key])
682
+ else
683
+ ssl_options[:client_key].to_s
684
+ end
655
685
 
656
686
  # Add each of the keys in the given keyfile into the keystore.
657
- open(ssl_options[:client_key]) do |fp|
658
- key_parts = fp.read.scan(KEY_EXTRACTION_REGEXP)
659
- key_parts.each do |type, b64key|
660
- body = Base64.decode64 b64key
661
- spec = PKCS8EncodedKeySpec.new(body.to_java_bytes)
662
- type = type.strip
663
- type = "RSA" if type == ""
664
- key = KeyFactory.getInstance(type).generatePrivate(spec)
665
- key_store.set_key_entry("key-#{Digest::SHA1.hexdigest(body)}", key, keystore_password, certs)
666
- end
687
+ key_parts = key_str.scan(KEY_EXTRACTION_REGEXP)
688
+ key_parts.each do |type, b64key|
689
+ body = Base64.decode64 b64key
690
+ spec = PKCS8EncodedKeySpec.new(body.strip.to_java_bytes)
691
+ type = type.strip
692
+ type = "RSA" if type == ""
693
+ key = KeyFactory.getInstance(type).generatePrivate(spec)
694
+ key_store.set_key_entry("key-#{Digest::SHA1.hexdigest(body)}", key, keystore_password, certs)
667
695
  end
668
696
  end
669
697
 
670
698
  context.load_key_material(key_store, keystore_password) if key_store
671
699
  end
672
700
 
673
- def get_trust_store(options)
674
- get_store :truststore, options
675
- end
676
-
677
- def get_key_store(options)
678
- get_store :keystore, options
679
- end
680
-
681
701
  def get_store(prefix, options)
682
702
  KeyStore.get_instance(options[:"#{prefix}_type"] || guess_store_type(options[prefix])).tap do |store|
683
703
  instream = open(options[prefix], "rb").to_inputstream
@@ -11,14 +11,13 @@ module Manticore
11
11
  # @!attribute [r] callback_result
12
12
  # @return Value returned from any given on_success/response block
13
13
  class Response
14
- include_package "org.apache.http.client"
15
- include_package "org.apache.http.util"
16
- include_package "org.apache.http.protocol"
14
+
15
+ java_import "org.apache.http.client.ResponseHandler"
17
16
  java_import "org.apache.http.client.protocol.HttpClientContext"
18
- java_import "java.util.concurrent.Callable"
17
+ java_import "org.apache.http.protocol.ExecutionContext"
19
18
 
20
- include ResponseHandler
21
- include Callable
19
+ include org.apache.http.client.ResponseHandler
20
+ include java.util.concurrent.Callable
22
21
 
23
22
  attr_accessor :background
24
23
  attr_reader :context, :request, :callback_result, :called, :future
@@ -54,15 +53,16 @@ module Manticore
54
53
  ex = Manticore::ConnectTimeout
55
54
  rescue Java::JavaNet::SocketException => e
56
55
  ex = Manticore::SocketException
57
- rescue Java::OrgApacheHttpClient::ClientProtocolException, Java::JavaxNetSsl::SSLHandshakeException, Java::OrgApacheHttpConn::HttpHostConnectException,
58
- Java::OrgApacheHttp::NoHttpResponseException, Java::OrgApacheHttp::ConnectionClosedException => e
56
+ rescue Java::OrgApacheHttpClient::ClientProtocolException, Java::JavaxNetSsl::SSLHandshakeException,
57
+ Java::OrgApacheHttpConn::HttpHostConnectException, Java::OrgApacheHttp::NoHttpResponseException,
58
+ Java::OrgApacheHttp::ConnectionClosedException => e
59
59
  ex = Manticore::ClientProtocolException
60
60
  rescue Java::JavaNet::UnknownHostException => e
61
61
  ex = Manticore::ResolutionFailure
62
62
  rescue Java::JavaLang::IllegalArgumentException => e
63
63
  ex = Manticore::InvalidArgumentException
64
64
  rescue Java::JavaLang::IllegalStateException => e
65
- if e.message.match(/Connection pool shut down/)
65
+ if (e.message || '').index('Connection pool shut down')
66
66
  ex = Manticore::ClientStoppedException
67
67
  else
68
68
  @exception = e
@@ -75,7 +75,7 @@ module Manticore
75
75
 
76
76
  # TODO: If calling async, execute_complete may fail and then silently swallow exceptions. How do we fix that?
77
77
  if ex || @exception
78
- @exception ||= ex.new(e.cause || e.message)
78
+ @exception ||= ex.new(e)
79
79
  @handlers[:failure].call @exception
80
80
  execute_complete
81
81
  nil
@@ -90,8 +90,8 @@ module Manticore
90
90
  # @return [String]
91
91
  def final_url
92
92
  call_once
93
- last_request = context.get_attribute ExecutionContext.HTTP_REQUEST
94
- last_host = context.get_attribute ExecutionContext.HTTP_TARGET_HOST
93
+ last_request = context.get_attribute ExecutionContext::HTTP_REQUEST
94
+ last_host = context.get_attribute ExecutionContext::HTTP_TARGET_HOST
95
95
  host = last_host.to_uri
96
96
  url = last_request.get_uri
97
97
  URI.join(host, url.to_s)
@@ -1,3 +1,3 @@
1
1
  module Manticore
2
- VERSION = "0.6.3"
2
+ VERSION = "0.8.0"
3
3
  end
data/lib/manticore.rb CHANGED
@@ -5,7 +5,11 @@ require "cgi"
5
5
  require_relative "./manticore_jars.rb"
6
6
  require_relative "./org/manticore/manticore-ext"
7
7
 
8
- org.manticore.Manticore.new.load(JRuby.runtime, false)
8
+ if defined? JRuby::Util.load_ext
9
+ JRuby::Util.load_ext 'org.manticore.Manticore'
10
+ else
11
+ org.manticore.Manticore.new.load(JRuby.runtime, false)
12
+ end
9
13
 
10
14
  require_relative "./manticore/version"
11
15
 
@@ -13,7 +17,27 @@ require_relative "./manticore/version"
13
17
  # with the beauty of Ruby.
14
18
  module Manticore
15
19
  # General base class for all Manticore exceptions
16
- class ManticoreException < StandardError; end
20
+ class ManticoreException < StandardError
21
+ def initialize(arg = nil)
22
+ case arg
23
+ when nil
24
+ @_cause = nil
25
+ super()
26
+ when java.lang.Throwable
27
+ @_cause = arg
28
+ super(arg.message)
29
+ else
30
+ @_cause = nil
31
+ super(arg)
32
+ end
33
+ end
34
+
35
+ # @return cause which is likely to be a Java exception
36
+ # @overload Exception#cause
37
+ def cause
38
+ @_cause || super
39
+ end
40
+ end
17
41
 
18
42
  # Exception thrown if you attempt to read from a closed Response stream
19
43
  class StreamClosedException < ManticoreException; end
@@ -1,8 +1,18 @@
1
1
  # this is a generated file, to avoid over-writing it just delete this comment
2
- require "jar_dependencies"
2
+ begin
3
+ require 'jar_dependencies'
4
+ rescue LoadError
5
+ require 'commons-logging/commons-logging/1.2/commons-logging-1.2.jar'
6
+ require 'commons-codec/commons-codec/1.15/commons-codec-1.15.jar'
7
+ require 'org/apache/httpcomponents/httpcore/4.4.14/httpcore-4.4.14.jar'
8
+ require 'org/apache/httpcomponents/httpclient/4.5.13/httpclient-4.5.13.jar'
9
+ require 'org/apache/httpcomponents/httpmime/4.5.13/httpmime-4.5.13.jar'
10
+ end
3
11
 
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")
12
+ if defined? Jars
13
+ require_jar 'commons-logging', 'commons-logging', '1.2'
14
+ require_jar 'commons-codec', 'commons-codec', '1.15'
15
+ require_jar 'org.apache.httpcomponents', 'httpcore', '4.4.14'
16
+ require_jar 'org.apache.httpcomponents', 'httpclient', '4.5.13'
17
+ require_jar 'org.apache.httpcomponents', 'httpmime', '4.5.13'
18
+ end
Binary file
data/manticore.gemspec CHANGED
@@ -19,19 +19,23 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
21
 
22
+ spec.required_ruby_version = '>= 2.3' # JRuby >= 9.1
23
+
22
24
  private_key = File.expand_path("~/.gemcert/gem-private_key.pem")
23
25
  if File.exists? private_key
24
26
  spec.signing_key = private_key
25
27
  spec.cert_chain = ['gem-public_cert.pem']
26
28
  end
27
29
 
28
- spec.add_development_dependency "bundler", "~> 1.3"
30
+ spec.add_dependency "openssl_pkcs8_pure"
31
+
32
+ spec.add_development_dependency "bundler"
29
33
  spec.add_development_dependency "rake"
30
- spec.add_development_dependency "jar-dependencies"
34
+ spec.add_development_dependency "jar-dependencies", "~> 0.4.1"
31
35
 
32
- spec.requirements << "jar org.apache.httpcomponents:httpclient, '~> 4.5.0'"
33
- spec.requirements << "jar org.apache.httpcomponents:httpmime, '~> 4.5.0'"
36
+ spec.requirements << "jar org.apache.httpcomponents:httpclient, '~> 4.5.13'"
37
+ spec.requirements << "jar org.apache.httpcomponents:httpmime, '~> 4.5.13'"
34
38
  spec.requirements << "jar commons-logging:commons-logging, '~> 1.2'"
35
39
  spec.requirements << "jar commons-codec:commons-codec, '~> 1.9'"
36
- spec.requirements << "jar org.apache.httpcomponents:httpcore, '~> 4.4.4'"
40
+ spec.requirements << "jar org.apache.httpcomponents:httpcore, '~> 4.4.14'"
37
41
  end
@@ -130,7 +130,13 @@ describe Manticore::Client do
130
130
  let(:client) { Manticore::Client.new :ssl => {:verify => :strict} }
131
131
 
132
132
  it "breaks on SSL validation errors" do
133
- expect { client.get("https://localhost:55444/").call }.to raise_exception(Manticore::ClientProtocolException)
133
+ begin
134
+ client.get("https://localhost:55445/").body
135
+ rescue Manticore::ClientProtocolException => e
136
+ expect( e.cause ).to be_a javax.net.ssl.SSLHandshakeException
137
+ else
138
+ fail "exception not raised"
139
+ end
134
140
  end
135
141
  end
136
142
 
@@ -166,7 +172,7 @@ describe Manticore::Client do
166
172
  end
167
173
  end
168
174
 
169
- context "when client_cert and client_key are given" do
175
+ context "when client_cert and client_key are given as file paths" do
170
176
  let(:client) {
171
177
  Manticore::Client.new(
172
178
  :ssl => {
@@ -183,6 +189,40 @@ describe Manticore::Client do
183
189
  end
184
190
  end
185
191
 
192
+ context "when client_cert and client_key are given as OpenSSL::X509::Certificate" do
193
+ let(:client) {
194
+ Manticore::Client.new(
195
+ :ssl => {
196
+ verify: :strict,
197
+ ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__),
198
+ client_cert: OpenSSL::X509::Certificate.new(File.read(File.expand_path("../../ssl/client.crt", __FILE__))),
199
+ client_key: OpenSSL::PKey::RSA.new(File.read(File.expand_path("../../ssl/client.key", __FILE__))),
200
+ },
201
+ )
202
+ }
203
+
204
+ it "successfully auths requests" do
205
+ expect(client.get("https://localhost:55445/").body).to match("hello")
206
+ end
207
+ end
208
+
209
+ context "when client_cert and client_key are given as strings" do
210
+ let(:client) {
211
+ Manticore::Client.new(
212
+ :ssl => {
213
+ verify: :strict,
214
+ ca_file: File.expand_path("../../ssl/root-ca.crt", __FILE__),
215
+ client_cert: File.read(File.expand_path("../../ssl/client.crt", __FILE__)),
216
+ client_key: File.read(File.expand_path("../../ssl/client.key", __FILE__)),
217
+ },
218
+ )
219
+ }
220
+
221
+ it "successfully auths requests" do
222
+ expect(client.get("https://localhost:55445/").body).to match("hello")
223
+ end
224
+ end
225
+
186
226
  context "when off" do
187
227
  let(:client) { Manticore::Client.new :ssl => {:verify => :disable} }
188
228
 
@@ -193,6 +233,10 @@ describe Manticore::Client do
193
233
  it "does not break on expired SSL certificates" do
194
234
  expect { client.get("https://localhost:55446/").body }.to_not raise_exception
195
235
  end
236
+
237
+ it "does not break on untrusted certificates" do
238
+ expect { client.get("https://localhost:55447/").body }.to_not raise_exception
239
+ end
196
240
  end
197
241
 
198
242
  context "against a server that verifies clients" do
@@ -529,7 +573,7 @@ describe Manticore::Client do
529
573
  describe "#head" do
530
574
  it "works" do
531
575
  response = client.head(local_server)
532
- expect(JSON.load(response.body)).to be_nil
576
+ expect(response.body).to be_nil
533
577
  end
534
578
  end
535
579
 
@@ -730,11 +774,16 @@ describe Manticore::Client do
730
774
  ].join("\n"))
731
775
  client.close
732
776
  rescue IOError => e
777
+ break
733
778
  end
734
779
  end
735
780
  end
736
781
  end
737
782
 
783
+ after do
784
+ @server.kill
785
+ end
786
+
738
787
  let(:client) { Manticore::Client.new keepalive: true, pool_max: 1 }
739
788
 
740
789
  it "retries 3 times by default" do
@@ -791,7 +840,13 @@ describe Manticore::Client do
791
840
  let(:client) { Manticore::Client.new request_timeout: 1, connect_timeout: 1, socket_timeout: 1 }
792
841
 
793
842
  it "times out" do
794
- expect { client.get(local_server "/?sleep=2").body }.to raise_exception(Manticore::SocketTimeout)
843
+ begin
844
+ client.get(local_server "/?sleep=2").body
845
+ rescue Manticore::SocketTimeout => e
846
+ expect( e.cause ).to be_a java.net.SocketTimeoutException
847
+ else
848
+ fail "exception not raised"
849
+ end
795
850
  end
796
851
 
797
852
  it "times out when custom request options are passed" do
@@ -6,7 +6,7 @@ describe Manticore::Response do
6
6
 
7
7
  its(:headers) { is_expected.to be_a Hash }
8
8
  its(:body) { is_expected.to be_a String }
9
- its(:length) { is_expected.to be_a Fixnum }
9
+ its(:length) { is_expected.to be_a Integer }
10
10
 
11
11
  it "provides response header lookup via #[]" do
12
12
  expect(subject["Content-Type"]).to eq "application/json"
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,12 @@
1
1
  # encoding: utf-8
2
2
  require "rubygems"
3
3
  require "bundler/setup"
4
+ require "simplecov"
5
+
6
+ SimpleCov.start do
7
+ add_filter "spec/"
8
+ end
9
+
4
10
  require "manticore"
5
11
  require "zlib"
6
12
  require "json"
@@ -145,6 +151,7 @@ RSpec.configure do |c|
145
151
  start_ssl_server 55444
146
152
  start_ssl_server 55445, :SSLVerifyClient => OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT, :SSLCACertificateFile => File.expand_path("../ssl/root-ca.crt", __FILE__)
147
153
  start_ssl_server 55446, cert: File.expand_path("../ssl/host-expired.crt", __FILE__)
154
+ start_ssl_server 55447, cert: File.expand_path("../ssl/host-untrusted.crt", __FILE__), SSLCACertificateFile: File.expand_path("../ssl/root-untrusted-ca.crt", __FILE__)
148
155
 
149
156
  Manticore.disable_httpcomponents_logging!
150
157
  }
metadata CHANGED
@@ -1,36 +1,36 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manticore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.3
4
+ version: 0.8.0
5
5
  platform: java
6
6
  authors:
7
7
  - Chris Heald
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-28 00:00:00.000000000 Z
11
+ date: 2022-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '1.3'
19
- name: bundler
18
+ version: '0'
19
+ name: openssl_pkcs8_pure
20
20
  prerelease: false
21
- type: :development
21
+ type: :runtime
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: '0'
33
- name: rake
33
+ name: bundler
34
34
  prerelease: false
35
35
  type: :development
36
36
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,7 +44,7 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
- name: jar-dependencies
47
+ name: rake
48
48
  prerelease: false
49
49
  type: :development
50
50
  version_requirements: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 0.4.1
61
+ name: jar-dependencies
62
+ prerelease: false
63
+ type: :development
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.4.1
55
69
  description: Manticore is an HTTP client built on the Apache HttpCore components
56
70
  email:
57
71
  - cheald@mashable.com
@@ -60,6 +74,7 @@ extensions: []
60
74
  extra_rdoc_files: []
61
75
  files:
62
76
  - ".gitignore"
77
+ - ".gitlab-ci.yml"
63
78
  - ".travis.yml"
64
79
  - APACHE-LICENSE-2.0.txt
65
80
  - CHANGELOG.md
@@ -71,7 +86,7 @@ files:
71
86
  - ext/manticore/org/manticore/HttpGetWithEntity.java
72
87
  - ext/manticore/org/manticore/Manticore.java
73
88
  - gem-public_cert.pem
74
- - lib/commons-codec/commons-codec/1.10/commons-codec-1.10.jar
89
+ - lib/commons-codec/commons-codec/1.15/commons-codec-1.15.jar
75
90
  - lib/commons-logging/commons-logging/1.2/commons-logging-1.2.jar
76
91
  - lib/faraday/adapter/manticore.rb
77
92
  - lib/manticore.rb
@@ -84,9 +99,9 @@ files:
84
99
  - lib/manticore/stubbed_response.rb
85
100
  - lib/manticore/version.rb
86
101
  - lib/manticore_jars.rb
87
- - lib/org/apache/httpcomponents/httpclient/4.5.2/httpclient-4.5.2.jar
88
- - lib/org/apache/httpcomponents/httpcore/4.4.4/httpcore-4.4.4.jar
89
- - lib/org/apache/httpcomponents/httpmime/4.5.2/httpmime-4.5.2.jar
102
+ - lib/org/apache/httpcomponents/httpclient/4.5.13/httpclient-4.5.13.jar
103
+ - lib/org/apache/httpcomponents/httpcore/4.4.14/httpcore-4.4.14.jar
104
+ - lib/org/apache/httpcomponents/httpmime/4.5.13/httpmime-4.5.13.jar
90
105
  - lib/org/manticore/manticore-ext.jar
91
106
  - manticore.gemspec
92
107
  - spec/manticore/client_proxy_spec.rb
@@ -109,20 +124,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
109
124
  requirements:
110
125
  - - ">="
111
126
  - !ruby/object:Gem::Version
112
- version: '0'
127
+ version: '2.3'
113
128
  required_rubygems_version: !ruby/object:Gem::Requirement
114
129
  requirements:
115
130
  - - ">="
116
131
  - !ruby/object:Gem::Version
117
132
  version: '0'
118
133
  requirements:
119
- - jar org.apache.httpcomponents:httpclient, '~> 4.5.0'
120
- - jar org.apache.httpcomponents:httpmime, '~> 4.5.0'
134
+ - jar org.apache.httpcomponents:httpclient, '~> 4.5.13'
135
+ - jar org.apache.httpcomponents:httpmime, '~> 4.5.13'
121
136
  - jar commons-logging:commons-logging, '~> 1.2'
122
137
  - jar commons-codec:commons-codec, '~> 1.9'
123
- - jar org.apache.httpcomponents:httpcore, '~> 4.4.4'
124
- rubyforge_project:
125
- rubygems_version: 2.4.8
138
+ - jar org.apache.httpcomponents:httpcore, '~> 4.4.14'
139
+ rubygems_version: 3.1.6
126
140
  signing_key:
127
141
  specification_version: 4
128
142
  summary: Manticore is an HTTP client built on the Apache HttpCore components