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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: aaec2b636e38b91767b212d83f2519c7e52ed085
4
- data.tar.gz: 83eda4139c8cad24ccff8f9c022d5b4a8a9e7778
2
+ SHA256:
3
+ metadata.gz: 508b2d2c3ce9fc25ca2ac915954807783cc8266aac23936a6896d103121a2f0c
4
+ data.tar.gz: a8ac97bd7fb22df23ac164d5f06f3a35c926d9eac57ae7bfb8e84c0c8d9e7907
5
5
  SHA512:
6
- metadata.gz: 9e60fe0524842aaba68b508587ef4928db16c11fbbfcdd5b29c2453d1175e6edd79322ec4068c18e921eea3f7e021d5a5a9b523e46ad12aeed5e7668c6920b1d
7
- data.tar.gz: 90c45bbc808cfeeac2b79685eed88162092fe8a73c81ca928f9c81309b10897a02c0ec2e88866ab1ef97baeeb884df85a595e48916c6d63cc2c925307cc4a2bc
6
+ metadata.gz: 56a60c747c187ddd1255e5da7cbc2ad78570c2ebf5390841298f45366133b48c857df8ac7b7b8bdbbb5194546e3b3112a8c08b5109c66a1299f6fe787ae890fc
7
+ data.tar.gz: 78e29e767486b820f1d1a280ae4db04b1ad33eccb7da7538bae9e48116305b44d069dc13ee322484146f9cce28b6edf71e868d73be8e075957404c50a99416eb
@@ -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/
@@ -1,22 +1,20 @@
1
+ dist: xenial
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.1.17.0 # Ruby 2.3
9
+ - jruby-9.2.13.0 # Ruby 2.5
10
10
  jdk:
11
- - oraclejdk8
12
- - oraclejdk7
13
- - openjdk7
11
+ - openjdk9
12
+ - openjdk11
14
13
  before_install:
15
- - gem install ruby-maven
16
- - bundle install
14
+ - gem install bundler -v 1.17.3
17
15
  matrix:
18
16
  include:
19
17
  - rvm: jruby-head
20
- jdk: oraclejdk8
18
+ jdk: openjdk10
21
19
  allow_failures:
22
- - rvm: jruby-head
20
+ - rvm: jruby-head
@@ -1,6 +1,23 @@
1
1
  ## v0.6
2
2
 
