Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/nahi/httpclient into 177_…
Browse files Browse the repository at this point in the history
…add_socks_proxy_support
  • Loading branch information
mumumu committed Feb 4, 2019
2 parents e8486e1 + 4d60d8b commit 56679f2
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 105 deletions.
14 changes: 4 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
sudo: false

rvm:
- 2.0.0
- 2.1.8
- 2.2.4
- 2.3.0
- 2.4.0
- 2.3.8
- 2.4.4
- 2.5.3
- 2.6.1
- ruby-head
- jruby-19mode
- jruby-head

script: "bundle exec rake --trace"

notifications:
recipients:
- [email protected]

matrix:
allow_failures:
- rvm: jruby-head
4 changes: 4 additions & 0 deletions lib/httpclient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,10 @@ def patch(uri, *args, &block)
request(:patch, uri, new_args, &block)
end

# :call-seq:
# post(uri, {query: query, body: body, header: header, follow_redirect: follow_redirect}) -> HTTP::Message
# post(uri, body, header, follow_redirect) -> HTTP::Message
#
# Sends POST request to the specified URL. See request for arguments.
# You should not depend on :follow_redirect => true for POST method. It
# sends the same POST method to the new location which is prohibited in HTTP spec.
Expand Down
22 changes: 14 additions & 8 deletions lib/httpclient/jruby_ssl_socket.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ class JavaSocketWrap

BUF_SIZE = 1024 * 16

def self.normalize_timeout(timeout)
[Java::JavaLang::Integer::MAX_VALUE, timeout].min
end

def self.connect(socket, site, opts = {})
socket_addr = InetSocketAddress.new(site.host, site.port)
if opts[:connect_timeout]
socket.connect(socket_addr, opts[:connect_timeout])
socket.connect(socket_addr, normalize_timeout(opts[:connect_timeout]))
else
socket.connect(socket_addr)
end
socket.setSoTimeout(opts[:so_timeout]) if opts[:so_timeout]
socket.setSoTimeout(normalize_timeout(opts[:so_timeout])) if opts[:so_timeout]
socket.setKeepAlive(true) if opts[:tcp_keepalive]
socket
end
Expand Down Expand Up @@ -491,6 +495,8 @@ def initialize(socket, dest, config, opts = {})
ssl_connect(dest.host)
rescue java.security.GeneralSecurityException => e
raise OpenSSL::SSL::SSLError.new(e.getMessage)
rescue java.net.SocketTimeoutException => e
raise HTTPClient::ConnectTimeoutError.new(e.getMessage)
rescue java.io.IOException => e
raise OpenSSL::SSL::SSLError.new("#{e.class}: #{e.getMessage}")
end
Expand Down Expand Up @@ -546,13 +552,13 @@ def create_ssl_context(config)
def create_ssl_socket(socket, dest, config, opts)
ctx = create_ssl_context(config)
factory = ctx.getSocketFactory
if socket
ssl_socket = factory.createSocket(socket, dest.host, dest.port, true)
else
ssl_socket = factory.createSocket
JavaSocketWrap.connect(ssl_socket, dest, opts)
unless socket
# Create a plain socket first to set connection timeouts on,
# then wrap it in a SSL socket so that SNI gets setup on it.
socket = javax.net.SocketFactory.getDefault.createSocket
JavaSocketWrap.connect(socket, dest, opts)
end
ssl_socket
factory.createSocket(socket, dest.host, dest.port, true)
end

def peer_cert
Expand Down
7 changes: 3 additions & 4 deletions lib/jsonclient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def request(method, uri, *args, &block)

def argument_to_hash_for_json(args)
hash = argument_to_hash(args, :body, :header, :follow_redirect)
if hash[:body].is_a?(Hash)
if hash[:body].is_a?(Hash) || hash[:body].is_a?(Array)
hash[:header] = json_header(hash[:header])
hash[:body] = JSON.generate(hash[:body])
end
Expand All @@ -47,11 +47,10 @@ def argument_to_hash_for_json(args)
def json_header(header)
header ||= {}
if header.is_a?(Hash)
header['Content-Type'] = @content_type_json_request
header.merge('Content-Type' => @content_type_json_request)
else
header << ['Content-Type', @content_type_json_request]
header + [['Content-Type', @content_type_json_request]]
end
header
end

def wrap_json_response(original)
Expand Down
18 changes: 18 additions & 0 deletions test/test_jsonclient.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ def test_post
assert_equal(1, JSON.parse(res.previous.content)['a'])
end

def test_post_with_array
res = @client.post(serverurl + 'json', [{'a' => 1, 'b' => {'c' => 2}}])
assert_equal(2, res.content[0]['b']['c'])
assert_equal('application/json; charset=utf-8', res.content_type)
end

