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
|
|