3
- ### v0.6.1 (pending)
3
+ ### v0.7.0
4
+
5
+ * Drop support for JRuby 1.7. It probably still works, but we don't test against it anymore
6
+ * Fix a thread safety issue with regards to adding requests to the parallel execution queue while the client is already processing a queue (#80)
7
+
8
+ ### v0.6.4
9
+
10
+ * client_cert and client_key now take the literal keys as strings, OpenSSL::X509::Certificate/OpenSSL::PKey::Pkey instances, or key file paths. (#77)
11
+ * Reduced unnecessary string copying (!78 - thanks @kares)
12
+
13
+ ### v0.6.2-v0.6.3
14
+
15
+ * Fixed the use of authentication information in proxy URLs (#71)
16
+ * Changed the default encoding to UTF-8 when a response MIME is application/json (#70)
17
+
18
+ ### v0.6.1
19
+
20
+ * 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)
4
21
 
5
22
  ### v0.6.0
6
23
 
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.png?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://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.
6
8
 
data/Rakefile CHANGED
@@ -1,27 +1,27 @@
1
1
  require "bundler/gem_tasks"
2
2
 
3
- require 'rspec/core/rake_task'
3
+ require "rspec/core/rake_task"
4
4
  RSpec::Core::RakeTask.new(:spec) do |spec|
5
- spec.pattern = 'spec/**/*_spec.rb'
6
- spec.rspec_opts = ['--tty --color --format documentation']
5
+ spec.pattern = "spec/**/*_spec.rb"
6
+ spec.rspec_opts = ["--tty --color --format documentation"]
7
7
  end
8
8
  task :default => [:generate_certs, :spec]
9
9
 
10
10
  # Download and vendor the jars needed
11
- require 'jars/installer'
11
+ require "jars/installer"
12
12
  task :install_jars do
13
13
  Jars::Installer.vendor_jars!
14
14
  end
15
15
 
16
16
  ## Build the Manticore extensions into a jar. You may need to install_jars first
17
17
  # Dependency jars for the Manticore ext build
18
- require 'rake/javaextensiontask'
19
- jars = ["#{ENV['MY_RUBY_HOME']}/lib/jruby.jar"] + Dir.glob("lib/**/*.jar")
20
- jars.reject! {|j| j.match("manticore-ext") }
18
+ require "rake/javaextensiontask"
19
+ jars = ["#{ENV["MY_RUBY_HOME"]}/lib/jruby.jar"] + Dir.glob("lib/**/*.jar")
20
+ jars.reject! { |j| j.match("manticore-ext") }
21
21
  Rake::JavaExtensionTask.new do |ext|
22
22
  ext.name = "manticore-ext"
23
23
  ext.lib_dir = "lib/org/manticore"
24
- ext.classpath = jars.map {|x| File.expand_path x}.join ':'
24
+ ext.classpath = jars.map { |x| File.expand_path x }.join ":"
25
25
  end
26
26
 
27
27
  # Generate all the stuff we need for a full test run
@@ -30,10 +30,10 @@ task :generate_certs do
30
30
  openssl = `which openssl`.strip
31
31
  keytool = `which keytool`.strip
32
32
 
33
- Dir.glob("#{root}/*").each {|f| File.unlink f }
33
+ Dir.glob("#{root}/*").each { |f| File.unlink f }
34
34
 
35
- # Create the CA
36
35
  cmds = [
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
39
 
@@ -41,15 +41,17 @@ task :generate_certs do
41
41
  "#{openssl} genrsa 4096 | #{openssl} pkcs8 -topk8 -nocrypt -out #{root}/client.key",
42
42
  "#{openssl} req -sha256 -key #{root}/client.key -newkey rsa:4096 -out #{root}/client.csr -subj \"/C=US/ST=The Internet/L=The Internet/O=Manticore Client/OU=Manticore/CN=localhost\"",
43
43
  "#{openssl} x509 -req -in #{root}/client.csr -CA #{root}/root-ca.crt -CAkey #{root}/root-ca.key -CAcreateserial -out #{root}/client.crt -sha256 -days 1",
44
+ "#{openssl} x509 -req -in #{root}/client.csr -CA #{root}/root-ca.crt -CAkey #{root}/root-ca.key -CAcreateserial -out #{root}/client-expired.crt -sha256 -days -7",
44
45
 
45
46
  # Create the server cert
46
47
  "#{openssl} genrsa 4096 | #{openssl} pkcs8 -topk8 -nocrypt -out #{root}/host.key",
47
48
  "#{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\"",
48
49
  "#{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
+ "#{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",
49
51
 
50
52
  "#{keytool} -import -file #{root}/root-ca.crt -alias rootCA -keystore #{root}/truststore.jks -noprompt -storepass test123",
51
53
  "#{openssl} pkcs12 -export -clcerts -out #{root}/client.p12 -inkey #{root}/client.key -in #{root}/client.crt -certfile #{root}/root-ca.crt -password pass:test123",
52
54
  ]
53
55
 
54
- cmds.each.with_index {|cmd, index| puts "#{index}. #{cmd}"; system cmd }
55
- end
56
+ cmds.each.with_index { |cmd, index| puts "#{index}. #{cmd}"; system cmd }
57
+ end
@@ -39,8 +39,17 @@ 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
+ if (charset == null) {
45
+ String mimeType = EntityUtils.getContentMimeType(entity);
46
+ if ( mimeType != null && mimeType.startsWith("application/json") ) {
47
+ charset = "UTF-8";
48
+ } else {
49
+ charset = HTTP.DEFAULT_CONTENT_CHARSET;
50
+ }
51
+ }
52
+
44
53
  Encoding encoding;
45
54
  try {
46
55
  encoding = context.getRuntime().getEncodingService().getEncodingFromString(charset);
@@ -57,7 +66,7 @@ public class Manticore implements Library {
57
66
 
58
67
  private IRubyObject readWholeEntity(ThreadContext context, HttpEntity entity, Encoding encoding) throws IOException {
59
68
  ByteList bl = new ByteList(EntityUtils.toByteArray(entity), false);
60
- return RubyString.newStringShared(context.getRuntime(), bl, encoding);
69
+ return RubyString.newString(context.getRuntime(), bl, encoding);
61
70
  }
62
71
 
63
72
  private IRubyObject streamEntity(ThreadContext context, HttpEntity entity, Encoding encoding, Block block) throws IOException {
@@ -77,7 +86,7 @@ public class Manticore implements Library {
77
86
  byte[] tmp = new byte[4096];
78
87
  int l;
79
88
  while((l = instream.read(tmp)) != -1) {
80
- 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) );
81
90
  }
82
91
  } finally {
83
92
  instream.close();
@@ -85,4 +94,4 @@ public class Manticore implements Library {
85
94
  return context.nil;
86
95
  }
87
96
  }
88
- }
97
+ }
@@ -1,9 +1,9 @@
1
- require 'faraday'
1
+ require "faraday"
2
2
 
3
3
  module Faraday
4
4
  class Adapter
5
5
  class Manticore < Faraday::Adapter
6
- dependency { require 'manticore' }
6
+ dependency { require "manticore" }
7
7
 
8
8
  class ParallelManager
9
9
  def client=(client)
@@ -20,20 +20,15 @@ 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
34
- opts[:ssl][:ca_file] = ssl[:ca_file]
28
+ opts[:ssl][:verify] = ssl[:verify] unless ssl[:verify].nil?
29
+ opts[:ssl][:ca_file] = ssl[:ca_file]
35
30
  opts[:ssl][:client_cert] = ssl[:client_cert]
36
- opts[:ssl][:client_key] = ssl[:client_key]
31
+ opts[:ssl][:client_key] = ssl[:client_key]
37
32
  end
38
33
  conn_opts = @connection_options.dup
39
34
  if conn_opts.key?(:ssl)
@@ -50,7 +45,7 @@ module Faraday
50
45
  opts = {}
51
46
  if env.key? :request_headers
52
47
  opts[:headers] = env[:request_headers]
53
- opts[:headers].reject! {|k, _| k.downcase == "content-length" } # Manticore computes Content-Length
48
+ opts[:headers].reject! { |k, _| k.downcase == "content-length" } # Manticore computes Content-Length
54
49
  end
55
50
  body = read_body(env)
56
51
  opts[:body] = body if body
@@ -60,9 +55,9 @@ module Faraday
60
55
  opts[:connect_timeout] = req[:open_timeout] if req.key?(:open_timeout)
61
56
  if prx = req[:proxy]
62
57
  opts[:proxy] = {
63
- :url => prx[:uri].to_s,
64
- :user => prx[:user],
65
- :password => prx[:password]
58
+ :url => prx[:uri].to_s,
59
+ :user => prx[:user],
60
+ :password => prx[:password],
66
61
  }
67
62
  end
68
63
  end
@@ -106,6 +101,7 @@ module Faraday
106
101
  env[:body].respond_to?(:read) ? env[:body].read : env[:body]
107
102
  end
108
103
  end
104
+
109
105
  register_middleware nil, :manticore => :Manticore
110
106
  end
111
- end
107
+ end
@@ -1,6 +1,6 @@
1
- require 'java'
2
- require 'uri'
3
- require 'cgi'
1
+ require "java"
2
+ require "uri"
3
+ require "cgi"
4
4
 
5
5
  require_relative "./manticore_jars.rb"
6
6
  require_relative "./org/manticore/manticore-ext"
@@ -42,12 +42,12 @@ module Manticore
42
42
  class UnknownException < ManticoreException; end
43
43
 
44
44
  require_relative "./manticore/java_extensions"
45
- require_relative './manticore/client/proxies'
46
- require_relative './manticore/client'
47
- require_relative './manticore/response'
48
- require_relative './manticore/stubbed_response'
49
- require_relative './manticore/cookie'
50
- require_relative './manticore/facade'
45
+ require_relative "./manticore/client/proxies"
46
+ require_relative "./manticore/client"
47
+ require_relative "./manticore/response"
48
+ require_relative "./manticore/stubbed_response"
49
+ require_relative "./manticore/cookie"
50
+ require_relative "./manticore/facade"
51
51
 
52
52
  include Facade
53
53
  include_http_client
@@ -57,4 +57,4 @@ module Manticore
57
57
  props.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.SimpleLog")
58
58
  props.setProperty("org.apache.commons.logging.simplelog.log.org.apache.http", "error")
59
59
  end
60
- end
60
+ end
@@ -1,6 +1,7 @@
1
- require 'thread'
2
- require 'base64'
3
- require 'weakref'
1
+ require "thread"
2
+ require "base64"
3
+ require "weakref"
4
+ require "openssl_pkcs8_pure"
4
5
 
5
6
  module Manticore
6
7
  # @!macro [new] http_method_shared
@@ -13,9 +14,9 @@ module Manticore
13
14
  # @option options [String] proxy Proxy host in form: http://proxy.org:1234
14
15
  # @option options [Hash] proxy Proxy host in form: {host: 'proxy.org'[, port: 80[, scheme: 'http']]}
15
16
  # @option options [URI] proxy Proxy host as a URI object
16
- # @option options [Integer] connect_timeout Request-specific connect timeout
17
- # @option options [Integer] socket_timeout Request-specific socket timeout
18
- # @option options [Integer] request_timeout Request-specific request timeout
17
+ # @option options [Float] connect_timeout Request-specific connect timeout (in seconds)
18
+ # @option options [Float] socket_timeout Request-specific socket timeout (in seconds)
19
+ # @option options [Float] request_timeout Request-specific request timeout (in seconds)
19
20
  # @option options [Integer] max_redirects Request-specific maximum redirect limit
20
21
  # @option options [Boolean] follow_redirects Specify whether this request should follow redirects
21
22
  # @option options [Hash] auth Specify authentication for the request
@@ -79,7 +80,7 @@ module Manticore
79
80
  include_package "org.apache.http.auth"
80
81
  include_package "java.util.concurrent"
81
82
  include_package "org.apache.http.client.protocol"
82
- include_package 'org.apache.http.conn.ssl'
83
+ include_package "org.apache.http.conn.ssl"
83
84
  include_package "java.security.cert"
84
85
  include_package "java.security.spec"
85
86
  include_package "java.security"
@@ -105,14 +106,14 @@ module Manticore
105
106
  include ProxiesInterface
106
107
 
107
108
  # The default maximum pool size for requests
108
- DEFAULT_MAX_POOL_SIZE = 50
109
+ DEFAULT_MAX_POOL_SIZE = 50
109
110
 
110
111
  DEFAULT_REQUEST_TIMEOUT = 60
111
- DEFAULT_SOCKET_TIMEOUT = 10
112
+ DEFAULT_SOCKET_TIMEOUT = 10
112
113
  DEFAULT_CONNECT_TIMEOUT = 10
113
- DEFAULT_MAX_REDIRECTS = 5
114
+ DEFAULT_MAX_REDIRECTS = 5
114
115
  DEFAULT_EXPECT_CONTINUE = false
115
- DEFAULT_STALE_CHECK = false
116
+ DEFAULT_STALE_CHECK = false
116
117
 
117
118
  attr_reader :client
118
119
 
@@ -169,15 +170,15 @@ module Manticore
169
170
  # @option options [String] ssl[:keystore_password] (nil) Password used for decrypting the client auth key store
170
171
  # @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
172
  # @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
173
+ # @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
174
+ # @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
175
  # @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
176
  # can't be shared across those threads. This should generally be left off unless you know what you're doing.
176
177
  def initialize(options = {})
177
178
  @finalizers = []
178
179
  self.class.shutdown_on_finalize self, @finalizers
179
180
 
180
- builder = client_builder
181
+ builder = client_builder
181
182
  builder.set_user_agent options.fetch(:user_agent, "Manticore #{VERSION}")
182
183
  @options = options
183
184
  @use_cookies = options.fetch(:cookies, false)
@@ -195,24 +196,24 @@ module Manticore
195
196
 
196
197
  @keepalive = options.fetch(:keepalive, true)
197
198
  if @keepalive == false
198
- builder.set_connection_reuse_strategy {|response, context| false }
199
+ builder.set_connection_reuse_strategy { |response, context| false }
199
200
  else
200
201
  builder.set_connection_reuse_strategy DefaultConnectionReuseStrategy.new
201
202
  end
202
203
 
203
204
  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) )
