httpclient 2.8.0 → 2.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d31f6d6614892afef55ee460384719e2a3fd308
4
- data.tar.gz: deb8c8f5172a0d956daebda1853b585d7d2f5845
3
+ metadata.gz: c4ffce5e3ce378196b7441498f0a93969da6086f
4
+ data.tar.gz: 91ba9e1062f6515828ae1983ca28eb0a2d40a75d
5
5
  SHA512:
6
- metadata.gz: 5df03c1b552368850d643690166ef8dadedab621395ffae31c279cf863b4d4c8b7a1ac1504b9bf5feb6dde6452ce47ec725187dc15535c3c6576f4f606961664
7
- data.tar.gz: ef50511dd9b8d46ff3c6b5bad0e55a66b99501c62246b308c3f54eec3273253e006dce6ef13ab78b8533b2fb5eeda121c00f1943d562815f40c9c33e472b0f91
6
+ metadata.gz: 743acf9501f271b66d4b7dcc25812ea766f81d4e3eae6f5a4784ce157a3db7f81a386c6d8a7cced0b87cb464040752997047dad0d627cc94fb9451371f34a44b
7
+ data.tar.gz: 1e14c7fdd6ec23d895310ca70f3a96a6bd44910371f6221c33095fa4302344da15574a109e800493481e8477dbbb33ce4c4d2cb0661e271c0846d3b8674cf8ba
@@ -20,6 +20,7 @@ end
20
20
  url = ARGV.shift
21
21
  if method && url
22
22
  client = HTTPClient.new
23
+ client.strict_response_size_check = true
23
24
  if method == 'download'
24
25
  print client.get_content(url)
25
26
  else
@@ -37,6 +38,7 @@ require 'irb/completion'
37
38
  class Runner
38
39
  def initialize
39
40
  @httpclient = HTTPClient.new
41
+ @httpclient.strict_response_size_check = true
40
42
  end
41
43
 
42
44
  def method_missing(msg, *a, &b)
@@ -309,7 +309,6 @@ class HTTPClient
309
309
  if assignable
310
310
  aname = name + '='
311
311
  define_method(aname) { |rhs|
312
- reset_all
313
312
  @session_manager.__send__(aname, rhs)
314
313
  }
315
314
  end
@@ -365,6 +364,9 @@ class HTTPClient
365
364
  attr_proxy(:test_loopback_http_response)
366
365
  # Decompress a compressed (with gzip or deflate) content body transparently. false by default.
367
366
  attr_proxy(:transparent_gzip_decompression, true)
367
+ # Raise BadResponseError if response size does not match with Content-Length header in response. false by default.
368
+ # TODO: enable by default
369
+ attr_proxy(:strict_response_size_check, true)
368
370
  # Local socket address. Set HTTPClient#socket_local.host and HTTPClient#socket_local.port to specify local binding hostname and port of TCP socket.
369
371
  attr_proxy(:socket_local, true)
370
372
 
@@ -844,13 +846,7 @@ class HTTPClient
844
846
  end
845
847
  uri = to_resource_url(uri)
846
848
  if block
847
- if block.arity == 1
848
- filtered_block = proc { |res, str|
849
- block.call(str)
850
- }
851
- else
852
- filtered_block = block
853
- end
849
+ filtered_block = adapt_block(&block)
854
850
  end
855
851
  if follow_redirect
856
852
  follow_redirect(method, uri, query, body, header, &block)
@@ -1082,11 +1078,17 @@ private
1082
1078
  ENV[name.downcase] || ENV[name.upcase]
1083
1079
  end
1084
1080
 
1081
+ def adapt_block(&block)
1082
+ return block if block.arity == 2
1083
+ proc { |r, str| block.call(str) }
1084
+ end
1085
+
1085
1086
  def follow_redirect(method, uri, query, body, header, &block)
1086
1087
  uri = to_resource_url(uri)
1087
1088
  if block
1089
+ b = adapt_block(&block)
1088
1090
  filtered_block = proc { |r, str|
1089
- block.call(str) if r.ok?
1091
+ b.call(r, str) if r.ok?
1090
1092
  }
1091
1093
  end
