manticore 0.6.2-java → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 52e7c6c63c54c59317eb836e5caa6cc1dbb08fc1
4
- data.tar.gz: 362d618ee0a1e92762bd5acbb9639c0ea18af0e9
2
+ SHA256:
3
+ metadata.gz: 67e67c0611ad51fbaf279f456ef5a9e463038f1017c0eb8c7665032a05534b59
4
+ data.tar.gz: 0ecf2a3014befbbc5b26d95c3ee36809ccc8605e450631e4ec0f1c143225bbc5
5
5
  SHA512:
6
- metadata.gz: ab0c5c529908001ac420bc3c82234ff9016139024211dc2e1e9111dc71e43b37b6ce92c674a5b67c270329de752e3d33fc9e8cb726246a792bdc060e02bb3881
7
- data.tar.gz: 1aa799e26509c9e0ce51be46b5cf3f156bd0bfc33f9ecc8a41c136a039f2547ef8e8d0ad479afcfd69a34b6d0fbdb7525e670d65c8c594e51d50a4c53a04a62f
6
+ metadata.gz: 19f7db686cff19817b8310f7838f9115d343ab7516e7cbab066c0f0f7d223c7a0a42c40f9e361426c07345088dbdb818cabab59fb2a481d35050f939e27afafd
7
+ data.tar.gz: ebc35118980baac6eff3e1f795f5ad3aa0af01c7ac29cd6a9502f9300fb1da88d8b97ecfc7c1198d5902a35ab2501179df775791e3306e27004e85d690145bc2
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.16.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,28 @@
1
+ ## v0.7
2
+
3
+ ### v0.7.1
4
+
5
+ * Don't override certificates with same Subject (#93)
6
+ * Set Java cause for ManticoreException types (#96)
7
+ * Fix SSL handshake hang indefinitely (#98)
8
+
9
+ ### v0.7.0
10
+
11
+ * Drop support for JRuby 1.7. It probably still works, but we don't test against it anymore
12
+ * Fix a thread safety issue with regards to adding requests to the parallel execution queue while the client is already processing a queue (#80)
13
+
1
14
  ## v0.6
2
15
 
16
+ ### v0.6.4
17
+
18
+ * client_cert and client_key now take the literal keys as strings, OpenSSL::X509::Certificate/OpenSSL::PKey::Pkey instances, or key file paths. (#77)
19
+ * Reduced unnecessary string copying (!78 - thanks @kares)
20
+
21
+ ### v0.6.2-v0.6.3
22
+
23
+ * Fixed the use of authentication information in proxy URLs (#71)
24
+ * Changed the default encoding to UTF-8 when a response MIME is application/json (#70)
25
+
3
26
  ### v0.6.1
4
27
 
5
28
  * 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,5 +1,7 @@
1
1
  # Manticore
2
2
 
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
+
3
5
  [![Build Status](https://travis-ci.org/cheald/manticore.svg?branch=master)](https://travis-ci.org/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.
@@ -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
@@ -39,14 +39,19 @@ public class Manticore implements Library {
39
39
  @JRubyMethod(name = "read_entity")
40
40
  public IRubyObject readEntity(ThreadContext context, IRubyObject rEntity, Block block) throws IOException {
41
41
  HttpEntity entity = (HttpEntity)rEntity.toJava(HttpEntity.class);
42
+
42
43
  String charset = EntityUtils.getContentCharSet(entity);
43
- if(charset == null) { charset = HTTP.DEFAULT_CONTENT_CHARSET; }
44
- Encoding encoding;
45
- try {
44
+ if (charset == null) {
46
45
  String mimeType = EntityUtils.getContentMimeType(entity);
47
- if (mimeType.startsWith("application/json")) {
46
+ if ( mimeType != null && mimeType.startsWith("application/json") ) {
48
47
  charset = "UTF-8";
48
+ } else {
49
+ charset = HTTP.DEFAULT_CONTENT_CHARSET;
49
50
  }
51
+ }
52
+
53
+ Encoding encoding;
54
+ try {
50
55
  encoding = context.getRuntime().getEncodingService().getEncodingFromString(charset);
51
56
  } catch(Throwable e) {
52
57
  encoding = context.getRuntime().getEncodingService().getEncodingFromString(HTTP.DEFAULT_CONTENT_CHARSET);
@@ -61,7 +66,7 @@ public class Manticore implements Library {
61
66
 
62
67
  private IRubyObject readWholeEntity(ThreadContext context, HttpEntity entity, Encoding encoding) throws IOException {
63
68
  ByteList bl = new ByteList(EntityUtils.toByteArray(entity), false);
64
- return RubyString.newStringShared(context.getRuntime(), bl, encoding);
69
+ return RubyString.newString(context.getRuntime(), bl, encoding);
65
70
  }
66
71
 
67
72
  private IRubyObject streamEntity(ThreadContext context, HttpEntity entity, Encoding encoding, Block block) throws IOException {
@@ -81,7 +86,7 @@ public class Manticore implements Library {
81
86
  byte[] tmp = new byte[4096];
82
87
  int l;
83
88
  while((l = instream.read(tmp)) != -1) {
84
- 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) );
85
90
  }
86
91
  } finally {
87
92
  instream.close();
@@ -89,4 +94,4 @@ public class Manticore implements Library {
89
94
  return context.nil;
90
95
  }
91
96
  }
92
- }
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]
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,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,20 @@ 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.TrustSelfSignedStrategy"
92
+ java_import "org.apache.http.client.utils.URIBuilder"
93
+ java_import "org.apache.http.impl.DefaultConnectionReuseStrategy"
94
+ java_import "org.apache.http.impl.auth.BasicScheme"
92
95
 
93
96
  # This is a class rather than a proc because the proc holds a closure around
94
97
  # the instance of the Client that creates it.
@@ -169,8 +172,8 @@ module Manticore
169
172
  # @option options [String] ssl[:keystore_password] (nil) Password used for decrypting the client auth key store
170
173
  # @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
174
  # @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
175
+ # @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
176
+ # @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
177
  # @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
178
  # can't be shared across those threads. This should generally be left off unless you know what you're doing.
176
179
  def initialize(options = {})
@@ -200,11 +203,7 @@ module Manticore
200
203
  builder.set_connection_reuse_strategy DefaultConnectionReuseStrategy.new
201
204
  end
202
205
 
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
-
206
+ builder.set_default_socket_config socket_config_from_options(options)
208
207
  builder.set_connection_manager pool(options)
209
208
 
210
209
  request_config = RequestConfig.custom
@@ -222,7 +221,7 @@ module Manticore
222
221
  @client = builder.build
223
222
  finalize @client, :close
224
223
  @options = options
225
- @async_requests = []
224
+ @async_requests = Queue.new
226
225
  @stubs = {}
227
226
  end
228
227
 
@@ -333,8 +332,9 @@ module Manticore
333
332
  # @return [Array] An array of the responses from the requests executed.
334
333
  def execute!
335
334
  method = executor.java_method(:submit, [java.util.concurrent.Callable.java_class])
336
- result = @async_requests.map { |r| method.call r }
337
- @async_requests.clear
335
+
336
+ result = []
337
+ result << method.call(@async_requests.pop) until @async_requests.empty?
338
338
  result.map do |future|
339
339
  begin
340
340
  future.get
@@ -385,11 +385,13 @@ module Manticore
385
385
  def pool_builder(options)
386
386
  http_sf = PlainConnectionSocketFactory.new
387
387
 
388
+ # :nocov:
388
389
  if options[:ignore_ssl_validation]
389
390
  $stderr.puts "The options[:ignore_ssl_validation] setting is deprecated in favor of options[:ssl][:verify]"
390
391
  options[:ssl] ||= {}
391
392
  options[:ssl] = {:verify => !options.delete(:ignore_ssl_validation)}.merge(options[:ssl])
392
393
  end
394
+ # :nocov:
393
395
 
394
396
  https_sf = ssl_socket_factory_from_options options.fetch(:ssl, {})
395
397
  registry = RegistryBuilder.create.register("http", http_sf).register("https", https_sf).build
@@ -403,10 +405,19 @@ module Manticore
403
405
  cm.set_validate_after_inactivity options.fetch(:check_connection_timeout, 2_000)
404
406
  cm.set_default_max_per_route options.fetch(:pool_max_per_route, @max_pool_size)
405
407
  cm.set_max_total @max_pool_size
408
+ cm.set_default_socket_config socket_config_from_options(options)
409
+
406
410
  finalize cm, :shutdown
407
411
  end
408
412
  end
409
413
  end
414
+
415
+ def socket_config_from_options(options)
416
+ socket_config_builder = SocketConfig.custom
417
+ socket_config_builder.set_so_timeout(options.fetch(:socket_timeout, DEFAULT_SOCKET_TIMEOUT) * 1000)
418
+ socket_config_builder.set_tcp_no_delay(options.fetch(:tcp_no_delay, true))
419
+ socket_config_builder.build
420
+ end
410
421
 
411
422
  def create_executor_if_needed
412
423
  return @executor if @executor
@@ -506,7 +517,7 @@ module Manticore
506
517
 
507
518
  if @use_cookies == :per_request
508
519
  store = BasicCookieStore.new
509
- context.setAttribute(ClientContext.COOKIE_STORE, store)
520
+ context.setAttribute(ClientContext::COOKIE_STORE, store)
510
521
  end
511
522
 
512
523
  return req, context
@@ -614,7 +625,7 @@ module Manticore
614
625
  raise "Invalid value for :verify. Valid values are (:all, :browser, :default)"
615
626
  end
616
627
 
617
- context = SSLContexts.custom
628
+ context = SSLContextBuilder.new
618
629
  setup_trust_store ssl_options, context, trust_strategy
619
630
  setup_key_store ssl_options, context
620
631
 
@@ -629,8 +640,8 @@ module Manticore
629
640
  trust_store ||= blank_keystore
630
641
  open(ssl_options[:ca_file]) do |fp|
631
642
  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)
643
+ cert_collection.each_with_index do |cert, i|
644
+ trust_store.set_certificate_entry("#{i}#" + cert.getSubjectX500Principal.name, cert)
634
645
  end
635
646
  end
636
647
  end
@@ -645,39 +656,44 @@ module Manticore
645
656
  keystore_password = (ssl_options[:keystore_password] || "").to_java.toCharArray
646
657
 
647
658
  # 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
659
  if ssl_options[:client_cert] && ssl_options[:client_key]
650
660
  key_store ||= blank_keystore
651
661
  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
662
+
663
+ cert_str = if ssl_options[:client_cert].is_a?(OpenSSL::X509::Certificate)
664
+ ssl_options[:client_cert].to_s
665
+ elsif ssl_options[:client_cert].is_a?(String) && File.exists?(ssl_options[:client_cert])
666
+ File.read(ssl_options[:client_cert])
667
+ else
668
+ ssl_options[:client_cert].to_s
669
+ end
670
+
671
+ cert_stream = java.io.ByteArrayInputStream.new(cert_str.strip.to_java_bytes)
672
+ certs = CertificateFactory.get_instance("X509").generate_certificates(cert_stream).to_array([].to_java(Certificate))
673
+
674
+ key_str = if ssl_options[:client_key].is_a?(OpenSSL::PKey::PKey)
675
+ ssl_options[:client_key].to_pem_pkcs8
676
+ elsif ssl_options[:client_key].is_a?(String) && File.exists?(ssl_options[:client_key])
677
+ File.read(ssl_options[:client_key])
678
+ else
679
+ ssl_options[:client_key].to_s
680
+ end
655
681
 
656
682
  # 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
683
+ key_parts = key_str.scan(KEY_EXTRACTION_REGEXP)
684
+ key_parts.each do |type, b64key|
685
+ body = Base64.decode64 b64key
686
+ spec = PKCS8EncodedKeySpec.new(body.strip.to_java_bytes)
687
+ type = type.strip
688
+ type = "RSA" if type == ""
689
+ key = KeyFactory.getInstance(type).generatePrivate(spec)
690
+ key_store.set_key_entry("key-#{Digest::SHA1.hexdigest(body)}", key, keystore_password, certs)
667
691
  end
668
692
  end
669
693
 
670
694
  context.load_key_material(key_store, keystore_password) if key_store
671
695
  end
672
696
 
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
697
  def get_store(prefix, options)
682
698
  KeyStore.get_instance(options[:"#{prefix}_type"] || guess_store_type(options[prefix])).tap do |store|
683
699
  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.2"
2
+ VERSION = "0.7.1"
3
3
  end
Binary file
data/manticore.gemspec CHANGED
@@ -19,15 +19,19 @@ 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
36
  spec.requirements << "jar org.apache.httpcomponents:httpclient, '~> 4.5.0'"
33
37
  spec.requirements << "jar org.apache.httpcomponents:httpmime, '~> 4.5.0'"
@@ -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
 
@@ -529,7 +569,7 @@ describe Manticore::Client do
529
569
  describe "#head" do
530
570
  it "works" do
531
571
  response = client.head(local_server)
532
- expect(JSON.load(response.body)).to be_nil
572
+ expect(response.body).to be_nil
533
573
  end
534
574
  end
535
575
 
@@ -730,11 +770,16 @@ describe Manticore::Client do
730
770
  ].join("\n"))
731
771
  client.close
732
772
  rescue IOError => e
773
+ break
733
774
  end
734
775
  end
735
776
  end
736
777
  end
737
778
 
779
+ after do
780
+ @server.kill
781
+ end
782
+
738
783
  let(:client) { Manticore::Client.new keepalive: true, pool_max: 1 }
739
784
 
740
785
  it "retries 3 times by default" do
@@ -791,7 +836,13 @@ describe Manticore::Client do
791
836
  let(:client) { Manticore::Client.new request_timeout: 1, connect_timeout: 1, socket_timeout: 1 }
792
837
 
793
838
  it "times out" do
794
- expect { client.get(local_server "/?sleep=2").body }.to raise_exception(Manticore::SocketTimeout)
839
+ begin
840
+ client.get(local_server "/?sleep=2").body
841
+ rescue Manticore::SocketTimeout => e
842
+ expect( e.cause ).to be_a java.net.SocketTimeoutException
843
+ else
844
+ fail "exception not raised"
845
+ end
795
846
  end
796
847
 
797
848
  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"
metadata CHANGED
@@ -1,38 +1,38 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manticore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.7.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: 2018-05-28 00:00:00.000000000 Z
11
+ date: 2021-08-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
+ type: :runtime
20
21
  prerelease: false
21
- type: :development
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
34
- prerelease: false
33
+ name: bundler
35
34
  type: :development
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
@@ -44,14 +44,28 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
- name: jar-dependencies
48
- prerelease: false
47
+ name: rake
49
48
  type: :development
49
+ prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
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
+ type: :development
63
+ prerelease: false
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
@@ -109,7 +124,7 @@ 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
  - - ">="
@@ -121,8 +136,7 @@ requirements:
121
136
  - jar commons-logging:commons-logging, '~> 1.2'
122
137
  - jar commons-codec:commons-codec, '~> 1.9'
123
138
  - jar org.apache.httpcomponents:httpcore, '~> 4.4.4'
124
- rubyforge_project:
125
- rubygems_version: 2.4.8
139
+ rubygems_version: 3.0.6
126
140
  signing_key:
127
141
  specification_version: 4
128
142
  summary: Manticore is an HTTP client built on the Apache HttpCore components