httpclient 2.6.0.1 → 2.7.0
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 +4 -4
 - data/README.md +1 -1
 - data/bin/httpclient +5 -1
 - data/lib/http-access2.rb +1 -1
 - data/lib/httpclient.rb +37 -5
 - data/lib/httpclient/auth.rb +3 -3
 - data/lib/httpclient/cacert.pem +3952 -0
 - data/lib/httpclient/{cacert.p7s → cacert1024.pem} +0 -0
 - data/lib/httpclient/connection.rb +1 -1
 - data/lib/httpclient/cookie.rb +12 -4
 - data/lib/httpclient/http.rb +1 -1
 - data/lib/httpclient/jruby_ssl_socket.rb +526 -0
 - data/lib/httpclient/session.rb +161 -244
 - data/lib/httpclient/ssl_config.rb +54 -17
 - data/lib/httpclient/ssl_socket.rb +149 -0
 - data/lib/httpclient/timeout.rb +1 -1
 - data/lib/httpclient/util.rb +23 -1
 - data/lib/httpclient/version.rb +1 -1
 - data/lib/oauthclient.rb +1 -1
 - data/test/{ca-chain.cert → ca-chain.pem} +0 -0
 - data/test/helper.rb +7 -5
 - data/test/test_auth.rb +27 -8
 - data/test/test_cookie.rb +2 -2
 - data/test/test_httpclient.rb +57 -21
 - data/test/test_ssl.rb +70 -21
 - data/test/test_webagent-cookie.rb +2 -2
 - metadata +13 -10
 
| 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # HTTPClient - HTTP client library.
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2000- 
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2000-2015  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>.
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
         
     | 
| 
       5 
5 
     | 
    
         
             
            # redistribute it and/or modify it under the same terms of Ruby's license;
         
     | 
| 
         @@ -20,20 +20,19 @@ class HTTPClient 
     | 
|
| 
       20 
20 
     | 
    
         
             
              #
         
     | 
| 
       21 
21 
     | 
    
         
             
              # == Trust Anchor Control
         
     | 
| 
       22 
22 
     | 
    
         
             
              #
         
     | 
| 
       23 
     | 
    
         
            -
              # SSLConfig loads 'httpclient/cacert. 
     | 
| 
      
 23 
     | 
    
         
            +
              # SSLConfig loads 'httpclient/cacert.pem' as a trust anchor
         
     | 
| 
       24 
24 
     | 
    
         
             
              # (trusted certificate(s)) with add_trust_ca in initialization time.
         
     | 
| 
       25 
25 
     | 
    
         
             
              # This means that HTTPClient instance trusts some CA certificates by default,
         
     | 
| 
       26 
     | 
    
         
            -
              # like Web browsers.  'httpclient/cacert. 
     | 
| 
       27 
     | 
    
         
            -
              # included in released package.
         
     | 
| 
       28 
     | 
    
         
            -
              #
         
     | 
| 
       29 
     | 
    
         
            -
              # 'cacert.p7s' is automatically generated from JDK 1.6.  Regardless its
         
     | 
| 
       30 
     | 
    
         
            -
              # filename extension (p7s), HTTPClient doesn't verify the signature in it.
         
     | 
| 
      
 26 
     | 
    
         
            +
              # like Web browsers.  'httpclient/cacert.pem' is downloaded from curl web
         
     | 
| 
      
 27 
     | 
    
         
            +
              # site by the author and included in released package.
         
     | 
| 
       31 
28 
     | 
    
         
             
              #
         
     | 
| 
       32 
29 
     | 
    
         
             
              # You may want to change trust anchor by yourself.  Call clear_cert_store
         
     | 
| 
       33 
30 
     | 
    
         
             
              # then add_trust_ca for that purpose.
         
     | 
| 
       34 
31 
     | 
    
         
             
              class SSLConfig
         
     | 
| 
       35 
32 
     | 
    
         
             
                include OpenSSL if SSLEnabled
         
     | 
| 
       36 
33 
     | 
    
         | 
| 
      
 34 
     | 
    
         
            +
                CIPHERS_DEFAULT = "ALL:!aNULL:!eNULL:!SSLv2" # OpenSSL >1.0.0 default
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
       37 
36 
     | 
    
         
             
                # Which TLS protocol version (also called method) will be used. Defaults
         
     | 
| 
       38 
37 
     | 
    
         
             
                # to :auto which means that OpenSSL decides (In my tests this resulted 
         
     | 
| 
       39 
38 
     | 
    
         
             
                # with always the highest available protocol being used).
         
     | 
| 
         @@ -42,18 +41,20 @@ class HTTPClient 
     | 
|
| 
       42 
41 
     | 
    
         
             
                # See {OpenSSL::SSL::SSLContext::METHODS} for a list of available versions
         
     | 
| 
       43 
42 
     | 
    
         
             
                # in your specific Ruby environment.
         
     | 
| 
       44 
43 
     | 
    
         
             
                attr_reader :ssl_version
         
     | 
| 
       45 
     | 
    
         
            -
                # OpenSSL::X509::Certificate:: certificate for SSL client  
     | 
| 
       46 
     | 
    
         
            -
                # nil by default. (no client  
     | 
| 
      
 44 
     | 
    
         
            +
                # OpenSSL::X509::Certificate:: certificate for SSL client authentication.
         
     | 
