http 0.8.0.pre4 → 0.8.0.pre5

Sign up to get free protection for your applications and to get access to all the features.
@@ -68,12 +68,6 @@ RSpec.describe HTTP::Response::Status do
68
68
 
69
69
  # "Bad Request"
70
70
  its([400]) { is_expected.to be :bad_request }
71
-
72
- # "Request-URI Too Long"
73
- its([414]) { is_expected.to be :request_uri_too_long }
74
-
75
- # "I'm a Teapot"
76
- its([418]) { is_expected.to be :im_a_teapot }
77
71
  end
78
72
 
79
73
  described_class::SYMBOLS.each do |code, symbol|
@@ -106,12 +106,12 @@ RSpec.describe HTTP do
106
106
 
107
107
  context "with redirects" do
108
108
  it "is easy for 301" do
109
- response = HTTP.with_follow(true).get("#{dummy.endpoint}/redirect-301")
109
+ response = HTTP.follow.get("#{dummy.endpoint}/redirect-301")
110
110
  expect(response.to_s).to match(/<!doctype html>/)
111
111
  end
112
112
 
113
113
  it "is easy for 302" do
114
- response = HTTP.with_follow(true).get("#{dummy.endpoint}/redirect-302")
114
+ response = HTTP.follow.get("#{dummy.endpoint}/redirect-302")
115
115
  expect(response.to_s).to match(/<!doctype html>/)
116
116
  end
117
117
  end
data/spec/spec_helper.rb CHANGED
@@ -17,13 +17,6 @@ require "http"
17
17
  require "rspec/its"
18
18
  require "support/capture_warning"
19
19
 
20
- # Allow testing against a SSL server
21
- def certs_dir
22
- Pathname.new File.expand_path("../../tmp/certs", __FILE__)
23
- end
24
-
25
- require "support/create_certs"
26
-
27
20
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
28
21
  RSpec.configure do |config|
29
22
  config.expect_with :rspec do |expectations|
@@ -5,6 +5,7 @@ require "support/black_hole"
5
5
  require "support/dummy_server/servlet"
6
6
  require "support/servers/config"
7
7
  require "support/servers/runner"
8
+ require "support/ssl_helper"
8
9
 
9
10
  class DummyServer < WEBrick::HTTPServer
10
11
  include ServerConfig
@@ -16,37 +17,25 @@ class DummyServer < WEBrick::HTTPServer
16
17
  :Logger => BlackHole
17
18
  }.freeze
18
19
 
19
- def initialize(options = {})
20
- if options[:ssl]
21
- override_config = {
22
- :SSLEnable => true,
23
- :SSLStartImmediately => true
24
- }
25
- else
26
- override_config = {}
27
- end
28
-
29
- super CONFIG.merge(override_config)
20
+ SSL_CONFIG = CONFIG.merge(
21
+ :SSLEnable => true,
22
+ :SSLStartImmediately => true
23
+ ).freeze
30
24
 
25
+ def initialize(options = {})
26
+ super(options[:ssl] ? SSL_CONFIG : CONFIG)
31
27
  mount("/", Servlet)
32
28
  end
33
29
 
34
30
  def endpoint
35
- "#{ssl? ? 'https' : 'http'}://#{addr}:#{port}"
31
+ "#{scheme}://#{addr}:#{port}"
32
+ end
33
+
34
+ def scheme
35
+ config[:SSLEnable] ? "https" : "http"
36
36
  end
37
37
 
38
38
  def ssl_context
39
- @ssl_context ||= begin
40
- context = OpenSSL::SSL::SSLContext.new
41
- context.verify_mode = OpenSSL::SSL::VERIFY_PEER
42
- context.key = OpenSSL::PKey::RSA.new(
43
- File.read(File.join(certs_dir, "server.key"))
44
- )
45
- context.cert = OpenSSL::X509::Certificate.new(
46
- File.read(File.join(certs_dir, "server.crt"))
47
- )
48
- context.ca_file = File.join(certs_dir, "ca.crt")
49
- context
50
- end
39
+ @ssl_context ||= SSLHelper.server_context
51
40
  end