1092
1094
  if HTTP::Message.file?(body)
@@ -1270,6 +1272,7 @@ private
1270
1272
  return
1271
1273
  end
1272
1274
  piper, pipew = IO.pipe
1275
+ pipew.binmode
1273
1276
  res = HTTP::Message.new_response(piper, req.header)
1274
1277
  @debug_dev << "= Request\n\n" if @debug_dev
1275
1278
  sess = @session_manager.query(req, proxy)
@@ -700,8 +700,9 @@ module HTTP
700
700
 
701
701
  def params_from_file(value)
702
702
  params = {}
703
+ original_filename = value.respond_to?(:original_filename) ? value.original_filename : nil
703
704
  path = value.respond_to?(:path) ? value.path : nil
704
- params['filename'] = File.basename(path || '')
705
+ params['filename'] = original_filename || File.basename(path || '')
705
706
  # Creation time is not available from File::Stat
706
707
  if value.respond_to?(:mtime)
707
708
  params['modification-date'] = value.mtime.rfc822
@@ -808,6 +809,8 @@ module HTTP
808
809
  case path
809
810
  when /\.txt$/i
810
811
  'text/plain'
812
+ when /\.xml$/i
813
+ 'text/xml'
811
814
  when /\.(htm|html)$/i
812
815
  'text/html'
813
816
  when /\.doc$/i
@@ -289,11 +289,11 @@ unless defined?(SSLSocket)
289
289
  @keystore.load(nil)
290
290
  end
291
291
 
292
- def add(cert_file, key_file, password)
293
- cert_str = cert_file.respond_to?(:to_pem) ? cert_file.to_pem : File.read(cert_file.to_s)
292
+ def add(cert_source, key_source, password)
293
+ cert_str = cert_source.respond_to?(:to_pem) ? cert_source.to_pem : File.read(cert_source.to_s)
294
294
  cert = PEMUtils.read_certificate(cert_str)
295
295
  @keystore.setCertificateEntry('client_cert', cert)
296
- key_str = key_file.respond_to?(:to_pem) ? key_file.to_pem : File.read(key_file.to_s)
296
+ key_str = key_source.respond_to?(:to_pem) ? key_source.to_pem : File.read(key_source.to_s)
297
297
  key_pair = PEMUtils.read_private_key(key_str, password)
298
298
  @keystore.setKeyEntry('client_key', key_pair.getPrivate, PASSWORD, [cert].to_java(Certificate))
299
299
  end
@@ -312,20 +312,21 @@ unless defined?(SSLSocket)
312
312
  @size = 0
313
313
  end
314
314
 
315
- def add(file_or_dir)
316
- return if file_or_dir == :default
317
- if File.directory?(file_or_dir)
318
- warn("#{file_or_dir}: directory not yet supported")
315
+ def add(cert_source)
316
+ return if cert_source == :default
317
+ if cert_source.respond_to?(:to_pem)
318
+ pem = cert_source.to_pem
319
+ elsif File.directory?(cert_source)
320
+ warn("#{cert_source}: directory not yet supported")
321
+ return
319
322
  else
320
323
  pem = nil
321
- File.read(file_or_dir).each_line do |line|
324
+ File.read(cert_source).each_line do |line|
322
325
  case line
323
326
  when /-----BEGIN CERTIFICATE-----/
324
327
  pem = ''
325
328
  when /-----END CERTIFICATE-----/
326
- cert = PEMUtils.read_certificate(pem)
327
- @size += 1
328
- @trust_store.setCertificateEntry("cert_#{@size}", cert)
329
+ break
329
330
  else
330
331
  if pem
331
332
  pem << line
@@ -333,6 +334,9 @@ unless defined?(SSLSocket)
333
334
  end
334
335
  end
335
336
  end
337
+ cert = PEMUtils.read_certificate(pem)
338
+ @size += 1
339
+ @trust_store.setCertificateEntry("cert_#{@size}", cert)
336
340
  end
337
341
 
338
342
  def trust_store
@@ -442,12 +446,12 @@ unless defined?(SSLSocket)
442
446
  new(socket, session.dest, session.ssl_config, session.debug_dev)
443
447
  end
444
448
 