205
+ socket_config_builder.set_so_timeout(options.fetch(:socket_timeout, DEFAULT_SOCKET_TIMEOUT) * 1000)
206
+ socket_config_builder.set_tcp_no_delay(options.fetch(:tcp_no_delay, true))
206
207
  builder.set_default_socket_config socket_config_builder.build
207
208
 
208
209
  builder.set_connection_manager pool(options)
209
210
 
210
211
  request_config = RequestConfig.custom
211
- request_config.set_connection_request_timeout options.fetch(:request_timeout, DEFAULT_REQUEST_TIMEOUT) * 1000
212
- request_config.set_connect_timeout options.fetch(:connect_timeout, DEFAULT_CONNECT_TIMEOUT) * 1000
213
- request_config.set_socket_timeout options.fetch(:socket_timeout, DEFAULT_SOCKET_TIMEOUT) * 1000
214
- request_config.set_max_redirects options.fetch(:max_redirects, DEFAULT_MAX_REDIRECTS)
215
- request_config.set_expect_continue_enabled options.fetch(:expect_continue, DEFAULT_EXPECT_CONTINUE)
212
+ request_config.set_connection_request_timeout options.fetch(:request_timeout, DEFAULT_REQUEST_TIMEOUT) * 1000
213
+ request_config.set_connect_timeout options.fetch(:connect_timeout, DEFAULT_CONNECT_TIMEOUT) * 1000
214
+ request_config.set_socket_timeout options.fetch(:socket_timeout, DEFAULT_SOCKET_TIMEOUT) * 1000
215
+ request_config.set_max_redirects options.fetch(:max_redirects, DEFAULT_MAX_REDIRECTS)
216
+ request_config.set_expect_continue_enabled options.fetch(:expect_continue, DEFAULT_EXPECT_CONTINUE)
216
217
  request_config.set_stale_connection_check_enabled options.fetch(:stale_check, DEFAULT_STALE_CHECK)
