manticore 0.3.1-java → 0.3.2-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
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