445
- DEFAULT_SSL_PROTOCOL = 'TLS'
449
+ DEFAULT_SSL_PROTOCOL = (java.lang.System.getProperty('java.specification.version') == '1.7') ? 'TLSv1.2' : 'TLS'
446
450
  def initialize(socket, dest, config, debug_dev = nil)
447
451
  if config.ssl_version == :auto
448
452
  ssl_version = DEFAULT_SSL_PROTOCOL
449
453
  else
450
- ssl_version = config.ssl_version.to_s.gsub(/_/, '.')
454
+ ssl_version = config.ssl_version.to_s.tr('_', '.')
451
455
  end
452
456
  unless config.cert_store_crl_items.empty?
453
457
  raise NotImplementedError.new('Manual CRL configuration is not yet supported')
@@ -464,7 +468,7 @@ unless defined?(SSLSocket)
464
468
 
465
469
  trust_store = nil
466
470
  verify_callback = config.verify_callback || config.method(:default_verify_callback)
467
- if config.verify_mode == nil
471
+ if !config.verify?
468
472
  tmf = VerifyNoneTrustManagerFactory.new(verify_callback)
469
473
  else
470
474
  tmf = SystemTrustManagerFactory.new(verify_callback)
@@ -115,6 +115,9 @@ class HTTPClient
115
115
  attr_accessor :read_block_size
116
116
  attr_accessor :protocol_retry_count
117
117
 
118
+ # Raise BadResponseError if response size does not match with Content-Length header in response.
119
+ attr_accessor :strict_response_size_check
120
+
118
121
  # Local address to bind local side of the socket to
119
122
  attr_accessor :socket_local
120
123
 
@@ -148,6 +151,7 @@ class HTTPClient
148
151
  @test_loopback_http_response = []
149
152
 
150
153
  @transparent_gzip_decompression = false
154
+ @strict_response_size_check = false
151
155
  @socket_local = Site.new
152
156
 
153
157
  @sess_pool = {}
@@ -221,6 +225,7 @@ class HTTPClient
221
225
  sess.protocol_retry_count = @protocol_retry_count
222
226
  sess.ssl_config = @ssl_config
223
227
  sess.debug_dev = @debug_dev
228
+ sess.strict_response_size_check = @strict_response_size_check
224
229
  sess.socket_local = @socket_local
225
230
  sess.test_loopback_http_response = @test_loopback_http_response
226
231
  sess.transparent_gzip_decompression = @transparent_gzip_decompression
@@ -444,6 +449,7 @@ class HTTPClient
444
449
  attr_accessor :read_block_size
445
450
  attr_accessor :protocol_retry_count
446
451
 
452
+ attr_accessor :strict_response_size_check
447
453
  attr_accessor :socket_local
448
454
 
449
455
  attr_accessor :ssl_config
@@ -473,6 +479,7 @@ class HTTPClient
473
479
  @ssl_peer_cert = nil
474
480
 
475
481
  @test_loopback_http_response = nil
482
+ @strict_response_size_check = false
476
483
  @socket_local = Site::EMPTY
477
484
 
478
485
  @agent_name = agent_name
@@ -871,6 +878,9 @@ class HTTPClient
871
878
  rescue EOFError
872
879
  close
873
880
  buf = nil
881
+ if @strict_response_size_check
882
+ raise BadResponseError.new("EOF while reading rest #{@content_length} bytes")
883
+ end
874
884
  end
875
885
  end
876
886
  if buf && buf.bytesize > 0
@@ -887,18 +897,18 @@ class HTTPClient
887
897
  def read_body_chunked(&block)
888
898
  buf = empty_bin_str
889
899
  while true
890
- len = @socket.gets(RS)
891
- if len.nil? # EOF
892
- close
893
- return
894
- end
895
- @chunk_length = len.hex
896
- if @chunk_length == 0
897
- @content_length = 0
898
- @socket.gets(RS)
899
- return
900
- end
901
900
  ::Timeout.timeout(@receive_timeout, ReceiveTimeoutError) do