| 
      
 45 
     | 
    
         
            +
                # nil by default. (no client authentication)
         
     | 
| 
       47 
46 
     | 
    
         
             
                attr_reader :client_cert
         
     | 
| 
       48 
47 
     | 
    
         
             
                # OpenSSL::PKey::PKey:: private key for SSL client authentication.
         
     | 
| 
       49 
     | 
    
         
            -
                # nil by default. (no client  
     | 
| 
      
 48 
     | 
    
         
            +
                # nil by default. (no client authentication)
         
     | 
| 
       50 
49 
     | 
    
         
             
                attr_reader :client_key
         
     | 
| 
      
 50 
     | 
    
         
            +
                attr_reader :client_key_pass
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
       52 
52 
     | 
    
         
             
                # A number which represents OpenSSL's verify mode.  Default value is
         
     | 
| 
       53 
53 
     | 
    
         
             
                # OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT.
         
     | 
| 
       54 
54 
     | 
    
         
             
                attr_reader :verify_mode
         
     | 
| 
       55 
55 
     | 
    
         
             
                # A number of verify depth.  Certification path which length is longer than
         
     | 
| 
       56 
56 
     | 
    
         
             
                # this depth is not allowed.
         
     | 
| 
      
 57 
     | 
    
         
            +
                # CAUTION: this is OpenSSL specific option and ignored on JRuby.
         
     | 
| 
       57 
58 
     | 
    
         
             
                attr_reader :verify_depth
         
     | 
| 
       58 
59 
     | 
    
         
             
                # A callback handler for custom certificate verification.  nil by default.
         
     | 
| 
       59 
60 
     | 
    
         
             
                # If the handler is set, handler.call is invoked just after general
         
     | 
| 
         @@ -65,6 +66,8 @@ class HTTPClient 
     | 
|
| 
       65 
66 
     | 
    
         
             
                attr_reader :timeout
         
     | 
| 
       66 
67 
     | 
    
         
             
                # A number of OpenSSL's SSL options.  Default value is
         
     | 
| 
       67 
68 
     | 
    
         
             
                # OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2
         
     | 
| 
      
 69 
     | 
    
         
            +
                # CAUTION: this is OpenSSL specific option and ignored on JRuby.
         
     | 
| 
      
 70 
     | 
    
         
            +
                # Use ssl_version to specify the TLS version you want to use.
         
     | 
| 
       68 
71 
     | 
    
         
             
                attr_reader :options
         
     | 
| 
       69 
72 
     | 
    
         
             
                # A String of OpenSSL's cipher configuration.  Default value is
         
     | 
| 
       70 
73 
     | 
    
         
             
                # ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH
         
     | 
| 
         @@ -78,11 +81,17 @@ class HTTPClient 
     | 
|
| 
       78 
81 
     | 
    
         
             
                # For server side configuration.  Ignore this.
         
     | 
| 
       79 
82 
     | 
    
         
             
                attr_reader :client_ca # :nodoc:
         
     | 
| 
       80 
83 
     | 
    
         | 
| 
      
 84 
     | 
    
         
            +
                # These array keeps original files/dirs that was added to @cert_store
         
     | 
| 
      
 85 
     | 
    
         
            +
                attr_reader :cert_store_items
         
     | 
| 
      
 86 
     | 
    
         
            +
                attr_reader :cert_store_crl_items
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
       81 
88 
     | 
    
         
             
                # Creates a SSLConfig.
         
     | 
| 
       82 
89 
     | 
    
         
             
                def initialize(client)
         
     | 
| 
       83 
90 
     | 
    
         
             
                  return unless SSLEnabled
         
     | 
| 
       84 
91 
     | 
    
         
             
                  @client = client
         
     | 
| 
       85 
92 
     | 
    
         
             
                  @cert_store = X509::Store.new
         
     | 
| 
      
 93 
     | 
    
         
            +
                  @cert_store_items = [:default]
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @cert_store_crl_items = []
         
     | 
| 
       86 
95 
     | 
    
         
             
                  @client_cert = @client_key = @client_ca = nil
         
     | 
| 
       87 
96 
     | 
    
         
             
                  @verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
         
     | 
| 
       88 
97 
     | 
    
         
             
                  @verify_depth = nil
         
     | 
| 
         @@ -97,7 +106,7 @@ class HTTPClient 
     | 
|
| 
       97 
106 
     | 
    
         
             
                  @options |= OpenSSL::SSL::OP_NO_SSLv2 if defined?(OpenSSL::SSL::OP_NO_SSLv2)
         
     | 
| 
       98 
107 
     | 
    
         
             
                  @options |= OpenSSL::SSL::OP_NO_SSLv3 if defined?(OpenSSL::SSL::OP_NO_SSLv3)
         
     | 
| 
       99 
108 
     | 
    
         
             
                  # OpenSSL 0.9.8 default: "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
         
     | 
| 
       100 
     | 
    
         
            -
                  @ciphers =  
     | 
| 
      
 109 
     | 
    
         
            +
                  @ciphers = CIPHERS_DEFAULT
         
     | 
| 
       101 
110 
     | 
    
         
             
                  @cacerts_loaded = false
         
     | 
| 
       102 
111 
     | 
    
         
             
                end
         
     | 
