diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3baeca08..e78683c8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,11 +4,17 @@ on: [push, pull_request] jobs: build: - name: build (${{ matrix.ruby }} / ${{ matrix.os }}) + name: ${{ matrix.os }} ${{ matrix.ruby }} strategy: + fail-fast: false matrix: - ruby: [ '3.0', 2.7, 2.6, head ] - os: [ ubuntu-latest, macos-latest ] + os: [ ubuntu-20.04, macos-10.15, windows-2019 ] + ruby: [ '3.0', 2.7, 2.6, 2.5, head ] + include: + - { os: windows-2019 , ruby: mingw } + - { os: windows-2019 , ruby: mswin } + exclude: + - { os: windows-2019 , ruby: head } runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 @@ -19,4 +25,4 @@ jobs: - name: Install dependencies run: bundle install - name: Run test - run: rake test + run: bundle exec rake test diff --git a/.gitignore b/.gitignore index 9106b2a3..4ea57987 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /pkg/ /spec/reports/ /tmp/ +Gemfile.lock diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 67321d2a..00000000 --- a/Gemfile.lock +++ /dev/null @@ -1,33 +0,0 @@ -PATH - remote: . - specs: - net-http (0.1.1) - net-protocol - uri - -GEM - remote: https://rubygems.org/ - specs: - io-wait (0.1.0) - net-protocol (0.1.0) - io-wait - timeout - power_assert (1.1.5) - rake (13.0.1) - test-unit (3.3.5) - power_assert - timeout (0.1.1) - uri (0.10.1) - webrick (1.7.0) - -PLATFORMS - ruby - -DEPENDENCIES - net-http! - rake - test-unit - webrick - -BUNDLED WITH - 2.1.4 diff --git a/Rakefile b/Rakefile index d81dd1f4..99661739 100644 --- a/Rakefile +++ b/Rakefile @@ -1,4 +1,4 @@ -require "bundler/gem_tasks" +require "bundler/gem_tasks" if defined?(Bundler) require "rake/testtask" Rake::TestTask.new(:test) do |t| diff --git a/net-http.gemspec b/net-http.gemspec index f5ef4045..ae78b43c 100644 --- a/net-http.gemspec +++ b/net-http.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |spec| spec.summary = %q{HTTP client api for Ruby.} spec.description = %q{HTTP client api for Ruby.} spec.homepage = "https://github.com/ruby/net-http" - spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0") + spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") spec.licenses = ["Ruby", "BSD-2-Clause"] spec.metadata["homepage_uri"] = spec.homepage diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb index aa826379..4dc9f1b0 100644 --- a/test/net/http/test_https.rb +++ b/test/net/http/test_https.rb @@ -14,6 +14,8 @@ def self.read_fixture(key) File.read(File.expand_path("../fixtures/#{key}", __dir__)) end + HOST = 'localhost' + HOST_IP = '127.0.0.1' CA_CERT = OpenSSL::X509::Certificate.new(read_fixture("cacert.pem")) SERVER_KEY = OpenSSL::PKey.read(read_fixture("server.key")) SERVER_CERT = OpenSSL::X509::Certificate.new(read_fixture("server.crt")) @@ -21,7 +23,7 @@ def self.read_fixture(key) TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) } CONFIG = { - 'host' => '127.0.0.1', + 'host' => HOST, 'proxy_host' => nil, 'proxy_port' => nil, 'ssl_enable' => true, @@ -31,7 +33,7 @@ def self.read_fixture(key) } def test_get - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE certs = [] @@ -43,15 +45,13 @@ def test_get assert_equal($test_net_http_data, res.body) } # TODO: OpenSSL 1.1.1h seems to yield only SERVER_CERT; need to check the incompatibility - certs.zip([CA_CERT, SERVER_CERT][-certs.size..]) do |actual, expected| + certs.zip([CA_CERT, SERVER_CERT][-certs.size..-1]) do |actual, expected| assert_equal(expected.to_der, actual.to_der) end - rescue SystemCallError - skip $! end def test_get_SNI - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.ipaddr = config('host') http.use_ssl = true http.cert_store = TEST_STORE @@ -64,16 +64,16 @@ def test_get_SNI assert_equal($test_net_http_data, res.body) } # TODO: OpenSSL 1.1.1h seems to yield only SERVER_CERT; need to check the incompatibility - certs.zip([CA_CERT, SERVER_CERT][-certs.size..]) do |actual, expected| + certs.zip([CA_CERT, SERVER_CERT][-certs.size..-1]) do |actual, expected| assert_equal(expected.to_der, actual.to_der) end end def test_get_SNI_proxy - TCPServer.open("127.0.0.1", 0) {|serv| + TCPServer.open(HOST_IP, 0) {|serv| _, port, _, _ = serv.addr client_thread = Thread.new { - proxy = Net::HTTP.Proxy("127.0.0.1", port, 'user', 'password') + proxy = Net::HTTP.Proxy(HOST_IP, port, 'user', 'password') http = proxy.new("foo.example.org", 8000) http.ipaddr = "192.0.2.1" http.use_ssl = true @@ -125,15 +125,13 @@ def test_get_SNI_failure end def test_post - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE data = config('ssl_private_key').to_der http.request_post("/", data, {'content-type' => 'application/x-www-form-urlencoded'}) {|res| assert_equal(data, res.body) } - rescue SystemCallError - skip $! end def test_session_reuse @@ -141,7 +139,7 @@ def test_session_reuse # See https://github.com/openssl/openssl/pull/5967 for details. skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/ - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE @@ -154,25 +152,21 @@ def test_session_reuse end http.start + assert_equal false, http.instance_variable_get(:@socket).io.session_reused? http.get("/") http.finish http.start - http.get("/") - - socket = http.instance_variable_get(:@socket).io - assert_equal true, socket.session_reused? - + assert_equal true, http.instance_variable_get(:@socket).io.session_reused? + assert_equal $test_net_http_data, http.get("/").body http.finish - rescue SystemCallError - skip $! end def test_session_reuse_but_expire # FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h. skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/ - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.cert_store = TEST_STORE @@ -188,8 +182,6 @@ def test_session_reuse_but_expire assert_equal false, socket.session_reused? http.finish - rescue SystemCallError - skip $! end if ENV["RUBY_OPENSSL_TEST_ALL"] @@ -204,14 +196,12 @@ def test_verify end def test_verify_none - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_NONE http.request_get("/") {|res| assert_equal($test_net_http_data, res.body) } - rescue SystemCallError - skip $! end def test_skip_hostname_verification @@ -240,14 +230,10 @@ def test_fail_if_verify_hostname_is_true end def test_certificate_verify_failure - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true ex = assert_raise(OpenSSL::SSL::SSLError){ - begin - http.request_get("/") {|res| } - rescue SystemCallError - skip $! - end + http.request_get("/") {|res| } } assert_match(/certificate verify failed/, ex.message) unless /mswin|mingw/ =~ RUBY_PLATFORM @@ -262,14 +248,14 @@ def test_certificate_verify_failure def test_identity_verify_failure # the certificate's subject has CN=localhost - http = Net::HTTP.new("127.0.0.1", config("port")) + http = Net::HTTP.new(HOST_IP, config("port")) http.use_ssl = true http.cert_store = TEST_STORE @log_tester = lambda {|_| } ex = assert_raise(OpenSSL::SSL::SSLError){ http.request_get("/") {|res| } } - re_msg = /certificate verify failed|hostname \"127.0.0.1\" does not match/ + re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/ assert_match(re_msg, ex.message) end @@ -277,10 +263,10 @@ def test_timeout_during_SSL_handshake bug4246 = "expected the SSL connection to have timed out but have not. [ruby-core:34203]" # listen for connections... but deliberately do not complete SSL handshake - TCPServer.open('localhost', 0) {|server| + TCPServer.open(HOST, 0) {|server| port = server.addr[1] - conn = Net::HTTP.new('localhost', port) + conn = Net::HTTP.new(HOST, port) conn.use_ssl = true conn.read_timeout = 0.01 conn.open_timeout = 0.01 @@ -295,7 +281,7 @@ def test_timeout_during_SSL_handshake end def test_min_version - http = Net::HTTP.new("localhost", config("port")) + http = Net::HTTP.new(HOST, config("port")) http.use_ssl = true http.min_version = :TLS1 http.cert_store = TEST_STORE @@ -305,7 +291,7 @@ def test_min_version end def test_max_version - http = Net::HTTP.new("127.0.0.1", config("port")) + http = Net::HTTP.new(HOST_IP, config("port")) http.use_ssl = true http.max_version = :SSL2 http.verify_callback = Proc.new do |preverify_ok, store_ctx|