52
41
  end
@@ -1,4 +1,4 @@
1
- RSpec.shared_context "HTTP handling" do |ssl = false|
1
+ RSpec.shared_context "HTTP handling" do
2
2
  describe "timeouts" do
3
3
  let(:conn_timeout) { 1 }
4
4
  let(:read_timeout) { 1 }
@@ -73,56 +73,18 @@ RSpec.shared_context "HTTP handling" do |ssl = false|
73
73
 
74
74
  let(:response) { client.get(server.endpoint).body.to_s }
75
75
 
76
- context "with localhost" do
77
- let(:endpoint) { server.endpoint.sub("127.0.0.1", "localhost") }
78
-
79
- it "errors if DNS takes too long" do
80
- # Block the localhost lookup
81
- expect(timeout_class::HostResolver)
82
- .to receive(:getaddress).with("localhost").and_return(nil)
83
-
84
- # Request
85
- expect(Resolv::DNS).to receive(:open).with(:timeout => 1) do |_|
86
- sleep 1.25
87
- "127.0.0.1"
88
- end
89
-
90
- expect { client.get(server.endpoint.sub("127.0.0.1", "localhost")) }
91
- .to raise_error(HTTP::TimeoutError, /Timed out/)
92
- end
93
- end
94
-
95
76
  it "errors if connecting takes too long" do
96
- socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
97
-
98
- fake_socket = double(:to_io => socket)
99
- expect(fake_socket).to receive(:connect_nonblock) do |*args|
77
+ expect(TCPSocket).to receive(:open) do
100
78
  sleep 1.25
101
- socket.connect_nonblock(*args)
102
79
  end
103
80
 
104
- allow_any_instance_of(timeout_class).to receive(:socket).and_return(fake_socket)
105
-
106
- expect { response }.to raise_error(HTTP::TimeoutError, /Timed out/)
81
+ expect { response }.to raise_error(HTTP::TimeoutError, /execution/)
107
82
  end
108
83
 
109
84
  it "errors if reading takes too long" do
110
85
  expect { client.get("#{server.endpoint}/sleep").body.to_s }
111
86
  .to raise_error(HTTP::TimeoutError, /Timed out/)
112
87
  end
113
-
114
- unless ssl
115
- it "errors if writing takes too long" do
116
- socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
117
- allow_any_instance_of(timeout_class).to receive(:socket).and_return(socket)
118
-
119
- expect(socket).to receive(:<<) do |*|
120
- sleep 1.25
121
- end
122
-
123
- expect { response }.to raise_error(HTTP::TimeoutError, /Timed out/)
124
- end
125
- end
126
88
  end
127
89
  end
128
90
 
@@ -148,6 +110,18 @@ RSpec.shared_context "HTTP handling" do |ssl = false|
148
110
  expect(sockets_used.uniq.length).to eq(1)
149
111
  end
150
112
 
113
+ context "on a mixed state" do
114
+ it "re-opens the connection" do
115
+ first_socket_id = client.get("#{server.endpoint}/socket/1").body.to_s
116
+
117
+ client.instance_variable_set(:@state, :dirty)
118
+
119
+ second_socket_id = client.get("#{server.endpoint}/socket/2").body.to_s
120
+
121
+ expect(first_socket_id).to_not eq(second_socket_id)
122
+ end
123
+ end
124
+
151
125
  context "when trying to read a stale body" do
152
126
  it "errors" do
153
127
  client.get("#{server.endpoint}/not-found")
@@ -169,8 +143,8 @@ RSpec.shared_context "HTTP handling" do |ssl = false|
169
143
 
170
144
  context "with a socket issue" do
171
145
  it "transparently reopens" do