| 
       103 
112 
     | 
    
         | 
| 
         @@ -135,8 +144,7 @@ class HTTPClient 
     | 
|
| 
       135 
144 
     | 
    
         
             
                #
         
     | 
| 
       136 
145 
     | 
    
         
             
                # Calling this method resets all existing sessions.
         
     | 
| 
       137 
146 
     | 
    
         
             
                def set_client_cert_file(cert_file, key_file, pass = nil)
         
     | 
| 
       138 
     | 
    
         
            -
                  @client_cert =  
     | 
| 
       139 
     | 
    
         
            -
                  @client_key = PKey::RSA.new(File.open(key_file) { |f| f.read }, pass)
         
     | 
| 
      
 147 
     | 
    
         
            +
                  @client_cert, @client_key, @client_key_pass = cert_file, key_file, pass
         
     | 
| 
       140 
148 
     | 
    
         
             
                  change_notify
         
     | 
| 
       141 
149 
     | 
    
         
             
                end
         
     | 
| 
       142 
150 
     | 
    
         | 
| 
         @@ -155,6 +163,7 @@ class HTTPClient 
     | 
|
| 
       155 
163 
     | 
    
         
             
                  @cacerts_loaded = true # avoid lazy override
         
     | 
| 
       156 
164 
     | 
    
         
             
                  @cert_store = X509::Store.new
         
     | 
| 
       157 
165 
     | 
    
         
             
                  @cert_store.set_default_paths
         
     | 
| 
      
 166 
     | 
    
         
            +
                  @cert_store_items = [ENV['SSL_CERT_FILE'] || :default]
         
     | 
| 
       158 
167 
     | 
    
         
             
                  change_notify
         
     | 
| 
       159 
168 
     | 
    
         
             
                end
         
     | 
| 
       160 
169 
     | 
    
         | 
| 
         @@ -165,6 +174,7 @@ class HTTPClient 
     | 
|
| 
       165 
174 
     | 
    
         
             
                def clear_cert_store
         
     | 
| 
       166 
175 
     | 
    
         
             
                  @cacerts_loaded = true # avoid lazy override
         
     | 
| 
       167 
176 
     | 
    
         
             
                  @cert_store = X509::Store.new
         
     | 
| 
      
 177 
     | 
    
         
            +
                  @cert_store_items.clear
         
     | 
| 
       168 
178 
     | 
    
         
             
                  change_notify
         
     | 
| 
       169 
179 
     | 
    
         
             
                end
         
     | 
| 
       170 
180 
     | 
    
         | 
| 
         @@ -175,6 +185,7 @@ class HTTPClient 
     | 
|
| 
       175 
185 
     | 
    
         
             
                def cert_store=(cert_store)
         
     | 
| 
       176 
186 
     | 
    
         
             
                  @cacerts_loaded = true # avoid lazy override
         
     | 
| 
       177 
187 
     | 
    
         
             
                  @cert_store = cert_store
         
     | 
| 
      
 188 
     | 
    
         
            +
                  @cert_store_items.clear
         
     | 
| 
       178 
189 
     | 
    
         
             
                  change_notify
         
     | 
| 
       179 
190 
     | 
    
         
             
                end
         
     | 
| 
       180 
191 
     | 
    
         | 
| 
         @@ -188,6 +199,7 @@ class HTTPClient 
     | 
|
| 
       188 
199 
     | 
    
         
             
                def add_trust_ca(trust_ca_file_or_hashed_dir)
         
     | 
| 
       189 
200 
     | 
    
         
             
                  @cacerts_loaded = true # avoid lazy override
         
     | 
| 
       190 
201 
     | 
    
         
             
                  add_trust_ca_to_store(@cert_store, trust_ca_file_or_hashed_dir)
         
     | 
| 
      
 202 
     | 
    
         
            +
                  @cert_store_items << trust_ca_file_or_hashed_dir
         
     | 
| 
       191 
203 
     | 
    
         
             
                  change_notify
         
     | 
| 
       192 
204 
     | 
    
         
             
                end
         
     | 
| 
       193 
205 
     | 
    
         
             
                alias set_trust_ca add_trust_ca
         
     | 
| 
         @@ -211,12 +223,20 @@ class HTTPClient 
     | 
|
| 
       211 
223 
     | 
    
         
             
                # crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
         
     | 
| 
       212 
224 
     | 
    
         
             
                #       OpenSSL::X509::CRL.
         
     | 
| 
       213 
225 
     | 
    
         
             
                #
         
     | 
| 
      
 226 
     | 
    
         
            +
                # On JRuby, instead of setting CRL by yourself you can set following
         
     | 
| 
      
 227 
     | 
    
         
            +
                # options to let HTTPClient to perform revocation check with CRL and OCSP:
         
     | 
| 
      
 228 
     | 
    
         
            +
                # -J-Dcom.sun.security.enableCRLDP=true -J-Dcom.sun.net.ssl.checkRevocation=true
         
     | 
| 
      
 229 
     | 
    
         
            +
                # ex. jruby -J-Dcom.sun.security.enableCRLDP=true -J-Dcom.sun.net.ssl.checkRevocation=true app.rb
         
     | 
| 
      
 230 
     | 
    
         
            +
                #
         
     | 