217
218
  request_config.set_circular_redirects_allowed false
218
219
 
@@ -222,7 +223,7 @@ module Manticore
222
223
  @client = builder.build
223
224
  finalize @client, :close
224
225
  @options = options
225
- @async_requests = []
226
+ @async_requests = Queue.new
226
227
  @stubs = {}
227
228
  end
228
229
 
@@ -233,7 +234,7 @@ module Manticore
233
234
  max: stats.get_max,
234
235
  leased: stats.get_leased,
235
236
  pending: stats.get_pending,
236
- available: stats.get_available
237
+ available: stats.get_available,
237
238
  }
238
239
  end
239
240
 
@@ -333,8 +334,9 @@ module Manticore
333
334
  # @return [Array] An array of the responses from the requests executed.
334
335
  def execute!
335
336
  method = executor.java_method(:submit, [java.util.concurrent.Callable.java_class])
336
- result = @async_requests.map {|r| method.call r }
337
- @async_requests.clear
337
+
338
+ result = []
339
+ result << method.call(@async_requests.pop) until @async_requests.empty?
338
340
  result.map do |future|
339
341
  begin
340
342
  future.get
@@ -357,8 +359,8 @@ module Manticore
357
359
 
358
360
  def self.shutdown_on_finalize(client, objs)
