manticore 0.3.1-java → 0.3.2-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
2
  SHA1:
3
- metadata.gz: 60f70fa96f93b6d9092b0455c139ae2aaf077fcf
4
- data.tar.gz: ea9ab057b99806987c30ff3198cefd1d0d6ae455
3
+ metadata.gz: cb2cec897fad8daff54f1823bb5a01f33da18d2e
4
+ data.tar.gz: 4ee22665fa497aceaa9b5df01c79264ef47a8667
5
5
  SHA512:
6
- metadata.gz: 24112c6208d50c27c68745340cf29c87f6cc37a8abeebb3bc051d2dc37ba883465f78e027e3dc4b5d77122c2bc9c2d9c2b6377607715bff5c953e38f0171ddb1
7
- data.tar.gz: db3909740b474447d5467290992aad8b51fa34c39006714d14848650686f3ffaa095c3e8674df2f7ae0c834d7ac8fda4cc291485e790f9f3f44289a2041a647e
6
+ metadata.gz: 2be50f1dff4384bd95f61d6d5328aa4690461436c9d57dadae905fba897602b1c470d41763edca4955ea1d45f96f48ef80a52eccab4b3679e26bda1317cd78d6
7
+ data.tar.gz: 174cae4b6fef3465b339bbd4e831eed8aeb40284459102fe68fa32b3412b04460b3cbc8c649267339e50830263d0a894760fe14c55ee6c778c9370e021a6db45
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,4 +1,22 @@
1
1
  ## v0.3
2
+ ### v0.3.3 (pending)
3
+ ### v0.3.2
4
+ * :ignore_ssl_validation is now deprecated. It has been replaced with :ssl, which takes a hash of options. These include:
5
+
6
+ :verify - :strict (default), :browser, :none -- Specify hostname verification behaviors.
7
+ :protocols - An array of protocols to accept
8
+ :cipher_suites - An array of cipher suites to accept
9
+ :truststore - Path to a keytool trust store, for specifying custom trusted certificate signers
10
+ :truststore_password - Password for the file specified in `:truststore`
11
+ :truststore_type - Specify the trust store type (JKS, PKCS12)
12
+ :keystore - Path to a keytool trust store, for specifying client authentication certificates
13
+ :keystore_password - Password for the file specified in `:keystore`
14
+ :keystore_type - Specify the key store type (JKS, PKCS12)
15
+
16
+ (thanks @torrancew)
17
+
18
+ * Fix encodings for bodies (thanks @synhaptein)
19
+
2
20
  ### v0.3.1
3
21
  * Added `automatic_retries` (default 3) parameter to client. The client will automatically retry requests that failed
4
22
  due to socket exceptions and empty responses up to this number of times. The most practical effect of this setting is
data/README.md CHANGED
@@ -47,9 +47,15 @@ If you don't want to worry about setting up and maintaining client pools, Mantic
47
47
 
48
48
  ```ruby
49
49
  document_body = Manticore.get("http://www.google.com/").body
50
+
51
+ # Or
52
+
53
+ document_body = Manticore.http(:get, "http://www.google.com/").body
50
54
  ```
51
55
 
52
- Additionally, you can mix the `Manticore::Facade` into your own class for similar behavior:
56
+ This is threadsafe and automatically backed with a pool, so you can execute `Manticore.get` in multiple threads without harming performance.
57
+
58
+ Alternately, you can mix the `Manticore::Facade` into your own class for similar behavior:
53
59
 
54
60
  ```ruby
55
61
  class MyClient
@@ -74,9 +80,11 @@ class MyOtherClient
74
80
  end
75
81
  ```
76
82
 