| 
      
 231 
     | 
    
         
            +
                # Revoked cert example: https://test-sspev.verisign.com:2443/test-SSPEV-revoked-verisign.html
         
     | 
| 
      
 232 
     | 
    
         
            +
                #
         
     | 
| 
       214 
233 
     | 
    
         
             
                # Calling this method resets all existing sessions.
         
     | 
| 
       215 
234 
     | 
    
         
             
                def add_crl(crl)
         
     | 
| 
       216 
235 
     | 
    
         
             
                  unless crl.is_a?(X509::CRL)
         
     | 
| 
       217 
236 
     | 
    
         
             
                    crl = X509::CRL.new(File.open(crl) { |f| f.read })
         
     | 
| 
       218 
237 
     | 
    
         
             
                  end
         
     | 
| 
       219 
238 
     | 
    
         
             
                  @cert_store.add_crl(crl)
         
     | 
| 
      
 239 
     | 
    
         
            +
                  @cert_store_crl_items << crl
         
     | 
| 
       220 
240 
     | 
    
         
             
                  @cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
         
     | 
| 
       221 
241 
     | 
    
         
             
                  change_notify
         
     | 
| 
       222 
242 
     | 
    
         
             
                end
         
     | 
| 
         @@ -278,7 +298,7 @@ class HTTPClient 
     | 
|
| 
       278 
298 
     | 
    
         
             
                  change_notify
         
     | 
| 
       279 
299 
     | 
    
         
             
                end
         
     | 
| 
       280 
300 
     | 
    
         | 
| 
       281 
     | 
    
         
            -
                # interfaces for  
     | 
| 
      
 301 
     | 
    
         
            +
                # interfaces for SSLSocket.
         
     | 
| 
       282 
302 
     | 
    
         
             
                def set_context(ctx) # :nodoc:
         
     | 
| 
       283 
303 
     | 
    
         
             
                  load_trust_ca unless @cacerts_loaded
         
     | 
| 
       284 
304 
     | 
    
         
             
                  @cacerts_loaded = true
         
     | 
| 
         @@ -288,8 +308,14 @@ class HTTPClient 
     | 
|
| 
       288 
308 
     | 
    
         
             
                  ctx.verify_depth = @verify_depth if @verify_depth
         
     | 
| 
       289 
309 
     | 
    
         
             
                  ctx.verify_callback = @verify_callback || method(:default_verify_callback)
         
     | 
| 
       290 
310 
     | 
    
         
             
                  # SSL config
         
     | 
| 
       291 
     | 
    
         
            -
                   
     | 
| 
       292 
     | 
    
         
            -
             
     | 
| 
      
 311 
     | 
    
         
            +
                  if @client_cert
         
     | 
| 
      
 312 
     | 
    
         
            +
                    ctx.cert = @client_cert.is_a?(X509::Certificate) ?  @client_cert :
         
     | 
| 
      
 313 
     | 
    
         
            +
                      X509::Certificate.new(File.open(@client_cert) { |f| f.read })
         
     | 
| 
      
 314 
     | 
    
         
            +
                  end
         
     | 
| 
      
 315 
     | 
    
         
            +
                  if @client_key
         
     | 
| 
      
 316 
     | 
    
         
            +
                    ctx.key = @client_key.is_a?(PKey::PKey) ? @client_key :
         
     | 
| 
      
 317 
     | 
    
         
            +
                      PKey::RSA.new(File.open(@client_key) { |f| f.read }, @client_key_pass)
         
     | 
| 
      
 318 
     | 
    
         
            +
                  end
         
     | 
| 
       293 
319 
     | 
    
         
             
                  ctx.client_ca = @client_ca
         
     | 
| 
       294 
320 
     | 
    
         
             
                  ctx.timeout = @timeout
         
     | 
| 
       295 
321 
     | 
    
         
             
                  ctx.options = @options
         
     | 
| 
         @@ -405,9 +431,20 @@ class HTTPClient 
     | 
|
| 
       405 
431 
     | 
    
         
             
                  nil
         
     | 
| 
       406 
432 
     | 
    
         
             
                end
         
     | 
| 
       407 
433 
     | 
    
         | 
| 
      
 434 
     | 
    
         
            +
                # Use 2014 bit certs trust anchor if possible.
         
     | 
| 
      
 435 
     | 
    
         
            +
                # CVE-2015-1793 requires: OpenSSL >= 1.0.2d or OpenSSL >= 1.0.1p
         
     | 
| 
      
 436 
     | 
    
         
            +
                # OpenSSL before 1.0.1 does not have CVE-2015-1793 problem
         
     | 
| 
       408 
437 
     | 
    
         
             
                def load_cacerts(cert_store)
         
     | 
| 
       409 
     | 
    
         
            -
                   
     | 
| 
      
 438 
     | 
    
         
            +
                  ver = OpenSSL::OPENSSL_VERSION
         
     | 
| 
      
 439 
     | 
    
         
            +
                  if (ver.start_with?('OpenSSL 1.0.1') && ver >= 'OpenSSL 1.0.1p') ||
         
     | 
| 
      
 440 
     | 
    
         
            +
                      (ver.start_with?('OpenSSL ') && ver >= 'OpenSSL 1.0.2d')
         
     | 
| 
      
 441 
     | 
    
         
            +
                    filename = 'cacert.pem'
         
     | 