359
361
  ObjectSpace.define_finalizer client, -> {
360
- objs.each {|obj, args| obj.send(*args) rescue nil }
361
- }
362
+ objs.each { |obj, args| obj.send(*args) rescue nil }
363
+ }
362
364
  end
363
365
 
364
366
  protected
@@ -383,13 +385,15 @@ module Manticore
383
385
  end
384
386
 
385
387
  def pool_builder(options)
386
- http_sf = PlainConnectionSocketFactory.new
388
+ http_sf = PlainConnectionSocketFactory.new
387
389
 
390
+ # :nocov:
388
391
  if options[:ignore_ssl_validation]
389
- $stderr.puts 'The options[:ignore_ssl_validation] setting is deprecated in favor of options[:ssl][:verify]'
392
+ $stderr.puts "The options[:ignore_ssl_validation] setting is deprecated in favor of options[:ssl][:verify]"
390
393
  options[:ssl] ||= {}
391
- options[:ssl] = {:verify => !options.delete(:ignore_ssl_validation)}.merge(options[:ssl])
394
+ options[:ssl] = {:verify => !options.delete(:ignore_ssl_validation)}.merge(options[:ssl])
392
395
  end
396
+ # :nocov:
393
397
 
394
398
  https_sf = ssl_socket_factory_from_options options.fetch(:ssl, {})