901
+ len = @socket.gets(RS)
902
+ if len.nil? # EOF
903
+ close
904
+ return
905
+ end
906
+ @chunk_length = len.hex
907
+ if @chunk_length == 0
908
+ @content_length = 0
909
+ @socket.gets(RS)
910
+ return
911
+ end
902
912
  @socket.read(@chunk_length, buf)
903
913
  @socket.read(2)
904
914
  end
@@ -920,6 +930,9 @@ class HTTPClient
920
930
  @socket.readpartial(@read_block_size, buf)
921
931
  rescue EOFError
922
932
  buf = nil
933
+ if @strict_response_size_check
934
+ raise BadResponseError.new("EOF while reading chunked response")
935
+ end
923
936
  end
924
937
  end
925
938
  if buf && buf.bytesize > 0
@@ -36,7 +36,30 @@ class HTTPClient
36
36
  # then add_trust_ca for that purpose.
37
37
  class SSLConfig
38
38
  include HTTPClient::Util
39
- include OpenSSL if SSLEnabled
39
+ if SSLEnabled
40
+ include OpenSSL
41
+
42
+ module ::OpenSSL
43
+ module X509
44
+ class Store
45
+ attr_reader :_httpclient_cert_store_items
46
+
47
+ def initialize(*a, &b)
48
+ super(*a, &b)
49
+ @_httpclient_cert_store_items = [ENV['SSL_CERT_FILE'] || :default]
50
+ end
51
+
52
+ [:add_cert, :add_file, :add_path].each do |m|
53
+ wrapped = instance_method(m)
54
+ define_method(m) do |cert|
55
+ wrapped.bind(self).call(cert)
56
+ @_httpclient_cert_store_items << cert
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
40
63
 
41
64
  CIPHERS_DEFAULT = "ALL:!aNULL:!eNULL:!SSLv2" # OpenSSL >1.0.0 default
42
65
 
@@ -89,7 +112,7 @@ class HTTPClient
89
112
  attr_reader :client_ca # :nodoc:
90
113
 
91
114
  # These array keeps original files/dirs that was added to @cert_store
92
- attr_reader :cert_store_items
115
+ def cert_store_items; @cert_store._httpclient_cert_store_items; end
93
116
  attr_reader :cert_store_crl_items
94
117
 
95
118
  # Creates a SSLConfig.
@@ -97,7 +120,6 @@ class HTTPClient
97
120
  return unless SSLEnabled
98
121
  @client = client
99
122
  @cert_store = X509::Store.new
100
- @cert_store_items = [:default]
101
123
  @cert_store_crl_items = []
102
124
  @client_cert = @client_key = @client_ca = nil
103
125
  @verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
@@ -170,7 +192,6 @@ class HTTPClient
170
192
  @cacerts_loaded = true # avoid lazy override
171
193
  @cert_store = X509::Store.new
172
194
  @cert_store.set_default_paths
173
- @cert_store_items = [ENV['SSL_CERT_FILE'] || :default]
174
195
  change_notify
175
196
  end
176
197
 
@@ -181,7 +202,7 @@ class HTTPClient
181
202
  def clear_cert_store
182
203
  @cacerts_loaded = true # avoid lazy override
183
204
  @cert_store = X509::Store.new
184
- @cert_store_items.clear
205
+ @cert_store._httpclient_cert_store_items.clear
185
206
  change_notify
186
207
  end
187
208
 
@@ -192,7 +213,6 @@ class HTTPClient
192
213
  def cert_store=(cert_store)
193
214
  @cacerts_loaded = true # avoid lazy override
194
215
  @cert_store = cert_store
195
- @cert_store_items.clear
196
216
  change_notify
197
217
  end
198
218
 
@@ -209,7 +229,6 @@ class HTTPClient
209
229
  end
210
230
  @cacerts_loaded = true # avoid lazy override
211
231
  add_trust_ca_to_store(@cert_store, trust_ca_file_or_hashed_dir)
212
- @cert_store_items << trust_ca_file_or_hashed_dir
213
232
  change_notify
214
233
  end
215
234
  alias set_trust_ca add_trust_ca
@@ -308,6 +327,10 @@ class HTTPClient
308
327
  change_notify
309
328
  end
310
329
 