77
- ### More Control
83
+ For detailed documentation, see the [full Manticore::Client documentation](http://www.rubydoc.info/github/cheald/manticore/master/Manticore/Client).
84
+
85
+ ### Configuring clients
78
86
 
79
- Manticore is built around a connection pool. When you create a `Client`, you will pass various parameters that it will use to set up the pool.
87
+ 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.
80
88
 
81
89
  ```ruby
82
90
  client = Manticore::Client.new(request_timeout: 5, connect_timeout: 5, socket_timeout: 5, pool_max: 10, pool_max_per_route: 2)
@@ -99,6 +107,32 @@ client = Manticore::Client.new(socket_timeout: 5) do |http_client_builder, reque
99
107
  end
100
108
  ```
101
109
 
110
+ ### Pools
111
+
112
+ You've seen "pools" mentioned a few times. Manticore creates and configures a [PoolingHttpClientConnectionManager](http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html)
113
+ which all requests are run through. The advantage here is that configuration and setup is performed once, and this lets clients take advantage of things like keepalive,
114
+ per-route concurrency limits, and other neat things. In general, you should create one `Manticore::Client` instance pe unique configuration needed. For example, you might have an app that performs 2 functions:
115
+
116
+ 1. General HTTP requesting from the internet-at-large
117
+ 2. Communication with a backend service over SSL, using a custom trust store
118
+
119
+ To set this up, you might create 2 pools, each configured for the task:
120
+
121
+ ```ruby
122
+ general_http_client = Manticore::Client.new connect_timeout: 10, socket_timeout: 10, request_timeout: 10, follow_redirects: true, max_per_route: 2
123
+ proxied_backend_client = Manticore::Client.new proxy: "https://backend.internal:4242", truststore: "./truststore.jks", truststore_password: "s3cr3t"
124
+ ```
125
+
126
+ This would create 2 separate request pools; the first would be configured with generous timeouts and redirect following, and would use the system
127
+ default trust stores (ie, the normal certs used to verify SSL certificates with the normal certificate authorities). Additionally, it will only permit
128
+ 2 concurrent requests to a given domain ("route") at a time; this can be nice for web crawling or fetching against rate-limited APIs, to help you stay
129
+ under your rate limits even when executing in a parallel context. The second client would use a custom trust store to recognize certs signed with your
130
+ internal CA, and would proxy all requests through an internal server.
131
+
132
+ Creating pools is expensive, so you don't want to be doing it for each request. Instead, you should set up your pools once and then re-use them.
133
+ Clients and their backing pools are thread-safe, so feel free to set them up once before you start performing parallel operations.
134
+
135
+
102
136
  ### Parallel execution
103
137
 
104
138
  Manticore can perform concurrent execution of multiple requests.
@@ -48,11 +48,11 @@ module Manticore
48
48
  #
49
49
  # @!macro [new] http_method_shared_async_with_body
50
50
  # @macro http_method_shared_async
51
- # @option options [Hash] body Hash of options to pass as request body
51
+ # @option options [String] body Body to pass with the request
52
52
  #
53
53
  # @!macro [new] http_method_shared_sync_with_body
54
54
  # @macro http_method_shared_sync
55
- # @option options [Hash] body Hash of options to pass as request body
55
+ # @option options [String] body Body to pass with the request
56
56
 
57
57
  # Core Manticore client, with a backing {http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/org/apache/http/impl/conn/PoolingHttpClientConnectionManager.html PoolingHttpClientConnectionManager}
58
58
  class Client
@@ -60,6 +60,7 @@ module Manticore
60
60
  include_package "org.apache.http.client.entity"
61
61
  include_package "org.apache.http.client.config"
62
62
  include_package "org.apache.http.config"
63
+ include_package "org.apache.http.conn.socket"
63
64
  include_package "org.apache.http.impl"
64
65
  include_package "org.apache.http.impl.client"
65
66
  include_package "org.apache.http.impl.conn"
@@ -72,6 +73,8 @@ module Manticore
72
73
  include_package "org.apache.http.client.protocol"
73
74
  include_package 'org.apache.http.conn.ssl'
74
75
  java_import "org.apache.http.HttpHost"
76
+ java_import "javax.net.ssl.SSLContext"
77
+ java_import "java.security.KeyStore"
75
78
 
76
79
  include ProxiesInterface
77
80
 
@@ -101,27 +104,40 @@ module Manticore
101
104
  # http_client_builder.disable_redirect_handling
102
105
  # end
103
106
  #
104
- # @param options [Hash] Client pool options
105
- # @option options [String] user_agent The user agent used in requests.
106
- # @option options [Integer] pool_max (50) The maximum number of active connections in the pool
107
- # @option options [integer] pool_max_per_route (pool_max) Sets the maximum number of active connections for a given target endpoint
108
- # @option options [boolean] cookies (true) enable or disable automatic cookie management between requests
109
- # @option options [boolean] compression (true) enable or disable transparent gzip/deflate support
110
- # @option options [integer] request_timeout (60) Sets the timeout for requests. Raises {Manticore::Timeout} on failure.
111
- # @option options [integer] connect_timeout (10) Sets the timeout for connections. Raises Manticore::Timeout on failure.
112
- # @option options [integer] socket_timeout (10) Sets SO_TIMEOUT for open connections. A value of 0 is an infinite timeout. Raises Manticore::Timeout on failure.
113
- # @option options [boolean] tcp_no_delay (true) Enable or disable Nagle's algorithm
114
- # @option options [integer] request_timeout (60) Sets the timeout for a given request. Raises Manticore::Timeout on failure.
115
- # @option options [integer] max_redirects (5) Sets the maximum number of redirects to follow.
116
- # @option options [integer] automatic_retries (3) Sets the number of times the client will automatically retry failed requests.
117
- # @option options [boolean] expect_continue (false) Enable support for HTTP 100
118
- # @option options [boolean] stale_check (false) Enable support for stale connection checking. Adds overhead.
119
- # @option options [String] proxy Proxy host in form: http://proxy.org:1234
120
- # @option options [Hash] proxy Proxy host in form: {host: 'proxy.org'[, port: 80[, scheme: 'http']]}
121
- # @option options [URI] proxy Proxy host as a URI object
122
- # @option options [Boolean/Integer] keepalive (true) Whether to allow connections to be reused. Defaults to true. If an integer,
123
- # then connections will be kept alive for this long when Connection: keep-alive
124
- # is sent, but no Keep-Alive header is sent.
107
+ # @param options [Hash] Client pool options
108
+ # @option options [String] user_agent The user agent used in requests.
109
+ # @option options [Integer] pool_max (50) The maximum number of active connections in the pool
110
+ # @option options [integer] pool_max_per_route (pool_max) Sets the maximum number of active connections for a given target endpoint
111
+ # @option options [boolean] cookies (true) enable or disable automatic cookie management between requests
112
+ # @option options [boolean] compression (true) enable or disable transparent gzip/deflate support
113
+ # @option options [integer] request_timeout (60) Sets the timeout for requests. Raises {Manticore::Timeout} on failure.
114
+ # @option options [integer] connect_timeout (10) Sets the timeout for connections. Raises Manticore::Timeout on failure.
115
+ # @option options [integer] socket_timeout (10) Sets SO_TIMEOUT for open connections. A value of 0 is an infinite timeout. Raises Manticore::Timeout on failure.
116
+ # @option options [boolean] tcp_no_delay (true) Enable or disable Nagle's algorithm
117
+ # @option options [integer] request_timeout (60) Sets the timeout for a given request. Raises Manticore::Timeout on failure.
118
+ # @option options [integer] max_redirects (5) Sets the maximum number of redirects to follow.
119
+ # @option options [integer] automatic_retries (3) Sets the number of times the client will automatically retry failed requests.
120
+ # @option options [boolean] expect_continue (false) Enable support for HTTP 100
121
+ # @option options [boolean] stale_check (false) Enable support for stale connection checking. Adds overhead.
122
+ # @option options [String] proxy Proxy host in form: http://proxy.org:1234
123
+ # @option options [Hash] proxy Proxy host in form: {host: 'proxy.org'[, port: 80[, scheme: 'http']]}
124
+ # @option options [URI] proxy Proxy host as a URI object
125
+ # @option options [Boolean/Fixnum] keepalive (true) Whether to allow connections to be reused. Defaults to true. If an integer,
126
+ # then connections will be kept alive for this long when Connection: keep-alive
127
+ # is sent, but no Keep-Alive header is sent.
128
+ # @option options [Hash] ssl Hash of options for configuring SSL
129
+ # @option options [Array<String>] ssl[:protocols] (nil) A list of protocols that Manticore should accept
130
+ # @option options [Array<String>] ssl[:cipher_suites] (nil) A list of cipher suites that Manticore should accept
131
+ # @option options [Symbol] ssl[:verify] (:strict) Hostname verification setting. Set to `:disable` to turn off hostname verification. Setting to `:browser` will
132
+ # cause Manticore to accept a certificate for *.foo.com for all subdomains and sub-subdomains (eg a.b.foo.com).
133
+ # The default `:strict` is like `:browser` except it'll only accept a single level of subdomains for wildcards,
134
+ # eg `b.foo.com` will be accepted for a `*.foo.com` certificate, but `a.b.foo.com` will not be.
135
+ # @option options [String] ssl[:truststore] (nil) Path to a custom trust store to use the verifying SSL connections
136
+ # @option options [String] ssl[:truststore_password] (nil) Password used for decrypting the server trust store
137
+ # @option options [String] ssl[:truststore_type] (nil) Format of the trust store, ie "JKS" or "PKCS12". If left nil, the type will be inferred from the truststore filename.
138
+ # @option options [String] ssl[:keystore] (nil) Path to a custom key store to use for client certificate authentication
139
+ # @option options [String] ssl[:keystore_password] (nil) Password used for decrypting the client auth key store
140
+ # @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.
125
141
  def initialize(options = {})
126
142
  builder = client_builder
127
143
  builder.set_user_agent options.fetch(:user_agent, "Manticore #{VERSION}")
@@ -241,6 +257,19 @@ module Manticore
241
257
  end
242
258
  end
243
259
 
260
+ # Perform an HTTP request, passing the method as a parameter
261
+ # @param method [String, Symbol] Method to call (get put head post options patch)
262
+ # @macro http_method_shared
263
+ # @macro http_request_exceptions
264
+ def http(method, url, options = {}, &block)
265
+ case method.to_s.downcase
266
+ when *%w(get put head post options patch)
267
+ send method, url, options, &block
268
+ else
269
+ raise "Invalid method: #{method}"
270
+ end
271
+ end
272
+
244
273
  # Cause this client to return a stubbed response for this URL
245
274
  # @param url [String] URL to stub for
246
275
  # @param stubs [Hash] Hash of options to return for the stubbed response
@@ -289,14 +318,17 @@ module Manticore
289
318
  end
290
319
 
291
320
  def pool_builder(options)
292
- if options.fetch(:ignore_ssl_validation, false)
293
- context = SSLContexts.custom.load_trust_material(nil, TrustSelfSignedStrategy.new).build
294
- sslsf = SSLConnectionSocketFactory.new(context, SSLConnectionSocketFactory::ALLOW_ALL_HOSTNAME_VERIFIER)
295
- registry = RegistryBuilder.create.register("https", sslsf).build
296
- PoolingHttpClientConnectionManager.new(registry)
297
- else
298
- PoolingHttpClientConnectionManager.new
321
+ http_sf = PlainConnectionSocketFactory.new
322
+
323
+ if options[:ignore_ssl_validation]
324
+ $stderr.puts 'The options[:ignore_ssl_validation] setting is deprecated in favor of options[:ssl][:verify]'
325
+ options[:ssl] ||= {}
326
+ options[:ssl] = {:verify => !options.delete(:ignore_ssl_validation)}.merge(options[:ssl])
299
327
  end
328
+
329
+ https_sf = ssl_socket_factory_from_options options.fetch(:ssl, {})
330
+ registry = RegistryBuilder.create.register("http", http_sf).register("https", https_sf).build
331
+ PoolingHttpClientConnectionManager.new(registry)
300
332
  end
301
333
 
302
334
  def pool(options = {})
@@ -380,7 +412,7 @@ module Manticore
380
412
  if options[:params]
381
413
  req.set_entity hash_to_entity(options[:params])
382
414
  elsif options[:body]
383
- req.set_entity StringEntity.new(options[:body])
415
+ req.set_entity StringEntity.new(options[:body], minimum_encoding_for(options[:body]))
384
416
  elsif options[:entity]
385
417
  req.set_entity options[:entity]
386
418
  end
@@ -442,10 +474,79 @@ module Manticore
442
474
  end
443
475
 
444
476
  def hash_to_entity(hash)
477
+ # This is a really stupid way to get the "lowest common denominator" encoding for the options hash
478
+ # Is there a better way?
479
+ encoding = minimum_encoding_for hash.to_a.flatten.join
445
480
  pairs = hash.map do |key, val|
446
481
  BasicNameValuePair.new(key, val)
447
482
  end
448
- UrlEncodedFormEntity.new(pairs)
483
+ UrlEncodedFormEntity.new(pairs, encoding)
484
+ end
485
+
486
+ # Apache HTTP assumes ISO_8859_1 for StringEntities; we'll try to be nice and pass that when possible
487
+ # so that it doesn't have to any multibyte work.
488
+ ISO_8859_1 = "ISO-8859-1".freeze
489
+ def minimum_encoding_for(string)
490
+ if string.ascii_only?
491
+ ISO_8859_1
492
+ else
493
+ string.encoding.to_s
494
+ end
495
+ end
496
+
497
+ # Configure the SSL Context
498
+ def ssl_socket_factory_from_options(ssl_options)
499
+ trust_store = trust_strategy = nil
500
+
501
+ verifier = SSLConnectionSocketFactory::STRICT_HOSTNAME_VERIFIER
502
+ case ssl_options.fetch(:verify, :strict)
503
+ when false, :disable, :none
504
+ trust_store = nil
505
+ trust_strategy = TrustSelfSignedStrategy.new
506
+ verifier = SSLConnectionSocketFactory::ALLOW_ALL_HOSTNAME_VERIFIER
507
+ when :browser
508
+ verifier = SSLConnectionSocketFactory::BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
509
+ when true, :strict, :default
510
+ verifier = SSLConnectionSocketFactory::STRICT_HOSTNAME_VERIFIER
511
+ else
512
+ raise "Invalid value for :verify. Valid values are (:all, :browser, :default)"
513
+ end
514
+
515
+
516
+ context = SSLContexts.custom
517
+
518
+ trust_store = get_store(:truststore, ssl_options) if ssl_options.key?(:truststore)
519
+ context.load_trust_material(trust_store, trust_strategy)
520
+
521
+ if ssl_options.key?(:keystore)
522
+ key_store = get_store(:keystore, ssl_options)
523
+ context.load_key_material(key_store, ssl_options.fetch(:keystore_password, nil).to_java.toCharArray)
524
+ end
525
+
526
+ SSLConnectionSocketFactory.new context.build, ssl_options[:protocols], ssl_options[:cipher_suites], verifier
527
+ end
528
+
529
+ def get_trust_store(options)
530
+ get_store :truststore, options
531
+ end
532
+
533
+ def get_key_store(options)
534
+ get_store :keystore, options
535
+ end
536
+
537
+ def get_store(prefix, options)
538
+ KeyStore.get_instance(options[:"#{prefix}_type"] || guess_store_type(options[prefix])).tap do |store|
539
+ instream = open(options[prefix], "rb").to_inputstream
540
+ store.load(instream, options.fetch(:"#{prefix}_password", nil).to_java.toCharArray)
541
+ end
542
+ end
543
+
544
+ def guess_store_type(filename)
545
+ if filename.end_with?(".p12")
546
+ "pkcs12"
547
+ else
548
+ KeyStore.get_default_type
549
+ end
449
550
  end
450
551
  end
451
- end
552
+ end
@@ -1,3 +1,3 @@
1
1
  module Manticore
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -1,3 +1,4 @@
1
+ # encoding: utf-8
1
2
  require 'spec_helper'
2
3
 
3
4
  java_import 'org.apache.http.entity.mime.MultipartEntityBuilder'
@@ -41,7 +42,7 @@ describe Manticore::Client do
41
42
  j["uri"]["port"].should == 55441
42
43
  end
43
44
 
44
- describe "ignore_ssl_validation" do
45
+ describe "ignore_ssl_validation (deprecated option)" do
45
46
  context "when on" do
46
47
  let(:client) { Manticore::Client.new ignore_ssl_validation: true }
47
48
 
@@ -59,6 +60,90 @@ describe Manticore::Client do
59
60
  end
60
61
  end
61
62
 
63
+ describe 'ssl settings' do
64
+ describe 'verify' do
65
+ context 'default' do
66
+ let(:client) { Manticore::Client.new }
67
+
68
+ it "should break on SSL validation errors" do
69
+ expect { client.get("https://localhost:55444/").call }.to raise_exception(Manticore::ClientProtocolException)
70
+ end
71
+ end
72
+
73
+ context 'when on and no trust store is given' do
74
+ let(:client) { Manticore::Client.new :ssl => {:verify => :strict} }
75
+
76
+ it "should break on SSL validation errors" do
77
+ expect { client.get("https://localhost:55444/").call }.to raise_exception(Manticore::ClientProtocolException)
78
+ end
79
+ end
80
+
81
+ context 'when on and custom trust store is given' do
82
+ let(:client) { Manticore::Client.new :ssl => {verify: :strict, truststore: File.expand_path("../../ssl/test_truststore", __FILE__), truststore_password: "test123"} }
83
+
84
+ it "should verify the request and succeed" do
85
+ expect { client.get("https://localhost:55444/").body }.to_not raise_exception
86
+ end
87
+ end
88
+
89
+ context 'when on and custom trust store is given with the wrong password' do
90
+ let(:client) { Manticore::Client.new :ssl => {verify: :strict, truststore: File.expand_path("../../ssl/test_truststore", __FILE__), truststore_password: "wrongpass"} }
91
+
92
+ it "should fail to load the keystore" do
93
+ expect { client.get("https://localhost:55444/").body }.to raise_exception(Java::JavaIo::IOException)
94
+ end
95
+ end
96
+
97
+ context 'when off' do
98
+ let(:client) { Manticore::Client.new :ssl => {:verify => :none} }
99
+
100
+ it "should not break on SSL validation errors" do
101
+ expect { client.get("https://localhost:55444/").body }.to_not raise_exception
102
+ end
103
+ end
104
+
105
+ context "against a server that verifies clients" do
106
+ context "when client cert auth is provided" do
107
+ let(:client) {
108
+ options = {
109
+ truststore: File.expand_path("../../ssl/test_truststore", __FILE__),
110
+ truststore_password: "test123",
111
+ keystore: File.expand_path("../../ssl/client.p12", __FILE__),
112
+ keystore_password: ""
113
+ }
114
+ Manticore::Client.new :ssl => options.merge(verify: :strict)
115
+ }
116
+
117
+ it "should successfully auth requests" do
118
+ expect(client.get("https://localhost:55445/").body).to match("hello")
119
+ end
120
+ end
121
+
122
+ context "when client cert auth is not provided" do
123
+ let(:client) {
124
+ options = {
125
+ truststore: File.expand_path("../../ssl/test_truststore", __FILE__),
126
+ truststore_password: "test123"
127
+ }
128
+ Manticore::Client.new :ssl => options.merge(verify: :strict)
129
+ }
130
+
131
+ it "should fail the request" do
132
+ expect { client.get("https://localhost:55445/").body }.to raise_exception(Manticore::ClientProtocolException)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ describe ":cipher_suites" do
139
+ pending
140
+ end
141
+
142
+ describe ":protocols" do
143
+ pending
144
+ end
145
+ end
146
+
62
147
  describe "lazy evaluation" do
63
148
  it "should not call synchronous requests by default" do
64
149
  req = client.get(local_server)
@@ -231,9 +316,19 @@ describe Manticore::Client do
231
316
  JSON.load(response.body)["body"].should == "This is a post body"
232
317
  end
233
318
 
319
+ it "should send a UTF-8 body" do
320
+ response = client.post(local_server, body: "This is a post body ∑")
321
+ JSON.load(response.body)["body"].should == "This is a post body ∑"
322
+ end
323
+
234
324
  it "should send params" do
235
325
  response = client.post(local_server, params: {key: "value"})
236
- JSON.load(response.body)["body"].should == "key=value"
326
+ CGI.unescape(JSON.load(response.body)["body"]).should == "key=value"
327
+ end
328
+
329
+ it "should send non-ASCII params" do
330
+ response = client.post(local_server, params: {"∑" => "√"})
331
+ CGI.unescape(JSON.load(response.body)["body"]).should == "∑=√"
237
332
  end
238
333
 
239
334
  it "should send an arbitrary entity" do
data/spec/spec_helper.rb CHANGED
@@ -6,6 +6,7 @@ require 'json'
6
6
  require 'rack'
7
7
  require 'webrick'
8
8
  require 'webrick/https'
9
+ require 'openssl'
9
10
 
10
11
  PORT = 55441
11
12
 
@@ -16,14 +17,14 @@ end
16
17
  def read_nonblock(socket)
17
18
  buffer = ""
18
19
  loop {
19
- begin
20
- buffer << socket.read_nonblock(4096)
21
- rescue Errno::EAGAIN
22
- # Resource temporarily unavailable - read would block
23
- break
24
- end
20
+ begin
21
+ buffer << socket.read_nonblock(4096)
22
+ rescue Errno::EAGAIN
23
+ # Resource temporarily unavailable - read would block
24
+ break
25
+ end
25
26
  }
26
- buffer
27
+ buffer.force_encoding("UTF-8")
27
28
  end
28
29
 
29
30
  def start_server(port = PORT)
@@ -37,7 +38,7 @@ def start_server(port = PORT)
37
38
  end
38
39
 
39
40
  if cl = request[:headers]["Content-Length"] || request[:headers]["Transfer-Encoding"] == "chunked"
40
- request[:body] = read_nonblock stream.socket
41
+ request[:body] = read_nonblock(stream.socket)
41
42
  end
42
43
 
43
44
  content_type = request[:headers]["X-Content-Type"] || "text/plain"
@@ -87,18 +88,28 @@ def stop_servers
87
88
  @servers.values.each(&:kill) if @servers
88
89
  end
89
90
 
90
- def start_ssl_server(port)
91
+ def start_ssl_server(port, options = {})
91
92
  cert_name = [
92
93
  %w[CN localhost],
93
94
  ]
95
+ cert = OpenSSL::X509::Certificate.new File.read(File.expand_path('../ssl/localhost.pem', __FILE__))
96
+ pkey = OpenSSL::PKey::RSA.new File.read(File.expand_path('../ssl/localhost.key', __FILE__))
94
97
  @servers[port] = Thread.new {
95
- server = WEBrick::HTTPServer.new(:Port => port, :SSLEnable => true, :SSLCertName => cert_name, :Logger => WEBrick::Log.new("/dev/null"))
98
+ server = WEBrick::HTTPServer.new(
99
+ {
100
+ :Port => port,
101
+ :SSLEnable => true,
102
+ :SSLCertificate => cert,
103
+ :SSLPrivateKey => pkey,
104
+ :AccessLog => [],
105
+ :Logger => WEBrick::Log.new("/dev/null")
106
+ }.merge(options)
107
+ )
96
108
  server.mount_proc "/" do |req, res|
97
109
  res.body = "hello!"
98
110
  end
99
111
 
100
112
  server.start
101
- puts "Server started?"
102
113
  }
103
114
  end
104
115
 
@@ -110,6 +121,7 @@ RSpec.configure do |c|
110
121
  start_server 55441
111
122
  start_server 55442
112
123
  start_ssl_server 55444
124
+ start_ssl_server 55445, :SSLVerifyClient => OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT, :SSLCACertificateFile => File.expand_path("../ssl/ca_cert.pem", __FILE__)
113
125
  }