395
399
  registry = RegistryBuilder.create.register("http", http_sf).register("https", https_sf).build
@@ -416,10 +420,10 @@ module Manticore
416
420
 
417
421
  def request(klass, url, options, &block)
418
422
  req, context = request_from_options(klass, url, options)
419
- async = options.delete(:async)
420
- background = options.delete(:async_background)
423
+ async = options.delete(:async)
424
+ background = options.delete(:async_background)
421
425
  create_executor_if_needed if (background || async)
422
- response = response_object_for(req, context, &block)
426
+ response = response_object_for(req, context, &block)
423
427
 
424
428
  if async
425
429
  @async_requests << response
@@ -439,13 +443,14 @@ module Manticore
439
443
 
440
444
  match_key = @stubs.keys.find { |k| request_uri.match(k) }
441
445
  if match_key
442
- StubbedResponse.new(self, request, context, &block).stub( @stubs[match_key] )
446
+ StubbedResponse.new(self, request, context, &block).stub(@stubs[match_key])
443
447
  else
444
448
  Response.new(self, request, context, &block)
445
449
  end
446
450
  end
447
451
 
448
452
  def uri_from_url_and_options(url, options)
453
+ url = url.to_s if url.is_a?(URI)
449
454
  builder = URIBuilder.new(url)
450
455
  pairs = struct_to_name_value_pairs(options[:query])
451
456
  builder.add_parameters pairs unless pairs.empty?
@@ -455,7 +460,7 @@ module Manticore
455
460
  def request_from_options(klass, url, options)
456
461
  req = klass.new uri_from_url_and_options(url, options).to_s
457
462
 
458
- if ( options[:params] || options[:body] || options[:entity]) && req.kind_of?(HttpEntityEnclosingRequestBase)
463
+ if (options[:params] || options[:body] || options[:entity]) && req.kind_of?(HttpEntityEnclosingRequestBase)
459
464
  if options[:params]
460
465
  pairs = struct_to_name_value_pairs(options[:params])
461
466
  encoding = minimum_encoding_for options[:params].to_s
@@ -478,23 +483,30 @@ module Manticore
478
483
  if req_options[:proxy]
479
484
  config.set_proxy get_proxy_host(req_options[:proxy])
480
485
  end
481
- config.set_max_redirects req_options[:max_redirects] if req_options[:max_redirects]
482
- config.set_redirects_enabled !!req_options[:follow_redirects] if req_options.fetch(:follow_redirects, nil) != nil
483
- config.set_connect_timeout req_options[:connect_timeout] * 1000 if req_options[:connect_timeout]
484
- config.set_socket_timeout req_options[:socket_timeout] * 1000 if req_options[:socket_timeout]
486
+ config.set_max_redirects req_options[:max_redirects] if req_options[:max_redirects]
487
+ config.set_redirects_enabled !!req_options[:follow_redirects] if req_options.fetch(:follow_redirects, nil) != nil
488
+ config.set_connect_timeout req_options[:connect_timeout] * 1000 if req_options[:connect_timeout]
489
+ config.set_socket_timeout req_options[:socket_timeout] * 1000 if req_options[:socket_timeout]
485
490
  config.set_connection_request_timeout req_options[:request_timeout] * 1000 if req_options[:request_timeout]
486
491
  req.set_config config.build
487
492
  end
488
493
 
489
-
490
- options[:headers].each {|k, v| req[k] = v } if options.key?(:headers)
491
-
494
+ headers = []
492
495
  # Support keepalive on HTTP/1.0 connections