| 
      
 442 
     | 
    
         
            +
                  else
         
     | 
| 
      
 443 
     | 
    
         
            +
                    filename = 'cacert1024.pem'
         
     | 
| 
      
 444 
     | 
    
         
            +
                  end
         
     | 
| 
      
 445 
     | 
    
         
            +
                  file = File.join(File.dirname(__FILE__), filename)
         
     | 
| 
       410 
446 
     | 
    
         
             
                  add_trust_ca_to_store(cert_store, file)
         
     | 
| 
      
 447 
     | 
    
         
            +
                  @cert_store_items << file
         
     | 
| 
       411 
448 
     | 
    
         
             
                end
         
     | 
| 
       412 
449 
     | 
    
         
             
              end
         
     | 
| 
       413 
450 
     | 
    
         | 
| 
         @@ -0,0 +1,149 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # HTTPClient - HTTP client library.
         
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2000-2015  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>.
         
     | 
| 
      
 3 
     | 
    
         
            +
            #
         
     | 
| 
      
 4 
     | 
    
         
            +
            # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
         
     | 
| 
      
 5 
     | 
    
         
            +
            # redistribute it and/or modify it under the same terms of Ruby's license;
         
     | 
| 
      
 6 
     | 
    
         
            +
            # either the dual license version in 2003, or any later version.
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            require 'httpclient/ssl_config'
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            class HTTPClient
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              # Wraps up OpenSSL::SSL::SSLSocket and offers debugging features.
         
     | 
| 
      
 15 
     | 
    
         
            +
              class SSLSocket
         
     | 
| 
      
 16 
     | 
    
         
            +
                def self.create_socket(session)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  site = session.proxy || session.dest
         
     | 
| 
      
 18 
     | 
    
         
            +
                  socket = session.create_socket(site.host, site.port)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 20 
     | 
    
         
            +
                    if session.proxy
         
     | 
| 
      
 21 
     | 
    
         
            +
                      session.connect_ssl_proxy(socket, Util.urify(session.dest.to_s))
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                    ssl_socket = new(socket, session.ssl_config, session.debug_dev)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    ssl_socket.ssl_connect(session.dest.host)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    ssl_socket
         
     | 
| 
      
 26 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 27 
     | 
    
         
            +
                    socket.close
         
     | 
| 
      
 28 
     | 
    
         
            +
                    raise
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                def initialize(socket, context, debug_dev = nil)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  unless SSLEnabled
         
     | 
| 
      
 34 
     | 
    
         
            +
                    raise ConfigurationError.new('Ruby/OpenSSL module is required')
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @socket = socket
         
     | 
| 
      
 37 
     | 
    
         
            +
                  @context = context
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @ssl_socket = create_openssl_socket(@socket)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @debug_dev = debug_dev
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def ssl_connect(hostname = nil)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  if hostname && @ssl_socket.respond_to?(:hostname=)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    @ssl_socket.hostname = hostname
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @ssl_socket.connect
         
     | 
| 
      
 47 
     | 
    
         
            +
                  if $DEBUG
         
     | 
| 
      
 48 
     | 
    
         
            +
                    if @ssl_socket.respond_to?(:ssl_version)
         
     | 
| 
      
 49 
     | 
    
         
            +
                      warn("Protocol version: #{@ssl_socket.ssl_version}")
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                    warn("Cipher: #{@ssl_socket.cipher.inspect}")
         
     | 
| 
      
 52 
     | 
    
         
            +
                    warn("State: #{@ssl_socket.state}")
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                  post_connection_check(hostname)
         
     | 
| 
      
 55 
     | 
    
         
            +
                end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
                def peer_cert
         
     | 
| 
      
 58 
     | 
    
         
            +
                  @ssl_socket.peer_cert
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                def close
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @ssl_socket.close
         
     | 
| 
      
 63 
     | 
    
         
            +
                  @socket.close
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                def closed?
         
     | 
| 
      
 67 
     | 
    
         
            +
                  @socket.closed?
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                def eof?
         
     | 
| 
      
 71 
     | 
    
         
            +
                  @ssl_socket.eof?
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                def gets(rs)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  str = @ssl_socket.gets(rs)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  debug(str)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  str
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                def read(size, buf = nil)
         
     | 
| 
      
 81 
     | 
    
         
            +
                  str = @ssl_socket.read(size, buf)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  debug(str)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  str
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def readpartial(size, buf = nil)
         
     | 
| 
      
 87 
     | 
    
         
            +
                  str = @ssl_socket.readpartial(size, buf)
         
     | 
| 
      
 88 
     | 
    
         
            +
                  debug(str)
         
     | 
| 
      
 89 
     | 
    
         
            +
                  str
         
     | 
| 
      
 90 
     | 
    
         
            +
                end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def <<(str)
         
     | 
| 
      
 93 
     | 
    
         
            +
                  rv = @ssl_socket.write(str)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  debug(str)
         
     | 
| 
      
 95 
     | 
    
         
            +
                  rv
         
     | 
| 
      
 96 
     | 
    
         
            +
                end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                def flush
         
     | 
| 
      
 99 
     | 
    
         
            +
                  @ssl_socket.flush
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                def sync
         
     | 
| 
      
 103 
     | 
    
         
            +
                  @ssl_socket.sync
         
     | 