def test_post_with_header
res = @client.post(serverurl + 'json', :header => {'X-foo' => 'bar'}, :body => {'a' => 1, 'b' => {'c' => 2}})
assert_equal(2, res.content['b']['c'])
Expand Down Expand Up @@ -54,6 +60,18 @@ def test_get_not_affected
assert_equal('', res.content_type)
end

def test_hash_header_not_modified
header = {'X-foo' => 'bar'}
res = @client.post(serverurl, :header => header, :body => {'a' => 1, 'b' => {'c' => 2}})
assert_equal({'X-foo' => 'bar'}, header)
end

def test_array_header_not_modified
header = [['X-foo', 'bar']]
res = @client.post(serverurl, :header => header, :body => {'a' => 1, 'b' => {'c' => 2}})
assert_equal([['X-foo', 'bar']], header)
end

class JSONServlet < WEBrick::HTTPServlet::AbstractServlet
def get_instance(*arg)
self
Expand Down
93 changes: 10 additions & 83 deletions test/test_ssl.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require File.expand_path('helper', File.dirname(__FILE__))
require 'webrick/https'
require 'time'


class TestSSL < Test::Unit::TestCase
Expand Down Expand Up @@ -81,45 +82,14 @@ def test_debug_dev
end

def test_verification_without_httpclient
ca_cert = ::OpenSSL::X509::Certificate.new(%w[-----BEGIN\ CERTIFICATE-----
MIIC3jCCAcYCCQCUWi3t8e122TANBgkqhkiG9w0BAQsFADAxMQ0wCwYDVQQKDARS
dWJ5MRMwEQYDVQQLDApodHRwY2xpZW50MQswCQYDVQQDDAJDQTAeFw0xODAyMjcx
MTM0NDRaFw0yODAyMjUxMTM0NDRaMDExDTALBgNVBAoMBFJ1YnkxEzARBgNVBAsM
Cmh0dHBjbGllbnQxCzAJBgNVBAMMAkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAs6FPPj8PVl1uxsMZas4VC/ibRvtyXQkfrEa7TO032Kh+ETsOQNS8
QJedhw/BMHuoVbU0/b6PZ//LJTUDN/C77/QWHKzcMoxkNye5PC2cJlSQMosaKjYG
1ERYmJ+FBiMMSpcLOCS5cYoP2fJHGtHqZPkxIPYy+IKQ7WuP3tUXkVC+ftpD6H4V
6MUnfLwagpaAAbRoFUJQoZISmH2+F5GOKX9KKiMBI94yqRRN4K/B9iqXgld45Hmg
67vX0ckRbqBhrz1CwPtaETLFB4hZT2ouBkMQYtrvpNXv80p7vcz+BwORo8b2Ns9B
4FqtpjMaS9Mf95z4Mn+NG7lanYtsHO2svwIDAQABMA0GCSqGSIb3DQEBCwUAA4IB
AQBu614zHB5SS+ORYrRwl7tICKUipWHdCJfYsJOQy/FKwe7vedwd/Uclfe06GU+m
bNv0y22/oF7vrM3EfnxFe2DNIKXTndszrQSLpT6OPBe4mAOSJxnIMy6B6/PyhK6I
D7TWFSVlYX9a4OfolsoE0gQtxhyLud4rvJgXyAq9kRZ1FcNfI75cImk67rCa8jRY
TJOTidKq1Kcn6RY7d8cf581HP7y/eK887K6lBvGiQE1aFDSLe2ZLY+rxS9GSMYfK
81XhUX2QKytGYch2y95ThMwOljVTg6fKDrtKGwj9mSsnlfTFX3gikvLLtB/o7JPR
2pWBic8PX7gnANQqH/4ahv1M
-----END\ CERTIFICATE-----].join("\n"))
cert = ::OpenSSL::X509::Certificate.new(%w[-----BEGIN\ CERTIFICATE-----
MIIC5zCCAc8CCQCz/lMJNLxQDjANBgkqhkiG9w0BAQsFADAxMQ0wCwYDVQQKDARS
dWJ5MRMwEQYDVQQLDApodHRwY2xpZW50MQswCQYDVQQDDAJDQTAeFw0xODAyMjcx
MTM1MTNaFw0yNzExMjcxMTM1MTNaMDoxDTALBgNVBAoMBFJ1YnkxEzARBgNVBAsM
Cmh0dHBjbGllbnQxFDASBgNVBAMMC0NlcnRpZmljYXRlMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEAo/zP4oPyqerNyJYNTKzAGGQR8uKmP9wLnLm/yTf/
jwzVLj3rvunw54aw89V3R4LLwBBMgFlE9OrUa+2zCvZJ8ykSoltU+w9E2EdXnXAR
C/GW678MA06NPBuMNQyf+7Lv7dipdv+0hUNXFarwGiJkCms0zcmTonkOC8Bh7stZ
EykkvQs5zmYVd+G26D5un8Wzjl6OckbBDcKTS9u9H1YveRcnN7odsh+qI4PjDmKG
PXR8Gz/loNYN/I55Hqe7vkQJZ7r1PjSBp/fIcb4pNEkKS9DAcNWkoHF2j5nBNdOq
mH3WR36vKlw5S4HLzDXQDeueFbtk3QGrWY2MWrpJNapeAQIDAQABMA0GCSqGSIb3
DQEBCwUAA4IBAQB2CiGKAvHjr4kjOavWqGfPv115N4fhmBcPH4YAeJB9mHTzpoPV
BCm0ouRG5Oqj/DJhm+mckFKSorZFSgVb/G92w0uXRvBMPJb4wyIbp5ld6K3138cn
DtmeON3gbHwh3or741LdD6GIaulA9CL/qI3bbiyrJrHAZuHbpA6UqHfTKTBVi0uq
kv8qmA8FrzI2itDqdp0dq3QMNGnG40OM8NSDX+8A9wMahPh+Oe3TePSvDTahXIU1
o+dzaUEIVhUWEikQBnfeEnxzN8B/qtt3wEpliAip9Z3LuN0pVFb81Mx1wEZls2Bd
Kj83iBw7flO651USNPnkOkU3DegNtcpTaT5M
-----END\ CERTIFICATE-----].join("\n"))
raw_cert = "-----BEGIN CERTIFICATE-----\nMIIDKDCCAhCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES\nMBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X\nDTA0MDEzMTAzMTQ1OFoXDTM1MDEyMzAzMTQ1OFowZTELMAkGA1UEBgwCSlAxEjAQ\nBgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMRAwDgYDVQQDDAdleGFtcGxl\nMSIwIAYJKoZIhvcNAQkBDBNleGFtcGxlQGV4YW1wbGUub3JnMIGfMA0GCSqGSIb3\nDQEBAQUAA4GNADCBiQKBgQDRWssrK8Gyr+500hpLjCGR3+AHL8/hEJM5zKi/MgLW\njTkvsgOwbYwXOiNtAbR9y4/ucDq7EY+cMUMHES4uFaPTcOaAV0aZRmk8AgslN1tQ\ngNS6ew7/Luq3DcVeWkX8PYgR9VG0mD1MPfJ6+IFA5d3vKpdBkBgN4l46jjO0/2Xf\newIDAQABo4GPMIGMMAwGA1UdEwEB/wQCMAAwMQYJYIZIAYb4QgENBCQWIlJ1Ynkv\nT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFOFvay0H7lr2\nxUx6waYEV2bVDYQhMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEFBQcDAgYI\nKwYBBQUHAwQwDQYJKoZIhvcNAQEFBQADggEBABd2dYWqbDIWf5sWFvslezxJv8gI\nw64KCJBuyJAiDuf+oazr3016kMzAlt97KecLZDusGNagPrq02UX7YMoQFsWJBans\ncDtHrkM0al5r6/WGexNMgtYbNTYzt/IwodISGBgZ6dsOuhznwms+IBsTNDAvWeLP\nlt2tOqD8kEmjwMgn0GDRuKjs4EoboA3kMULb1p9akDV9ZESU3eOtpS5/G5J5msLI\n9WXbYBjcjvkLuJH9VsJhb+R58Vl0ViemvAHhPilSl1SPWVunGhv6FcIkdBEi1k9F\ne8BNMmsEjFiANiIRvpdLRbiGBt0KrKTndVfsmoKCvY48oCOvnzxtahFxfs8=\n-----END CERTIFICATE-----"
raw_ca_cert = "-----BEGIN CERTIFICATE-----\nMIID0DCCArigAwIBAgIBADANBgkqhkiG9w0BAQUFADA8MQswCQYDVQQGDAJKUDES\nMBAGA1UECgwJSklOLkdSLkpQMQwwCgYDVQQLDANSUlIxCzAJBgNVBAMMAkNBMB4X\nDTA0MDEzMDAwNDIzMloXDTM2MDEyMjAwNDIzMlowPDELMAkGA1UEBgwCSlAxEjAQ\nBgNVBAoMCUpJTi5HUi5KUDEMMAoGA1UECwwDUlJSMQswCQYDVQQDDAJDQTCCASIw\nDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANbv0x42BTKFEQOE+KJ2XmiSdZpR\nwjzQLAkPLRnLB98tlzs4xo+y4RyY/rd5TT9UzBJTIhP8CJi5GbS1oXEerQXB3P0d\nL5oSSMwGGyuIzgZe5+vZ1kgzQxMEKMMKlzA73rbMd4Jx3u5+jdbP0EDrPYfXSvLY\nbS04n2aX7zrN3x5KdDrNBfwBio2/qeaaj4+9OxnwRvYP3WOvqdW0h329eMfHw0pi\nJI0drIVdsEqClUV4pebT/F+CPUPkEh/weySgo9wANockkYu5ujw2GbLFcO5LXxxm\ndEfcVr3r6t6zOA4bJwL0W/e6LBcrwiG/qPDFErhwtgTLYf6Er67SzLyA66UCAwEA\nAaOB3DCB2TAPBgNVHRMBAf8EBTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09w\nZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBRJ7Xd380KzBV7f\nUSKIQ+O/vKbhDzAOBgNVHQ8BAf8EBAMCAQYwZAYDVR0jBF0wW4AUSe13d/NCswVe\n31EiiEPjv7ym4Q+hQKQ+MDwxCzAJBgNVBAYMAkpQMRIwEAYDVQQKDAlKSU4uR1Iu\nSlAxDDAKBgNVBAsMA1JSUjELMAkGA1UEAwwCQ0GCAQAwDQYJKoZIhvcNAQEFBQAD\nggEBAIu/mfiez5XN5tn2jScgShPgHEFJBR0BTJBZF6xCk0jyqNx/g9HMj2ELCuK+\nr/Y7KFW5c5M3AQ+xWW0ZSc4kvzyTcV7yTVIwj2jZ9ddYMN3nupZFgBK1GB4Y05GY\nMJJFRkSu6d/Ph5ypzBVw2YMT/nsOo5VwMUGLgS7YVjU+u/HNWz80J3oO17mNZllj\nPvORJcnjwlroDnS58KoJ7GDgejv3ESWADvX1OHLE4cRkiQGeLoEU4pxdCxXRqX0U\nPbwIkZN9mXVcrmPHq8MWi4eC/V7hnbZETMHuWhUoiNdOEfsAXr3iP4KjyyRdwc7a\nd/xgcK06UVQRL/HbEYGiQL056mc=\n-----END CERTIFICATE-----"
ca_cert = ::OpenSSL::X509::Certificate.new(raw_ca_cert)
cert = ::OpenSSL::X509::Certificate.new(raw_cert)
store = ::OpenSSL::X509::Store.new
store.add_cert(ca_cert)
assert(store.verify(cert))
store.time = Time.new(2017, 01, 01)
assert(store.verify(cert), "Verify failed: #{store.error_string}, #{store.error}")
end