114
126
 
115
127
  c.after(:suite) { stop_servers }
@@ -0,0 +1,33 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ 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
32
+ wuhTyH5RfnYu
33
+ -----END CERTIFICATE-----
@@ -0,0 +1,52 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ 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
51
+ umjprdvaT6QOMOjb1GZqJhdCLskcB/w=
52
+ -----END PRIVATE KEY-----
Binary file
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC4I1J9AVuytCuy
3
+ BlmDQD/ZhJygHhLhGN2ZBPd2mBs0OfnNO2ert9zo5jUaRvHAKhTs6/gmmMd2U39R
4
+ TnN4cqHtEVbyDp/97zY4v75rL9iILk8l18qJVSbdsbEdZ9fyuj9MnLNY+J100FVS
5
+ jfNIR+mCunVPjI+Mb2tooSOZKovdcTZVZcLVwnnkXsPbDFOZbWp3V0v0vqyYxAQB
6
+ sLEypEtt1fzKrL0gevTCsRFYxsUbjdaJmb4E63hKAr+PkrjXT6r6gR4oWjFejoIm
7
+ OhEZxm1H6cLwBWK/PM55b7kdV9pNUetXTNz5uTjKx0512rsBC9GZK9rM/wATI1o+
8
+ KsXSxuDnAgMBAAECggEAG2OFnXpaPVZ3OV+gaNlhpeUHtvlCLaEZNO18MXOmeDo3
9
+ YcN4RB5xCWNUergatU6NFkBzBKqs4HjC80EMA9ppI2301MRAH/E4y3AZzq+rMXZR
10
+ 53sVcR/tTARmJ82OXVg+mhKkypMQOJPUXRcoHJQ1s3AwisiJgYYBH+r39IxTiXhQ
11
+ vMuiUFHmQSn7TAsDV9ULMvYmMh4FA+9RVW1DJ9zH5/IQKtRyLVupulGimF8n0kVR
12
+ tNVqwTckZpJJlZFdLHUjaTiSm4s5vYwoxNzNXxZ0GnBXBxs5YAErEjas/OhmYguZ
13
+ lFwpkVuV9/dwR4jfPRciGuRuJqO2I2Pp6K6/Z+QLoQKBgQDmYRNnOfESwaqVWh9G
14
+ VmT70bhob5A2GwVS2fJ+UOBCfnwrn+ybR2AZjliKlM4a6k+pboPrwl4rncH2LlXO
15
+ o/EX9VyTdDCMxiN+YMlvOuzpVF1LrM/BL6pw3uMjmWBEMmbprwiMFCKRC4BJZ3Vv
16
+ X07A1zoKq8oNFW+m80Db1eMciwKBgQDMncDJLJFBqIcas5plUlwTQXmr8Xq/+Q/B
17
+ UB4yU75eUbp1H0jFrJ8ier6A1IXX2bVnxUjilATM/trIH4GLMK66j5hp0ih0JfjE
18
+ gYnI83GKOxL+KF0C2tLjjhuTAVtmWXla8s37dBtz3ZleyyKfaGzvgm3zjheD+s/R
19
+ ordHaRpMlQKBgEOvq9q9TFX9bpf45Y1t3reZ03tjo9Qxtiu0eymfq3P944+Rqhup
20
+ KdP4XY1B0RhZVVRrcvj2n2JjNFSXIoDW7APlA/ESxxzlLhJ4b1Zt0qNvNQYB3Pxe
21
+ e84zvjp8WqtOv6vS0EkPtWQ2I9ftPLSfJO1FjvkJphCYBrjfaWPtgI+nAoGBAMOS
22
+ RKIEJxJKslejMv+FKNx+yHy/4kN7GsP6f+I6iMo986nerP/DbpbWGx+oAgW94NW+
23
+ i1uFftExBowhEQCpF1jZxyPd6yyY3p1z8u5PQUaOECk9CymfXdKCEXkA4wuAma2E
24
+ Rb0BzPuB4wXnwr/6X6TNVaplNbTAFcKZc/SdULXBAoGBAM02iPIys9ghA1nfQHD+
25
+ MD4lJNyPzOrnx1C8SXPP/hHUbFRmZF9hW3U9vuwo7jD2MzIrHAycAaIUjIDkTD+w
26
+ rUYsH9nOAHCbk1lGqy24SF4Pcvpj28O4gfHBdBEq4c2b48moml3tJOPOTEude8fp
27
+ PgYaeX3y+gzY7K7ZSM+gIuuo
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,100 @@
1
+ Certificate:
2
+ Data:
3
+ Version: 3 (0x2)
4
+ Serial Number: 3 (0x3)
5
+ Signature Algorithm: sha256WithRSAEncryption
6
+ Issuer: C=US, ST=MD, L=Baltimore, CN=Test CA/emailAddress=test@example.com
7
+ Validity
8
+ Not Before: Nov 29 00:38:23 2014 GMT
9
+ Not After : Aug 25 00:38:23 2017 GMT
10
+ Subject: C=US, ST=Arizona, L=NA, O=Manticore, OU=Manticore, CN=localhost
11
+ Subject Public Key Info:
12
+ Public Key Algorithm: rsaEncryption
13
+ Public-Key: (2048 bit)
14
+ Modulus:
15
+ 00:b8:23:52:7d:01:5b:b2:b4:2b:b2:06:59:83:40:
16
+ 3f:d9:84:9c:a0:1e:12:e1:18:dd:99:04:f7:76:98:
17
+ 1b:34:39:f9:cd:3b:67:ab:b7:dc:e8:e6:35:1a:46:
18
+ f1:c0:2a:14:ec:eb:f8:26:98:c7:76:53:7f:51:4e:
19
+ 73:78:72:a1:ed:11:56:f2:0e:9f:fd:ef:36:38:bf:
20
+ be:6b:2f:d8:88:2e:4f:25:d7:ca:89:55:26:dd:b1:
21
+ b1:1d:67:d7:f2:ba:3f:4c:9c:b3:58:f8:9d:74:d0:
22
+ 55:52:8d:f3:48:47:e9:82:ba:75:4f:8c:8f:8c:6f:
23
+ 6b:68:a1:23:99:2a:8b:dd:71:36:55:65:c2:d5:c2:
24
+ 79:e4:5e:c3:db:0c:53:99:6d:6a:77:57:4b:f4:be:
25
+ ac:98:c4:04:01:b0:b1:32:a4:4b:6d:d5:fc:ca:ac:
26
+ bd:20:7a:f4:c2:b1:11:58:c6:c5:1b:8d:d6:89:99:
27
+ be:04:eb:78:4a:02:bf:8f:92:b8:d7:4f:aa:fa:81:
28
+ 1e:28:5a:31:5e:8e:82:26:3a:11:19:c6:6d:47:e9:
29
+ c2:f0:05:62:bf:3c:ce:79:6f:b9:1d:57:da:4d:51:
30
+ eb:57:4c:dc:f9:b9:38:ca:c7:4e:75:da:bb:01:0b:
31
+ d1:99:2b:da:cc:ff:00:13:23:5a:3e:2a:c5:d2:c6:
32
+ e0:e7
33
+ Exponent: 65537 (0x10001)
34
+ X509v3 extensions:
35
+ X509v3 Subject Key Identifier:
36
+ 00:AD:24:E9:F6:F5:82:D6:44:2E:DB:A3:16:75:E4:B9:56:5E:87:55
37
+ X509v3 Authority Key Identifier:
38
+ keyid:C8:B7:44:26:1E:FA:12:7F:5E:DE:C1:D0:A8:91:36:CE:43:A5:8A:41
39
+
40
+ X509v3 Basic Constraints:
41
+ CA:FALSE
42
+ X509v3 Key Usage:
43
+ Digital Signature, Non Repudiation, Key Encipherment
44
+ Signature Algorithm: sha256WithRSAEncryption
45
+ 99:1b:a2:a5:63:03:22:70:62:4a:ff:3d:c7:46:53:25:9d:4c:
46
+ 9c:73:4f:b6:fa:cd:7a:57:cb:96:3b:8f:58:4e:26:b4:30:ea:
47
+ 39:25:ad:8f:f9:ce:8c:87:ef:fc:5a:8e:94:3e:37:ac:35:e2:
48
+ d1:4f:e2:1c:59:33:4c:19:08:33:53:6b:d3:da:d1:2b:7a:90:
49
+ 2a:15:f6:49:4f:95:4a:34:46:a1:a6:43:15:2d:c5:bc:e8:1b:
50
+ 9a:1c:bd:f3:01:b1:60:16:5d:7e:1b:52:9c:08:d6:b8:2e:68:
51
+ 2c:68:11:65:52:8a:52:fa:86:ee:a7:9f:bc:a7:54:a0:4d:3e:
52
+ 78:4a:f6:fb:a5:ed:83:51:68:93:e5:46:c4:c9:30:ff:76:ee:
53
+ e3:e6:cd:c6:7f:1f:19:61:01:0d:5e:05:c3:38:fa:c2:dd:c3:
54
+ ec:0a:18:5e:bf:66:6b:c1:09:9b:38:47:43:69:09:9f:91:ff:
55
+ 4c:2c:71:d9:4a:63:0a:84:68:ef:ac:d3:29:f8:16:dc:d5:3f:
56
+ 38:8b:14:a1:a6:00:c2:b4:5d:53:7f:14:ce:fc:74:f4:cc:c2:
57
+ ee:9f:b6:9c:22:6c:af:1c:a5:ee:36:f7:ef:f2:02:80:18:69:
58
+ eb:ec:bc:03:df:b6:e1:3f:6f:a2:26:57:a0:6b:23:2f:05:bd:
59
+ 7a:36:db:41:7f:2e:30:b4:06:a6:47:9d:a7:8a:f3:3b:6e:b8:
60
+ b1:86:14:a0:38:2c:64:14:cb:df:4e:b3:47:f4:a0:e1:50:02:
61
+ cc:20:db:01:31:77:35:35:e9:ad:2b:f5:4f:f9:40:35:fb:1a:
62
+ ad:33:fd:37:7d:e9:52:65:11:df:d6:6a:9e:dd:ed:54:c1:25:
63
+ 71:33:08:5b:62:18:67:c8:4e:d6:82:64:f7:d7:3b:b8:9d:5d:
64
+ 55:36:fc:6f:da:97:56:48:91:28:e8:fa:38:5f:a3:c6:60:b5:
65
+ 35:f0:a9:bf:15:40:d0:fb:3a:42:df:e8:25:82:ff:19:93:a8:
66
+ 57:dc:f2:2c:5f:de:1a:13:c6:c9:e3:5d:a8:f7:d9:6e:66:0d:
67
+ 3e:fc:ea:59:25:89:2c:ff:91:0e:3e:08:83:25:2f:f2:de:3e:
68
+ ec:be:27:64:3c:84:20:20:47:1b:2a:e6:1f:33:6c:15:af:86:
69
+ 79:86:a5:0a:12:d3:89:0b:82:b4:98:cc:02:7b:ef:b6:4f:5a:
70
+ ef:96:7a:d9:51:dc:b7:41:b4:a3:23:6a:ed:32:22:76:88:b6:
71
+ ec:e5:be:cb:a6:98:b3:35:d5:74:7e:5f:1c:97:a3:ac:f6:75:
72
+ e0:98:64:57:4c:22:ea:c4:93:37:cb:74:28:c6:a0:fe:eb:ec:
73
+ 48:00:cc:06:97:de:82:7c
74
+ -----BEGIN CERTIFICATE-----
75
+ MIIEnjCCAoagAwIBAgIBAzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJVUzEL
76
+ MAkGA1UECAwCTUQxEjAQBgNVBAcMCUJhbHRpbW9yZTEQMA4GA1UEAwwHVGVzdCBD
77
+ QTEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTAeFw0xNDExMjkwMDM4
78
+ MjNaFw0xNzA4MjUwMDM4MjNaMGgxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdBcml6
79
+ b25hMQswCQYDVQQHDAJOQTESMBAGA1UECgwJTWFudGljb3JlMRIwEAYDVQQLDAlN
80
+ YW50aWNvcmUxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQAD
81
+ ggEPADCCAQoCggEBALgjUn0BW7K0K7IGWYNAP9mEnKAeEuEY3ZkE93aYGzQ5+c07
82
+ Z6u33OjmNRpG8cAqFOzr+CaYx3ZTf1FOc3hyoe0RVvIOn/3vNji/vmsv2IguTyXX
83
+ yolVJt2xsR1n1/K6P0ycs1j4nXTQVVKN80hH6YK6dU+Mj4xva2ihI5kqi91xNlVl
84
+ wtXCeeRew9sMU5ltandXS/S+rJjEBAGwsTKkS23V/MqsvSB69MKxEVjGxRuN1omZ
85
+ vgTreEoCv4+SuNdPqvqBHihaMV6OgiY6ERnGbUfpwvAFYr88znlvuR1X2k1R61dM
86
+ 3Pm5OMrHTnXauwEL0Zkr2sz/ABMjWj4qxdLG4OcCAwEAAaNaMFgwHQYDVR0OBBYE
87
+ FACtJOn29YLWRC7boxZ15LlWXodVMB8GA1UdIwQYMBaAFMi3RCYe+hJ/Xt7B0KiR
88
+ Ns5DpYpBMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgXgMA0GCSqGSIb3DQEBCwUAA4IC
89
+ AQCZG6KlYwMicGJK/z3HRlMlnUycc0+2+s16V8uWO49YTia0MOo5Ja2P+c6Mh+/8
90
+ Wo6UPjesNeLRT+IcWTNMGQgzU2vT2tErepAqFfZJT5VKNEahpkMVLcW86BuaHL3z
91
+ AbFgFl1+G1KcCNa4LmgsaBFlUopS+obup5+8p1SgTT54Svb7pe2DUWiT5UbEyTD/
92
+ du7j5s3Gfx8ZYQENXgXDOPrC3cPsChhev2ZrwQmbOEdDaQmfkf9MLHHZSmMKhGjv
93
+ rNMp+Bbc1T84ixShpgDCtF1TfxTO/HT0zMLun7acImyvHKXuNvfv8gKAGGnr7LwD
94
+ 37bhP2+iJlegayMvBb16NttBfy4wtAamR52nivM7brixhhSgOCxkFMvfTrNH9KDh
95
+ UALMINsBMXc1NemtK/VP+UA1+xqtM/03felSZRHf1mqe3e1UwSVxMwhbYhhnyE7W
96
+ gmT31zu4nV1VNvxv2pdWSJEo6Po4X6PGYLU18Km/FUDQ+zpC3+glgv8Zk6hX3PIs
97
+ X94aE8bJ412o99luZg0+/OpZJYks/5EOPgiDJS/y3j7svidkPIQgIEcbKuYfM2wV
98
+ r4Z5hqUKEtOJC4K0mMwCe++2T1rvlnrZUdy3QbSjI2rtMiJ2iLbs5b7LppizNdV0
99
+ fl8cl6Os9nXgmGRXTCLqxJM3y3QoxqD+6+xIAMwGl96CfA==
100
+ -----END CERTIFICATE-----
@@ -0,0 +1,14 @@
1
+ test_truststore is a trust store which has trusted the cacert.pem certificate
2
+
3
+ localhost.pem is a server certificate signed by our test CA
4
+
5
+ We can test custom trust stores by:
6
+
7
+ 1. Starting a server which uses localhost.pem/localhost.key to serve SSL
8
+ 2. Trusting ca_cert.pem (via the test_truststore)
9
+
10
+ And then verifying that SSL operations complete successfully.
11
+
12
+ The test_truststore password is `test123`
13
+
14
+ You should never use these certificates or keys for anything other than testing Manticore's SSL behavior.
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manticore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: java
6
6
  authors:
7
7
  - Chris Heald
@@ -30,7 +30,7 @@ cert_chain:
30
30
  E7PWS50D9moUJ6xWcemf0qKYC87qBFh0ng73awjG9uf+13lMslqJRMtek8C92cvh
31
31
  +R9zgQlbeNjy9O1i
32
32
  -----END CERTIFICATE-----
33
- date: 2014-08-08 00:00:00.000000000 Z
33
+ date: 2014-12-11 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: addressable
@@ -114,6 +114,13 @@ files:
114
114
  - spec/manticore/response_spec.rb
115
115
  - spec/manticore/stubbed_response_spec.rb
116
116
  - spec/spec_helper.rb
117
+ - spec/ssl/ca_cert.pem
118
+ - spec/ssl/ca_key.pem
119
+ - spec/ssl/client.p12
120
+ - spec/ssl/localhost.key
121
+ - spec/ssl/localhost.pem
122
+ - spec/ssl/readme.md
123
+ - spec/ssl/test_truststore
117
124
  homepage: https://github.com/cheald/manticore
118
125
  licenses:
119
126
  - MIT
@@ -134,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
134
141
  version: '0'
135
142
  requirements: []
136
143
  rubyforge_project:
137
- rubygems_version: 2.2.2
144
+ rubygems_version: 2.1.9
138
145
  signing_key:
139
146
  specification_version: 4
140
147
  summary: Manticore is an HTTP client built on the Apache HttpCore components
@@ -146,3 +153,10 @@ test_files:
146
153
  - spec/manticore/response_spec.rb
147
154
  - spec/manticore/stubbed_response_spec.rb
148
155
  - spec/spec_helper.rb
156
+ - spec/ssl/ca_cert.pem
157
+ - spec/ssl/ca_key.pem
158
+ - spec/ssl/client.p12
159
+ - spec/ssl/localhost.key
160
+ - spec/ssl/localhost.pem
161
+ - spec/ssl/readme.md
162
+ - spec/ssl/test_truststore
metadata.gz.sig CHANGED
Binary file