| 
      
 104 
     | 
    
         
            +
                end
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
                def sync=(sync)
         
     | 
| 
      
 107 
     | 
    
         
            +
                  @ssl_socket.sync = sync
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              private
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                def post_connection_check(hostname)
         
     | 
| 
      
 113 
     | 
    
         
            +
                  verify_mode = @context.verify_mode || OpenSSL::SSL::VERIFY_NONE
         
     | 
| 
      
 114 
     | 
    
         
            +
                  if verify_mode == OpenSSL::SSL::VERIFY_NONE
         
     | 
| 
      
 115 
     | 
    
         
            +
                    return
         
     | 
| 
      
 116 
     | 
    
         
            +
                  elsif @ssl_socket.peer_cert.nil? and
         
     | 
| 
      
 117 
     | 
    
         
            +
                    check_mask(verify_mode, OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT)
         
     | 
| 
      
 118 
     | 
    
         
            +
                    raise OpenSSL::SSL::SSLError.new('no peer cert')
         
     | 
| 
      
 119 
     | 
    
         
            +
                  end
         
     | 
| 
      
 120 
     | 
    
         
            +
                  if @ssl_socket.respond_to?(:post_connection_check) and RUBY_VERSION > "1.8.4"
         
     | 
| 
      
 121 
     | 
    
         
            +
                    @ssl_socket.post_connection_check(hostname)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  else
         
     | 
| 
      
 123 
     | 
    
         
            +
                    @context.post_connection_check(@ssl_socket.peer_cert, hostname)
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
      
 127 
     | 
    
         
            +
                def check_mask(value, mask)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  value & mask == mask
         
     | 
| 
      
 129 
     | 
    
         
            +
                end
         
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
                def create_openssl_socket(socket)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  ssl_socket = nil
         
     | 
| 
      
 133 
     | 
    
         
            +
                  if OpenSSL::SSL.const_defined?("SSLContext")
         
     | 
| 
      
 134 
     | 
    
         
            +
                    ctx = OpenSSL::SSL::SSLContext.new
         
     | 
| 
      
 135 
     | 
    
         
            +
                    @context.set_context(ctx)
         
     | 
| 
      
 136 
     | 
    
         
            +
                    ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
         
     | 
| 
      
 137 
     | 
    
         
            +
                  else
         
     | 
| 
      
 138 
     | 
    
         
            +
                    ssl_socket = OpenSSL::SSL::SSLSocket.new(socket)
         
     | 
| 
      
 139 
     | 
    
         
            +
                    @context.set_context(ssl_socket)
         
     | 
| 
      
 140 
     | 
    
         
            +
                  end
         
     | 
| 
      
 141 
     | 
    
         
            +
                  ssl_socket
         
     | 
| 
      
 142 
     | 
    
         
            +
                end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                def debug(str)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  @debug_dev << str if @debug_dev && str
         
     | 
| 
      
 146 
     | 
    
         
            +
                end
         
     | 
| 
      
 147 
     | 
    
         
            +
              end
         
     | 
| 
      
 148 
     | 
    
         
            +
             
     | 
| 
      
 149 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/httpclient/timeout.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # HTTPClient - HTTP client library.
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2000- 
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2000-2015  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>.
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
         
     | 
| 
       5 
5 
     | 
    
         
             
            # redistribute it and/or modify it under the same terms of Ruby's license;
         
     | 
    
        data/lib/httpclient/util.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # HTTPClient - HTTP client library.
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2000- 
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2000-2015  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>.
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
         
     | 
| 
       5 
5 
     | 
    
         
             
            # redistribute it and/or modify it under the same terms of Ruby's license;
         
     | 
| 
         @@ -24,6 +24,28 @@ if RUBY_VERSION < "1.9.3" 
     | 
|
| 
       24 
24 
     | 
    
         
             
              end
         
     | 
| 
       25 
25 
     | 
    
         
             
            end
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
      
 27 
     | 
    
         
            +
            # With recent JRuby 1.7 + jruby-openssl, X509CRL#extentions_to_text causes
         
     | 
| 
      
 28 
     | 
    
         
            +
            # StringIndexOOBException when we try to dump SSL Server Certificate.
         
     | 
| 
      
 29 
     | 
    
         
            +
            # when one of extensions has "" as value.
         
     | 
| 
      
 30 
     | 
    
         
            +
            if defined?(JRUBY_VERSION)
         
     | 
| 
      
 31 
     | 
    
         
            +
              require 'openssl'
         
     | 
| 
      
 32 
     | 
    
         
            +
              require 'java'
         
     | 
| 
      
 33 
     | 
    
         
            +
              module OpenSSL
         
     | 
| 
      
 34 
     | 
    
         
            +
                module X509
         
     | 
| 
      
 35 
     | 
    
         
            +
                  class Certificate
         
     | 
| 
      
 36 
     | 
    
         
            +
                    java_import 'java.security.cert.Certificate'
         
     | 
| 
      
 37 
     | 
    
         
            +
                    java_import 'java.security.cert.CertificateFactory'
         
     | 
| 
      
 38 
     | 
    
         
            +
                    java_import 'java.io.ByteArrayInputStream'
         
     | 
| 
      
 39 
     | 
    
         
            +
                    def to_text
         
     | 