330
+ def verify?
331
+ @verify_mode && (@verify_mode & OpenSSL::SSL::VERIFY_PEER != 0)
332
+ end
333
+
311
334
  # interfaces for SSLSocket.
312
335
  def set_context(ctx) # :nodoc:
313
336
  load_trust_ca unless @cacerts_loaded
@@ -445,11 +468,7 @@ class HTTPClient
445
468
  def load_cacerts(cert_store)
446
469
  ver = OpenSSL::OPENSSL_VERSION
447
470
  file = File.join(File.dirname(__FILE__), 'cacert.pem')
448
- unless defined?(JRuby)
449
- # JRuby uses @cert_store_items
450
- add_trust_ca_to_store(cert_store, file)
451
- end
452
- @cert_store_items << file
471
+ add_trust_ca_to_store(cert_store, file)
453
472
  end
454
473
  end
455
474
 
@@ -1,3 +1,3 @@
1
1
  class HTTPClient
2
- VERSION = '2.8.0'
2
+ VERSION = '2.8.1'
3
3
  end
@@ -342,7 +342,7 @@ class WebAgent
342
342
  cookie.domain_orig = given.domain
343
343
  cookie.path_orig = given.path
344
344
 
345
- if cookie.discard? || cookie.expires == nil
345
+ if cookie.discard? || cookie.expires.nil?
346
346
  cookie.discard = true
347
347
  else
348
348
  cookie.discard = false
@@ -33,6 +33,7 @@ class OAuthClient < HTTPClient
33
33
  @oauth_config = HTTPClient::OAuth::Config.new
34
34
  self.www_auth.oauth.set_config(nil, @oauth_config)
35
35
  self.www_auth.oauth.challenge(nil)
36
+ self.strict_response_size_check = true
36
37
  end
37
38
 
38
39
  # Get request token.
@@ -2,7 +2,6 @@ require File.expand_path('helper', File.dirname(__FILE__))
2
2
  require 'digest/md5'
3
3
  require 'rack'
4
4
  require 'rack/lint'
5
- require 'rack/showexceptions'
6
5
  require 'rack-ntlm'
7
6
 
8
7
  class TestAuth < Test::Unit::TestCase
@@ -347,11 +347,13 @@ class TestClient < Test::Unit::TestCase
347
347
  def test_receive_timeout
348
348
  # this test takes 2 sec
349
349
  assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
350
+ @client.reset_all
350
351
  @client.receive_timeout = 1
351
352
  assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=0'))
352
353
  assert_raise(HTTPClient::ReceiveTimeoutError) do
353
354
  @client.get_content(serverurl + 'sleep?sec=2')
354
355
  end
356
+ @client.reset_all
355
357
  @client.receive_timeout = 3
356
358
  assert_equal('hello', @client.get_content(serverurl + 'sleep?sec=2'))
357
359
  end
@@ -609,10 +609,12 @@ EOS
609
609
  assert_not_equal('hello', content)
610
610
  assert_equal(GZIP_CONTENT, content)
611
611
  @client.transparent_gzip_decompression = true
612
+ @client.reset_all
612
613
  assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=gzip'))
613
614
  assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=deflate'))
614
615
  assert_equal('hello', @client.get_content(serverurl + 'compressed?enc=deflate_noheader'))
615
616
  @client.transparent_gzip_decompression = false
617
+ @client.reset_all
616
618
  end
617
619
 
618
620
  def test_get_content_with_block
@@ -765,6 +767,22 @@ EOS
765
767
  assert_equal(1000*1000, res.content.read.length)
766
768
  end
767
769
 
770
+ if RUBY_VERSION > "1.9"
771
+ def test_post_async_with_default_internal
772
+ original_encoding = Encoding.default_internal
773
+ Encoding.default_internal = Encoding::UTF_8
774
+ begin
775
+ post_body = StringIO.new("こんにちは")
776
+ conn = @client.post_async(serverurl + 'servlet', post_body)
777
+ Thread.pass while !conn.finished?
778
+ res = conn.pop
779
+ assert_equal 'post,こんにちは', res.content.read
780
+ ensure
781
+ Encoding.default_internal = original_encoding
782
+ end
783
+ end
784
+ end
785
+
768
786
  def test_get_with_block