172
- first_socket = client.get("#{server.endpoint}/socket").body.to_s
173
- expect(first_socket).to_not eq("")
146
+ first_socket_id = client.get("#{server.endpoint}/socket").body.to_s
147
+ expect(first_socket_id).to_not eq("")
174
148
  # Kill off the sockets we used
175
149
  # rubocop:disable Style/RescueModifier
176
150
  DummyServer::Servlet.sockets.each do |socket|
@@ -183,8 +157,8 @@ RSpec.shared_context "HTTP handling" do |ssl = false|
183
157
  expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error(IOError)
184
158
 
185
159
  # Should succeed since we create a new socket
186
- second_socket = client.get("#{server.endpoint}/socket").body.to_s
187
- expect(second_socket).to_not eq(first_socket)
160
+ second_socket_id = client.get("#{server.endpoint}/socket").body.to_s
161
+ expect(second_socket_id).to_not eq(first_socket_id)
188
162
  end
189
163
  end
190
164
 
@@ -1,8 +1,4 @@
1
1
  module ServerConfig
2
- def ssl?
3
- !!config[:SSLEnable]
4
- end
5
-
6
2
  def addr
7
3
  config[:BindAddress]
8
4
  end
@@ -0,0 +1,102 @@
1
+ require "pathname"
2
+
3
+ require "certificate_authority"
4
+
5
+ module SSLHelper
6
+ CERTS_PATH = Pathname.new File.expand_path("../../../tmp/certs", __FILE__)
7
+
8
+ class RootCertificate < ::CertificateAuthority::Certificate
9
+ EXTENSIONS = {"keyUsage" => {"usage" => %w(critical keyCertSign)}}
10
+
11
+ def initialize
12
+ super()
13
+
14
+ subject.common_name = "honestachmed.com"
15
+ serial_number.number = 1
16
+ key_material.generate_key
17
+
18
+ self.signing_entity = true
19
+
20
+ sign!("extensions" => EXTENSIONS)
21
+ end
22
+
23
+ def file
24
+ return @file if defined? @file
25
+
26
+ CERTS_PATH.mkpath
27
+
28
+ cert_file = CERTS_PATH.join("ca.crt")
29
+ cert_file.open("w") { |io| io << to_pem }
30
+
31
+ @file = cert_file.to_s
32
+ end
33
+ end
34
+
35
+ class ChildCertificate < ::CertificateAuthority::Certificate
36
+ def initialize(parent)
37
+ super()
38
+
39
+ subject.common_name = "127.0.0.1"
40
+ serial_number.number = 1
41
+
42
+ key_material.generate_key
43
+
44
+ self.parent = parent
45
+
46
+ sign!
47
+ end
48
+
49
+ def cert
50
+ OpenSSL::X509::Certificate.new to_pem
51
+ end
52
+
53
+ def key
54
+ OpenSSL::PKey::RSA.new key_material.private_key.to_pem
55
+ end
56
+ end
57
+
58
+ class << self
59
+ def server_context
60
+ context = OpenSSL::SSL::SSLContext.new
61
+
62
+ context.verify_mode = OpenSSL::SSL::VERIFY_PEER
63
+ context.key = server_cert.key
64
+ context.cert = server_cert.cert
65
+ context.ca_file = ca.file
66
+
67
+ context
68
+ end
69
+
70
+ def client_context
71
+ context = OpenSSL::SSL::SSLContext.new
72
+
73
+ context.options = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options]
74
+ context.verify_mode = OpenSSL::SSL::VERIFY_PEER
75
+ context.key = client_cert.key
76
+ context.cert = client_cert.cert
77
+ context.ca_file = ca.file
78
+
79
+ context
80
+ end
81
+
82
+ def client_params
83
+ {
84
+ :key => client_cert.key,
85
+ :cert => client_cert.cert,
86
+ :ca_file => ca.file
87
+ }
88
+ end
89
+
90
+ %w(server client).each do |side|
91
+ class_eval <<-RUBY, __FILE__, __LINE__
92
+ def #{side}_cert
93
+ @#{side}_cert ||= ChildCertificate.new ca
94
+ end
95
+ RUBY
96
+ end
97
+
98
+ def ca
99
+ @ca ||= RootCertificate.new
100
+ end
101
+ end
102
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0.pre4
4
+ version: 0.8.0.pre5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-03-29 00:00:00.000000000 Z
13
+ date: 2015-03-31 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: http_parser.rb
@@ -138,13 +138,13 @@ files:
138
138
  - spec/support/black_hole.rb