| 
      
 40 
     | 
    
         
            +
                      cf = CertificateFactory.getInstance('X.509')
         
     | 
| 
      
 41 
     | 
    
         
            +
                      cf.generateCertificate(ByteArrayInputStream.new(self.to_der.to_java_bytes)).toString
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  end
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
       27 
49 
     | 
    
         
             
            class HTTPClient
         
     | 
| 
       28 
50 
     | 
    
         | 
| 
       29 
51 
     | 
    
         | 
    
        data/lib/httpclient/version.rb
    CHANGED
    
    
    
        data/lib/oauthclient.rb
    CHANGED
    
    | 
         @@ -1,5 +1,5 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # HTTPClient - HTTP client library.
         
     | 
| 
       2 
     | 
    
         
            -
            # Copyright (C) 2000- 
     | 
| 
      
 2 
     | 
    
         
            +
            # Copyright (C) 2000-2015  NAKAMURA, Hiroshi  <nahi@ruby-lang.org>.
         
     | 
| 
       3 
3 
     | 
    
         
             
            #
         
     | 
| 
       4 
4 
     | 
    
         
             
            # This program is copyrighted free software by NAKAMURA, Hiroshi.  You can
         
     | 
| 
       5 
5 
     | 
    
         
             
            # redistribute it and/or modify it under the same terms of Ruby's license;
         
     | 
| 
         
            File without changes
         
     | 
    
        data/test/helper.rb
    CHANGED
    
    | 
         @@ -59,11 +59,13 @@ module Helper 
     | 
|
| 
       59 
59 
     | 
    
         
             
                @client = HTTPClient.new
         
     | 
| 
       60 
60 
     | 
    
         
             
              end
         
     | 
| 
       61 
61 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
               
     | 
| 
       63 
     | 
    
         
            -
                 
     | 
| 
       64 
     | 
    
         
            -
                 
     | 
| 
       65 
     | 
    
         
            -
                 
     | 
| 
       66 
     | 
    
         
            -
               
     | 
| 
      
 62 
     | 
    
         
            +
              def escape_noproxy
         
     | 
| 
      
 63 
     | 
    
         
            +
                backup = HTTPClient::NO_PROXY_HOSTS.dup
         
     | 
| 
      
 64 
     | 
    
         
            +
                HTTPClient::NO_PROXY_HOSTS.clear
         
     | 
| 
      
 65 
     | 
    
         
            +
                yield
         
     | 
| 
      
 66 
     | 
    
         
            +
              ensure
         
     | 
| 
      
 67 
     | 
    
         
            +
                HTTPClient::NO_PROXY_HOSTS.replace(backup)
         
     | 
| 
      
 68 
     | 
    
         
            +
              end
         
     | 
| 
       67 
69 
     | 
    
         | 
| 
       68 
70 
     | 
    
         
             
              def setup_proxyserver
         
     | 
| 
       69 