def test_verification
Expand Down Expand Up @@ -277,39 +247,10 @@ def test_set_default_paths
end
end

def test_load_cacerts
omit_if(RUBY_ENGINE == 'jruby', 'SSL_CERT_FILE environment does not work on JRuby')

# disables loading default openssl paths
stub_x509_const(:DEFAULT_CERT_FILE, '/invalid') do
assert_raise(OpenSSL::SSL::SSLError) do
@client.get(@url)
end

setup_client

escape_env do
ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.pem')
@client.get(@url)
end
end
end

def test_default_paths
assert_raise(OpenSSL::SSL::SSLError) do
@client.get(@url)
end
escape_env do
ENV['SSL_CERT_FILE'] = File.join(DIR, 'ca-chain.pem')
setup_client
@client.get(@url)
end
end

def test_no_sslv3
teardown_server
setup_server_with_ssl_version(:SSLv3)
assert_raise() do
assert_raise(OpenSSL::SSL::SSLError) do
@client.ssl_config.verify_mode = nil
@client.get("https://localhost:#{serverport}/hello")
end
Expand All @@ -325,7 +266,7 @@ def test_allow_tlsv1
end

def test_use_higher_TLS
# TODO: it does not pass with Java 7 or old openssl
omit('TODO: it does not pass with Java 7 or old openssl ')
teardown_server
setup_server_with_ssl_version('TLSv1_2')
assert_nothing_raised do
Expand Down Expand Up @@ -490,20 +431,6 @@ def test_timeout

private

def stub_x509_const(name, value)
OpenSSL::X509.module_eval do
begin
original = remove_const(name)
const_set(name, value)

yield
ensure
remove_const(name)
const_set(name, original)
end
end
end

def cert(filename)
OpenSSL::X509::Certificate.new(File.read(File.join(DIR, filename)))
end
Expand Down Expand Up @@ -549,7 +476,7 @@ def setup_server_with_ssl_version(ssl_version)
ssl_version = ssl_version.tr('_', '.')
end
logger = Logger.new(STDERR)
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
@server = WEBrick::HTTPServer.new(
:BindAddress => "localhost",
:Logger => logger,
Expand Down

0 comments on commit 56679f2

Please sign in to comment.