769
787
  called = false
770
788
  res = @client.get(serverurl + 'servlet') { |str|
@@ -788,6 +806,29 @@ EOS
788
806
  assert_nil(res.content)
789
807
  end
790
808
 
809
+ def test_get_with_block_and_redirects
810
+ called = false
811
+ res = @client.get(serverurl + 'servlet', :follow_redirect => true) { |str|
812
+ assert_equal('get', str)
813
+ called = true
814
+ }
815
+ assert(called)
816
+ # res does not have a content
817
+ assert_nil(res.content)
818
+ end
819
+
820
+ def test_get_with_block_arity_2_and_redirects
821
+ called = false
822
+ res = @client.get(serverurl + 'servlet', :follow_redirect => true) { |blk_res, str|
823
+ assert_equal(200, blk_res.status)
824
+ assert_equal('get', str)
825
+ called = true
826
+ }
827
+ assert(called)
828
+ # res does not have a content
829
+ assert_nil(res.content)
830
+ end
831
+
791
832
  def test_get_with_block_string_recycle
792
833
  @client.read_block_size = 2
793
834
  body = []
@@ -1032,6 +1073,10 @@ EOS
1032
1073
  def test_post_with_custom_multipart_and_file
1033
1074
  STDOUT.sync = true
1034
1075
  File.open(__FILE__) do |file|
1076
+ def file.original_filename
1077
+ 'file.txt'
1078
+ end
1079
+
1035
1080
  ext = { 'Content-Type' => 'multipart/alternative' }
1036
1081
  body = [{ 'Content-Type' => 'text/plain', :content => "this is only a test" },
1037
1082
  { 'Content-Type' => 'application/x-ruby', :content => file }]
@@ -1039,6 +1084,7 @@ EOS
1039
1084
  assert_match(/^Content-Type: text\/plain\r\n/m, res.content)
1040
1085
  assert_match(/^this is only a test\r\n/m, res.content)
1041
1086
  assert_match(/^Content-Type: application\/x-ruby\r\n/m, res.content)
1087
+ assert_match(/Content-Disposition: form-data; name="3"; filename="file.txt"/, res.content)
1042
1088
  assert_match(/FIND_TAG_IN_THIS_FILE/, res.content)
1043
1089
  end
1044
1090
  end
@@ -1311,11 +1357,13 @@ EOS
1311
1357
  # this test takes 2 sec
1312
1358
  assert_equal('hello?sec=2', @client.get_content(serverurl + 'sleep?sec=2'))
1313
1359
  @client.receive_timeout = 1
1360
+ @client.reset_all
1314
1361
  assert_equal('hello?sec=0', @client.get_content(serverurl + 'sleep?sec=0'))
1315
1362
  assert_raise(HTTPClient::ReceiveTimeoutError) do
1316
1363
  @client.get_content(serverurl + 'sleep?sec=2')
1317
1364
  end
1318
1365
  @client.receive_timeout = 3
1366
+ @client.reset_all
1319
1367
  assert_equal('hello?sec=2', @client.get_content(serverurl + 'sleep?sec=2'))
1320
1368
  end
1321
1369
 
@@ -1323,11 +1371,13 @@ EOS
1323
1371
  # this test takes 2 sec
1324
1372
  assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content)
1325
1373
  @client.receive_timeout = 1
1374
+ @client.reset_all
1326
1375
  assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 0).content)
1327
1376
  assert_raise(HTTPClient::ReceiveTimeoutError) do
1328
1377
  @client.post(serverurl + 'sleep', :sec => 2)
1329
1378
  end
1330
1379
  @client.receive_timeout = 3
1380
+ @client.reset_all
1331
1381
  assert_equal('hello', @client.post(serverurl + 'sleep', :sec => 2).content)
1332
1382
  end
1333
1383
 
@@ -1486,6 +1536,7 @@ EOS
1486
1536
  assert_equal('text/plain', HTTP::Message.mime_type('foo.txt'))
1487
1537
  assert_equal('text/html', HTTP::Message.mime_type('foo.html'))
1488
1538
  assert_equal('text/html', HTTP::Message.mime_type('foo.htm'))