139
139
  - spec/support/capture_warning.rb
140
140
  - spec/support/connection_reuse_shared.rb
141
- - spec/support/create_certs.rb
142
141
  - spec/support/dummy_server.rb
143
142
  - spec/support/dummy_server/servlet.rb
144
143
  - spec/support/http_handling_shared.rb
145
144
  - spec/support/proxy_server.rb
146
145
  - spec/support/servers/config.rb
147
146
  - spec/support/servers/runner.rb
147
+ - spec/support/ssl_helper.rb
148
148
  homepage: https://github.com/httprb/http.rb
149
149
  licenses:
150
150
  - MIT
@@ -199,11 +199,11 @@ test_files:
199
199
  - spec/support/black_hole.rb
200
200
  - spec/support/capture_warning.rb
201
201
  - spec/support/connection_reuse_shared.rb
202
- - spec/support/create_certs.rb
203
202
  - spec/support/dummy_server.rb
204
203
  - spec/support/dummy_server/servlet.rb
205
204
  - spec/support/http_handling_shared.rb
206
205
  - spec/support/proxy_server.rb
207
206
  - spec/support/servers/config.rb
208
207
  - spec/support/servers/runner.rb
208
+ - spec/support/ssl_helper.rb
209
209
  has_rdoc:
@@ -1,57 +0,0 @@
1
- require "fileutils"
2
- require "certificate_authority"
3
-
4
- FileUtils.mkdir_p(certs_dir)
5
-
6
- #
7
- # Certificate Authority
8
- #
9
-
10
- ca = CertificateAuthority::Certificate.new
11
-
12
- ca.subject.common_name = "honestachmed.com"
13
- ca.serial_number.number = 1
14
- ca.key_material.generate_key
15
- ca.signing_entity = true
16
-
17
- ca.sign! "extensions" => {"keyUsage" => {"usage" => %w(critical keyCertSign)}}
18
-
19
- ca_cert_path = File.join(certs_dir, "ca.crt")
20
- ca_key_path = File.join(certs_dir, "ca.key")
21
-
22
- File.write ca_cert_path, ca.to_pem
23
- File.write ca_key_path, ca.key_material.private_key.to_pem
24
-
25
- #
26
- # Server Certificate
27
- #
28
-
29
- server_cert = CertificateAuthority::Certificate.new
30
- server_cert.subject.common_name = "127.0.0.1"
31
- server_cert.serial_number.number = 1
32
- server_cert.key_material.generate_key
33
- server_cert.parent = ca
34
- server_cert.sign!
35
-
36
- server_cert_path = File.join(certs_dir, "server.crt")
37
- server_key_path = File.join(certs_dir, "server.key")
38
-
39
- File.write server_cert_path, server_cert.to_pem
40
- File.write server_key_path, server_cert.key_material.private_key.to_pem
41
-
42
- #
43
- # Client Certificate
44
- #
45
-
46
- client_cert = CertificateAuthority::Certificate.new
47
- client_cert.subject.common_name = "127.0.0.1"
48
- client_cert.serial_number.number = 1
49
- client_cert.key_material.generate_key
50
- client_cert.parent = ca
51
- client_cert.sign!
52
-
53
- client_cert_path = File.join(certs_dir, "client.crt")
54
- client_key_path = File.join(certs_dir, "client.key")
55
-
56
- File.write client_cert_path, client_cert.to_pem
57
- File.write client_key_path, client_cert.key_material.private_key.to_pem