71 
     | 
    
         
             
                @proxyserver = WEBrick::HTTPProxyServer.new(
         
     | 
    
        data/test/test_auth.rb
    CHANGED
    
    | 
         @@ -124,6 +124,7 @@ class TestAuth < Test::Unit::TestCase 
     | 
|
| 
       124 
124 
     | 
    
         
             
                  end
         
     | 
| 
       125 
125 
     | 
    
         
             
                  # Make it work if @value == nil
         
     | 
| 
       126 
126 
     | 
    
         
             
                  class SecurityBuffer < FieldSet
         
     | 
| 
      
 127 
     | 
    
         
            +
                    remove_method(:data_size) if method_defined?(:data_size)
         
     | 
| 
       127 
128 
     | 
    
         
             
                    def data_size
         
     | 
| 
       128 
129 
     | 
    
         
             
                      @active && @value ? @value.size : 0
         
     | 
| 
       129 
130 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -230,7 +231,7 @@ class TestAuth < Test::Unit::TestCase 
     | 
|
| 
       230 
231 
     | 
    
         
             
                  c.www_auth.basic_auth.instance_eval { @scheme = "BASIC" }
         
     | 
| 
       231 
232 
     | 
    
         
             
                  c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
         
     | 
| 
       232 
233 
     | 
    
         | 
| 
       233 
     | 
    
         
            -
                   
     | 
| 
      
 234 
     | 
    
         
            +
                  100.times.map { |idx|
         
     | 
| 
       234 
235 
     | 
    
         
             
                    Thread.new(idx) { |idx2|
         
     | 
| 
       235 
236 
     | 
    
         
             
                      Thread.abort_on_exception = true
         
     | 
| 
       236 
237 
     | 
    
         
             
                      Thread.pass
         
     | 
| 
         @@ -251,7 +252,7 @@ class TestAuth < Test::Unit::TestCase 
     | 
|
| 
       251 
252 
     | 
    
         
             
                c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
         
     | 
| 
       252 
253 
     | 
    
         
             
                c.debug_dev = str = ''
         
     | 
| 
       253 
254 
     | 
    
         
             
                c.get_content("http://localhost:#{serverport}/basic_auth/sub/dir/")
         
     | 
| 
       254 
     | 
    
         
            -
                assert_match 
     | 
| 
      
 255 
     | 
    
         
            +
                assert_match(/Authorization: Basic YWRtaW46YWRtaW4=/, str)
         
     | 
| 
       255 
256 
     | 
    
         
             
              end
         
     | 
| 
       256 
257 
     | 
    
         | 
| 
       257 
258 
     | 
    
         
             
              def test_digest_auth
         
     | 
| 
         @@ -267,7 +268,7 @@ class TestAuth < Test::Unit::TestCase 
     | 
|
| 
       267 
268 
     | 
    
         
             
                c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
         
     | 
| 
       268 
269 
     | 
    
         
             
                c.debug_dev = str = ''
         
     | 
| 
       269 
270 
     | 
    
         
             
                c.get_content("http://localhost:#{serverport}/digest_auth/sub/dir/")
         
     | 
| 
       270 
     | 
    
         
            -
                assert_match 
     | 
| 
      
 271 
     | 
    
         
            +
                assert_match(/Authorization: Digest/, str)
         
     | 
| 
       271 
272 
     | 
    
         
             
              end
         
     | 
| 
       272 
273 
     | 
    
         | 
| 
       273 
274 
     | 
    
         
             
              def test_digest_auth_with_block
         
     | 
| 
         @@ -332,6 +333,16 @@ class TestAuth < Test::Unit::TestCase 
     | 
|
| 
       332 
333 
     | 
    
         
             
                assert_match(/Proxy-Authorization: Basic YWRtaW46YWRtaW4=/, str)
         
     | 
| 
       333 
334 
     | 
    
         
             
              end
         
     | 
| 
       334 
335 
     | 
    
         | 
| 
      
 336 
     | 
    
         
            +
              def test_proxy_auth_force
         
     | 
| 
      
 337 
     | 
    
         
            +
                c = HTTPClient.new
         
     | 
| 
      
 338 
     | 
    
         
            +
                c.set_proxy_auth('admin', 'admin')
         
     | 
| 
      
 339 
     | 
    
         
            +
                c.force_basic_auth = true
         
     | 
| 
      
 340 
     | 
    
         
            +
                c.test_loopback_http_response << "HTTP/1.0 200 OK\nContent-Length: 2\n\nOK"
         
     | 
| 
      
 341 
     | 
    
         
            +
                c.debug_dev = str = ''
         
     | 
| 
      
 342 
     | 
    
         
            +
                c.get_content('http://example.com/')
         
     | 
| 
      
 343 
     | 
    
         
            +
                assert_match(/Proxy-Authorization: Basic YWRtaW46YWRtaW4=/, str)
         
     | 
| 
      
 344 
     | 
    
         
            +
              end
         
     | 
| 
      
 345 
     | 
    
         
            +
             
     | 
| 
       335 
346 
     | 
    
         
             
              def test_proxy_auth_reuses_credentials
         
     | 
| 
       336 
347 
     | 
    
         
             
                c = HTTPClient.new
         
     | 
| 
       337 
348 
     | 
    
         
             
                c.set_proxy_auth('admin', 'admin')
         
     | 
| 
         @@ -442,11 +453,19 @@ class TestAuth < Test::Unit::TestCase 
     | 
|
| 
       442 
453 
     | 
    
         
             
              end
         
     | 
| 
       443 
454 
     | 
    
         | 
| 
       444 
455 
     | 
    
         
             
              def test_basic_auth_post_with_multipart
         
     | 
| 
       445 
     | 
    
         
            -
                 
     | 
| 
       446 
     | 
    
         
            -
                 
     | 
| 
       447 
     | 
    
         
            -
             
     | 
| 
       448 
     | 
    
         
            -
                   
     | 
| 
       449 
     | 
    
         
            -
                   
     | 
| 
      
 456 
     | 
    
         
            +
                retry_times = 0
         
     | 
| 
      
 457 
     | 
    
         
            +
                begin
         
     | 
| 
      
 458 
     | 
    
         
            +
                  c = HTTPClient.new
         
     | 
| 
      
 459 
     | 
    
         
            +
                  c.set_auth("http://localhost:#{serverport}/", 'admin', 'admin')
         
     | 
| 
      
 460 
     | 
    
         
            +
                  File.open(__FILE__) do |f|
         
     | 
| 
      
 461 
     | 
    
         
            +
                    # read 'f' twice for authorization negotiation
         
     | 
| 
      
 462 
     | 
    
         
            +
                    assert_equal('basic_auth OK', c.post("http://localhost:#{serverport}/basic_auth", :file => f).content)
         
     | 
| 
      
 463 
     | 
    
         
            +
                  end
         
     | 
| 
      
 464 
     | 
    
         
            +
                rescue Errno::ECONNRESET, HTTPClient::KeepAliveDisconnected
         
     | 
| 
      
 465 
     | 
    
         
            +
                  # TODO: WEBrick server returns ECONNRESET/EPIPE before sending Unauthorized response to client?
         
     | 
| 
      
 466 
     | 
    
         
            +
                  raise if retry_times > 5
         
     | 
| 
      
 467 
     | 
    
         
            +
                  retry_times += 1
         
     | 
| 
      
 468 
     | 
    
         
            +
                  retry 
         
     | 
| 
       450 
469 
     | 
    
         
             
                end
         
     | 
| 
       451 
470 
     | 
    
         
             
              end
         
     | 
| 
       452 
471 
     | 
    
         |