1539
+ assert_equal('text/xml', HTTP::Message.mime_type('foo.xml'))
1489
1540
  assert_equal('application/msword', HTTP::Message.mime_type('foo.doc'))
1490
1541
  assert_equal('image/png', HTTP::Message.mime_type('foo.png'))
1491
1542
  assert_equal('image/gif', HTTP::Message.mime_type('foo.gif'))
@@ -1779,6 +1830,19 @@ EOS
1779
1830
  end
1780
1831
  end
1781
1832
 
1833
+ def test_strict_response_size_check
1834
+ @client.strict_response_size_check = false
1835
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\nContent-Length: 12345\r\n\r\nhello world"
1836
+ assert_equal('hello world', @client.get_content('http://dummy'))
1837
+
1838
+ @client.reset_all
1839
+ @client.strict_response_size_check = true
1840
+ @client.test_loopback_http_response << "HTTP/1.0 200 OK\r\nContent-Length: 12345\r\n\r\nhello world"
1841
+ assert_raise(HTTPClient::BadResponseError) do
1842
+ @client.get_content('http://dummy')
1843
+ end
1844
+ end
1845
+
1782
1846
  def test_socket_local
1783
1847
  @client.socket_local.host = '127.0.0.1'
1784
1848
  assert_equal('hello', @client.get_content(serverurl + 'hello'))
@@ -149,6 +149,22 @@ end
149
149
  #
150
150
  cfg.verify_mode = nil
151
151
  assert_equal("hello", @client.get_content(@url))
152
+ cfg.verify_mode = OpenSSL::SSL::VERIFY_NONE
153
+ assert_equal("hello", @client.get_content(@url))
154
+ end
155
+
156
+ def test_cert_store
157
+ cfg = @client.ssl_config
158
+ cfg.cert_store.add_cert(cert('ca.cert'))
159
+ begin
160
+ @client.get(@url)
161
+ assert(false)
162
+ rescue OpenSSL::SSL::SSLError => ssle
163
+ assert_match(/(certificate verify failed|unable to find valid certification path to requested target)/, ssle.message)
164
+ end
165
+ #
166
+ cfg.cert_store.add_cert(cert('subca.cert'))
167
+ assert_equal("hello", @client.get_content(@url))
152
168
  end
153
169
 
154
170
  if defined?(HTTPClient::JRubySSLSocket)
@@ -237,7 +253,7 @@ end
237
253
  def test_use_higher_TLS
238
254
  omit('TODO: it does not pass with Java 7 or old openssl ')
239
255
  teardown_server
240
- setup_server_with_ssl_version(:TLSv1_2)
256
+ setup_server_with_ssl_version('TLSv1_2')
241
257
  assert_nothing_raised do
242
258
  @client.ssl_config.verify_mode = nil
243
259
  @client.get("https://localhost:#{serverport}/hello")
@@ -288,6 +304,10 @@ private
288
304
  end
289
305
 
290
306
  def setup_server_with_ssl_version(ssl_version)
307
+ # JRubyOpenSSL does not support "TLSv1_2" as an known version, and some JCE provides TLS v1.2 as "TLSv1.2" not "TLSv1_2"
308
+ if RUBY_ENGINE == 'jruby' && ['TLSv1_1', 'TLSv1_2'].include?(ssl_version)
309
+ ssl_version = ssl_version.tr('_', '.')
310
+ end
291
311
  logger = Logger.new(STDERR)
292
312
  logger.level = Logger::Severity::FATAL # avoid logging SSLError (ERROR level)
293
313
  @server = WEBrick::HTTPServer.new(
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: httpclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hiroshi Nakamura
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-04-24 00:00:00.000000000 Z
11
+ date: 2016-08-07 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description:
14
14
  email: nahi@ruby-lang.org
@@ -103,7 +103,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
103
  version: '0'
104
104
  requirements: []
105
105
  rubyforge_project:
106
- rubygems_version: 2.5.1
106
+ rubygems_version: 2.4.5.1
107
107
  signing_key:
108
108
  specification_version: 4
109
109
  summary: gives something like the functionality of libwww-perl (LWP) in Ruby