493
- req["Connection"] = "Keep-Alive" if @keepalive
496
+ headers.push BasicHeader.new("Connection", "Keep-Alive") if @keepalive
497
+
498
+ if options.key?(:headers)
499
+ options[:headers].each do |k, v|
500
+ Array(v).each do |_v|
501
+ headers.push BasicHeader.new(k, _v)
502
+ end
503
+ end
504
+ end
505
+ req.set_headers headers.to_java(BasicHeader) unless headers.empty?
494
506
 
495
507
  context = HttpClientContext.new
496
508
  proxy_user = req_options[:proxy].is_a?(Hash) && (req_options[:proxy][:user] || req_options[:proxy][:username])
497
- auth_from_options(req, req_options, context) if req_options.key?(:auth) || proxy_user
509
+ auth_from_options(req, req_options, context)
498
510
 
499
511
  if @use_cookies == :per_request
500
512
  store = BasicCookieStore.new
@@ -529,7 +541,16 @@ module Manticore
529
541
 
530
542
  def auth_from_options(req, options, context)
531
543
  proxy = options.fetch(:proxy, {})
532
- if options[:auth] || proxy[:user] || proxy[:username]
544
+
545
+ proxy_user, proxy_pass = if proxy.is_a?(String)
546
+ proxy_uri = URI.parse(proxy)
547
+ [proxy_uri.user, proxy_uri.password]
548
+ else
549
+ [(proxy[:user] || proxy[:username]),
550
+ (proxy[:pass] || proxy[:password])]
551
+ end
552
+
553
+ if options[:auth] || proxy_user
533
554
  provider = BasicCredentialsProvider.new
534
555
  if options[:auth]
535
556
  username = options[:auth][:user] || options[:auth][:username]
@@ -547,10 +568,8 @@ module Manticore
547
568
  end
548
569
  end
549
570
 
550
- if proxy[:user] || proxy[:username]
551
- username = proxy[:user] || proxy[:username]
552
- password = proxy[:pass] || proxy[:password]
553
- provider.set_credentials AuthScope.new(get_proxy_host(proxy)), UsernamePasswordCredentials.new(username, password)
571
+ if proxy_user
572
+ provider.set_credentials AuthScope.new(get_proxy_host(proxy)), UsernamePasswordCredentials.new(proxy_user, proxy_pass)
554
573
  end
555
574
  context.set_credentials_provider(provider)
556
575
  end
@@ -561,9 +580,9 @@ module Manticore
561
580
  when nil
562
581
  []
563
582
  when Hash
564
- value.flat_map {|key, val| struct_to_name_value_pairs val, namespace ? "#{namespace}[#{key}]" : key }
583
+ value.flat_map { |key, val| struct_to_name_value_pairs val, namespace ? "#{namespace}[#{key}]" : key }
565
584
  when Array
566
- value.flat_map {|val| struct_to_name_value_pairs val, namespace }
585
+ value.flat_map { |val| struct_to_name_value_pairs val, namespace }
567
586
  else
568
587
  BasicNameValuePair.new(namespace, value.to_s)
569
588
  end
@@ -572,6 +591,7 @@ module Manticore
572
591
  # Apache HTTP assumes ISO_8859_1 for StringEntities; we'll try to be nice and pass that when possible
573
592
  # so that it doesn't have to any multibyte work.
574
593
  ISO_8859_1 = "ISO-8859-1".freeze
594
+
575
595
  def minimum_encoding_for(string)
576
596
  if string.ascii_only?
577
597
  ISO_8859_1
@@ -623,44 +643,50 @@ module Manticore
623
643
  end
624
644
 
625
645
  KEY_EXTRACTION_REGEXP = /(?:^-----BEGIN(.* )PRIVATE KEY-----\n)(.*?)(?:-----END\1PRIVATE KEY.*$)/m
646
+
626
647
  def setup_key_store(ssl_options, context)
627
648
  key_store = get_store(:keystore, ssl_options) if ssl_options.key?(:keystore)
628
649
  keystore_password = (ssl_options[:keystore_password] || "").to_java.toCharArray
629
650
 
630
651
  # Support OpenSSL-style bare X.509 certs with an RSA key
631
- # This is really dumb - we have to b64-decode the key ourselves, and we can only support PKCS8
632
652
  if ssl_options[:client_cert] && ssl_options[:client_key]
633
653
  key_store ||= blank_keystore
634
654
  certs, key = nil, nil
635
- open(ssl_options[:client_cert]) do |fp|
636
- certs = CertificateFactory.get_instance("X509").generate_certificates(fp.to_inputstream).to_array([].to_java(Certificate))
637
- end
655
+
656
+ cert_str = if ssl_options[:client_cert].is_a?(OpenSSL::X509::Certificate)
657
+ ssl_options[:client_cert].to_s
658
+ elsif ssl_options[:client_cert].is_a?(String) && File.exists?(ssl_options[:client_cert])
659
+ File.read(ssl_options[:client_cert])
660
+ else
661
+ ssl_options[:client_cert].to_s
662
+ end
663
+
664
+ cert_stream = java.io.ByteArrayInputStream.new(cert_str.strip.to_java_bytes)
665
+ certs = CertificateFactory.get_instance("X509").generate_certificates(cert_stream).to_array([].to_java(Certificate))
666
+
667
+ key_str = if ssl_options[:client_key].is_a?(OpenSSL::PKey::PKey)
668
+ ssl_options[:client_key].to_pem_pkcs8
669
+ elsif ssl_options[:client_key].is_a?(String) && File.exists?(ssl_options[:client_key])
670
+ File.read(ssl_options[:client_key])
671
+ else
672
+ ssl_options[:client_key].to_s
673
+ end
638
674
 
639
675
  # Add each of the keys in the given keyfile into the keystore.
640
- open(ssl_options[:client_key]) do |fp|
641
- key_parts = fp.read.scan(KEY_EXTRACTION_REGEXP)
642
- key_parts.each do |type, b64key|
643
- body = Base64.decode64 b64key
644
- spec = PKCS8EncodedKeySpec.new(body.to_java_bytes)
645
- type = type.strip
646
- type = "RSA" if type == ""
647
- key = KeyFactory.getInstance(type).generatePrivate(spec)
648
- key_store.set_key_entry("key-#{Digest::SHA1.hexdigest(body)}", key, keystore_password, certs)
649
- end
676
+ key_parts = key_str.scan(KEY_EXTRACTION_REGEXP)
677
+ key_parts.each do |type, b64key|
678
+ body = Base64.decode64 b64key
679
+ spec = PKCS8EncodedKeySpec.new(body.strip.to_java_bytes)
680
+ type = type.strip
681
+ type = "RSA" if type == ""
682
+ key = KeyFactory.getInstance(type).generatePrivate(spec)
683
+ key_store.set_key_entry("key-#{Digest::SHA1.hexdigest(body)}", key, keystore_password, certs)
650
684
  end
651
685
  end
652
686
 
653
687
  context.load_key_material(key_store, keystore_password) if key_store
654
688
  end
655
689
 
656
- def get_trust_store(options)
657
- get_store :truststore, options
658
- end
659
-
660
- def get_key_store(options)
661
- get_store :keystore, options
662
- end
663
-
664
690
  def get_store(prefix, options)
665
691
  KeyStore.get_instance(options[:"#{prefix}_type"] || guess_store_type(options[prefix])).tap do |store|
666
692
  instream = open(options[prefix], "rb").to_inputstream
@@ -669,7 +695,7 @@ module Manticore
669
695
  end
670
696
 
671
697
  def blank_keystore
672
- KeyStore.get_instance(KeyStore.get_default_type).tap {|k| k.load(nil, nil) }
698
+ KeyStore.get_instance(KeyStore.get_default_type).tap { |k| k.load(nil, nil) }
673
699
  end
674
700
 
675
701
  def guess_store_type(filename)
@@ -682,7 +708,7 @@ module Manticore
682
708
 
683
709
  def treat_params_as_query(options)
684
710
  if options.key?(:params) && !options.key?(:query)
685
- options.dup.tap {|o| o[:query] = o.delete(:params) }
711
+ options.dup.tap { |o| o[:query] = o.delete(:params) }
686
712
  else
687
713
  options
688
714
  end