bterlson-httpclient 2.1.4 → 2.1.5

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.
@@ -160,8 +160,10 @@ class WebAgent
160
160
 
161
161
  def parse(str, url)
162
162
  @url = url
163
+ # TODO: should not depend on join_quotedstr. scan with escape like CSV.
163
164
  cookie_elem = str.split(/;/)
164
165
  cookie_elem = join_quotedstr(cookie_elem, ';')
166
+ cookie_elem -= [""] # del empty elements, a cookie might included ";;"
165
167
  first_elem = cookie_elem.shift
166
168
  if first_elem !~ /([^=]*)(\=(.*))?/
167
169
  return
@@ -170,7 +172,7 @@ class WebAgent
170
172
  @name = $1.strip
171
173
  @value = normalize_cookie_value($3)
172
174
  cookie_elem.each{|pair|
173
- key, value = pair.split(/=/) ## value may nil
175
+ key, value = pair.split(/=/, 2) ## value may nil
174
176
  key.strip!
175
177
  value = normalize_cookie_value(value)
176
178
  case key.downcase
@@ -320,7 +320,7 @@ module HTTP
320
320
  end
321
321
  if @chunked
322
322
  set('Transfer-Encoding', 'chunked')
323
- elsif keep_alive or @body_size != 0
323
+ elsif @body_size and (keep_alive or @body_size != 0)
324
324
  set('Content-Length', @body_size.to_s)
325
325
  end
326
326
  if @http_version >= 1.1
@@ -623,7 +623,7 @@ module HTTP
623
623
  def new_connect_request(uri)
624
624
  m = new
625
625
  m.header.init_connect_request(uri)
626
- m.header.body_size = 0
626
+ m.header.body_size = nil
627
627
  m
628
628
  end
629
629
 
@@ -645,8 +645,12 @@ module HTTP
645
645
  m.header.init_request(method, uri, query)
646
646
  m.body = Body.new
647
647
  m.body.init_request(body || '', boundary)
648
- m.header.body_size = m.body.size
649
- m.header.chunked = true if m.body.size.nil?
648
+ if body
649
+ m.header.body_size = m.body.size
650
+ m.header.chunked = true if m.body.size.nil?
651
+ else
652
+ m.header.body_size = nil
653
+ end
650
654
  m
651
655
  end
652
656
 
@@ -445,7 +445,7 @@ class HTTPClient
445
445
  include SocketWrap
446
446
 
447
447
  def initialize(host, port, response)
448
- super(StringIO.new(response))
448
+ super(response.is_a?(StringIO) ? response : StringIO.new(response))
449
449
  @host = host
450
450
  @port = port
451
451
  end
@@ -800,9 +800,13 @@ class HTTPClient
800
800
  maxbytes = @read_block_size
801
801
  maxbytes = @content_length if maxbytes > @content_length
802
802
  timeout(@receive_timeout, ReceiveTimeoutError) do
803
- @socket.readpartial(maxbytes, buf) rescue EOFError
803
+ begin
804
+ @socket.readpartial(maxbytes, buf)
805
+ rescue EOFError
806
+ buf = nil
807
+ end
804
808
  end
805
- if buf.length > 0
809
+ if buf && buf.length > 0
806
810
  @content_length -= buf.length
807
811
  yield buf
808
812
  else
@@ -840,7 +844,11 @@ class HTTPClient
840
844
  buf = ''
841
845
  while true
842
846
  timeout(@receive_timeout, ReceiveTimeoutError) do
843
- @socket.readpartial(@read_block_size, buf) rescue EOFError
847
+ begin
848
+ @socket.readpartial(@read_block_size, buf)
849
+ rescue EOFError
850
+ buf = nil
851
+ end
844
852
  end
845
853
  if buf && buf.length > 0
846
854
  yield buf
@@ -339,40 +339,78 @@ class HTTPClient
339
339
  end
340
340
 
341
341
  def load_cacerts
342
- file = File.join(File.dirname(__FILE__), 'cacert.p7s')
343
- if File.exist?(file)
344
- dist_cert =<<__DIST_CERT__
345
- -----BEGIN CERTIFICATE-----
346
- MIIC/jCCAmegAwIBAgIBATANBgkqhkiG9w0BAQUFADBNMQswCQYDVQQGEwJKUDER
347
- MA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVsb3BtZW50MRUwEwYDVQQD
348
- DAxodHRwLWFjY2VzczIwHhcNMDcwOTExMTM1ODMxWhcNMDkwOTEwMTM1ODMxWjBN
349
- MQswCQYDVQQGEwJKUDERMA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVs
350
- b3BtZW50MRUwEwYDVQQDDAxodHRwLWFjY2VzczIwgZ8wDQYJKoZIhvcNAQEBBQAD
351
- gY0AMIGJAoGBALi66ujWtUCQm5HpMSyr/AAIFYVXC/dmn7C8TR/HMiUuW3waY4uX
352
- LFqCDAGOX4gf177pX+b99t3mpaiAjJuqc858D9xEECzhDWgXdLbhRqWhUOble4RY
353
- c1yWYC990IgXJDMKx7VAuZ3cBhdBxtlE9sb1ZCzmHQsvTy/OoRzcJCrTAgMBAAGj
354
- ge0wgeowDwYDVR0TAQH/BAUwAwEB/zAxBglghkgBhvhCAQ0EJBYiUnVieS9PcGVu
355
- U1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUJNE0GGaRKmN2qhnO
356
- FyBWVl4Qj6owDgYDVR0PAQH/BAQDAgEGMHUGA1UdIwRuMGyAFCTRNBhmkSpjdqoZ
357
- zhcgVlZeEI+qoVGkTzBNMQswCQYDVQQGEwJKUDERMA8GA1UECgwIY3Rvci5vcmcx
358
- FDASBgNVBAsMC0RldmVsb3BtZW50MRUwEwYDVQQDDAxodHRwLWFjY2VzczKCAQEw
359
- DQYJKoZIhvcNAQEFBQADgYEAH11tstSUuqFpMqoh/vM5l3Nqb8ygblbqEYQs/iG/
360
- UeQkOZk/P1TxB6Ozn2htJ1srqDpUsncFVZ/ecP19GkeOZ6BmIhppcHhE5WyLBcPX
361
- It5q1BW0PiAzT9LlEGoaiW0nw39so0Pr1whJDfc1t4fjdk+kSiMIzRHbTDvHWfpV
362
- nTA=
363
- -----END CERTIFICATE-----
364
- __DIST_CERT__
365
- p7 = PKCS7.read_smime(File.open(file) { |f| f.read })
366
- selfcert = X509::Certificate.new(dist_cert)
367
- store = X509::Store.new
368
- store.add_cert(selfcert)
369
- if (p7.verify(nil, store, p7.data, 0))
370
- set_trust_ca(file)
371
- else
372
- STDERR.puts("cacerts: #{file} loading failed")
342
+ [
343
+ [DIST_CERT, 'cacert.p7s'],
344
+ [DIST_CERT_SHA1, 'cacert_sha1.p7s']
345
+ ].each do |cert_str, ca_file|
346
+ file = File.join(File.dirname(__FILE__), ca_file)
347
+ if File.exist?(file)
348
+ p7 = PKCS7.read_smime(File.open(file) { |f| f.read })
349
+ selfcert = X509::Certificate.new(cert_str)
350
+ store = X509::Store.new
351
+ store.add_cert(selfcert)
352
+ if (p7.verify(nil, store, p7.data, 0))
353
+ set_trust_ca(file)
354
+ return
355
+ end
373
356
  end
374
357
  end
358
+ STDERR.puts("cacerts loading failed")
375
359
  end
360
+
361
+ DIST_CERT =<<__DIST_CERT__
362
+ -----BEGIN CERTIFICATE-----
363
+ MIID/TCCAuWgAwIBAgIBATANBgkqhkiG9w0BAQ0FADBLMQswCQYDVQQGEwJKUDER
364
+ MA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVsb3BtZW50MRMwEQYDVQQD
365
+ DApodHRwY2xpZW50MB4XDTA5MDUyMTEyMzkwNVoXDTM3MTIzMTIzNTk1OVowSzEL
366
+ MAkGA1UEBhMCSlAxETAPBgNVBAoMCGN0b3Iub3JnMRQwEgYDVQQLDAtEZXZlbG9w
367
+ bWVudDETMBEGA1UEAwwKaHR0cGNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEP
368
+ ADCCAQoCggEBAM2PlkdTH97zvIHoPIMj87wnNvpqIQUD7L/hlysO0XBsmR/XZUeU
369
+ ZKB10JQqMXviWpTnU9KU6xGTx3EI4wfd2dpLwH/d4d7K4LngW1kY7kJlZeJhakno
370
+ GzQ40RSI9WkQ0R9KOE888f7OkTBafcL8UyWFVIMhQBw2d9iNl4Jc69QojayCDoSX
371
+ XbbEP0n8yi7HwIU3RFuX6DtMpOx4/1K7Z002ccOGJ3J9kHgeDQSQtF42cQYC7qj2
372
+ 67I/OQgnB7ycxTCP0E7bdXQg+zqsngrhaoNn/+I+CoO7nD4t4uQ+B4agALh4PPxs
373
+ bQD9MCL+VurNGLYv0HVd+ZlLblpddC9PLTsCAwEAAaOB6zCB6DAPBgNVHRMBAf8E
374
+ BTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09wZW5TU0wgR2VuZXJhdGVkIENl
375
+ cnRpZmljYXRlMB0GA1UdDgQWBBRAnB6XlMoOcm7HVAw+JWxY205PHTAOBgNVHQ8B
376
+ Af8EBAMCAQYwcwYDVR0jBGwwaoAUQJwel5TKDnJux1QMPiVsWNtOTx2hT6RNMEsx
377
+ CzAJBgNVBAYTAkpQMREwDwYDVQQKDAhjdG9yLm9yZzEUMBIGA1UECwwLRGV2ZWxv
378
+ cG1lbnQxEzARBgNVBAMMCmh0dHBjbGllbnSCAQEwDQYJKoZIhvcNAQENBQADggEB
379
+ ABVFepybD5XqsBnOn/oDHvK0xAPMF4Ap4Ht1yMQLObg8paVhANSdqIevPlCr/mPL
380
+ DRjcy+J1fCnE6lCfsfLdTgAjirqt8pm92NccxmJ8hTmMd3LWC1n+eYWaolqTCVRM
381
+ Bpe8UY9enyXrFoudHlr9epr18E6As6VrCSfpXFZkD9WHVSWpzkB3qATu5qcDCzCH
382
+ bI0755Mdm/1hKJCD4l69h3J3OhRIEUPJfHnPvM5wtiyC2dcE9itwE/wdVzBJeIBX
383
+ JQm+Qj+K8qXcRTzZZGIBjw2n46xJgW6YncNCHU/WWfNCYwdkngHS/aN8IbEjhCwf
384
+ viXFisVrDN/+pZZGMf67ZaY=
385
+ -----END CERTIFICATE-----
386
+ __DIST_CERT__
387
+
388
+ DIST_CERT_SHA1 =<<__DIST_CERT__
389
+ -----BEGIN CERTIFICATE-----
390
+ MIID/TCCAuWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJKUDER
391
+ MA8GA1UECgwIY3Rvci5vcmcxFDASBgNVBAsMC0RldmVsb3BtZW50MRMwEQYDVQQD
392
+ DApodHRwY2xpZW50MB4XDTA5MDYyNTE0MjUzN1oXDTEwMTIzMTIzNTk1OVowSzEL
393
+ MAkGA1UEBhMCSlAxETAPBgNVBAoMCGN0b3Iub3JnMRQwEgYDVQQLDAtEZXZlbG9w
394
+ bWVudDETMBEGA1UEAwwKaHR0cGNsaWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEP
395
+ ADCCAQoCggEBAM2PlkdTH97zvIHoPIMj87wnNvpqIQUD7L/hlysO0XBsmR/XZUeU
396
+ ZKB10JQqMXviWpTnU9KU6xGTx3EI4wfd2dpLwH/d4d7K4LngW1kY7kJlZeJhakno
397
+ GzQ40RSI9WkQ0R9KOE888f7OkTBafcL8UyWFVIMhQBw2d9iNl4Jc69QojayCDoSX
398
+ XbbEP0n8yi7HwIU3RFuX6DtMpOx4/1K7Z002ccOGJ3J9kHgeDQSQtF42cQYC7qj2
399
+ 67I/OQgnB7ycxTCP0E7bdXQg+zqsngrhaoNn/+I+CoO7nD4t4uQ+B4agALh4PPxs
400
+ bQD9MCL+VurNGLYv0HVd+ZlLblpddC9PLTsCAwEAAaOB6zCB6DAPBgNVHRMBAf8E
401
+ BTADAQH/MDEGCWCGSAGG+EIBDQQkFiJSdWJ5L09wZW5TU0wgR2VuZXJhdGVkIENl
402
+ cnRpZmljYXRlMB0GA1UdDgQWBBRAnB6XlMoOcm7HVAw+JWxY205PHTAOBgNVHQ8B
403
+ Af8EBAMCAQYwcwYDVR0jBGwwaoAUQJwel5TKDnJux1QMPiVsWNtOTx2hT6RNMEsx
404
+ CzAJBgNVBAYTAkpQMREwDwYDVQQKDAhjdG9yLm9yZzEUMBIGA1UECwwLRGV2ZWxv
405
+ cG1lbnQxEzARBgNVBAMMCmh0dHBjbGllbnSCAQIwDQYJKoZIhvcNAQEFBQADggEB
406
+ AGKhgByl/ur6SBFFKJcISJONFRaxf2ji0l6ut9XO1H2BSOSRjUbsFDWdWZG+D24Q
407
+ JKKseSWPWAC5uHq00sBWkvmtip+duESPeDEdumdBhdiUUgGamW2Ew2y4yAdAVDeG
408
+ t1p2fs8SylQN6AMTG/+R+MGHxhvg+UELYLcvAjjcDW2VhDQaJ1eFEfcMW1zRtvvh
409
+ LJmVErouwFKyAjwhbF6sNxmToSnbO1ciWwIILMsOBNHMETCp+SzkRDIRWIkm6m+q
410
+ RwRyYoHysODGvnu8VXS1hGRr2GIxeBga7dAGa2VLE/iUQ0d4lEskYU+6C4ZLyAWF
411
+ O89dvLNRzpL10MaWCYVREks=
412
+ -----END CERTIFICATE-----
413
+ __DIST_CERT__
376
414
  end
377
415
 
378
416
 
@@ -168,6 +168,18 @@ class TestCookieManager < Test::Unit::TestCase
168
168
  assert_equal(Time.gm(2009,12,31,12,0,0), cookie.expires)
169
169
  end
170
170
 
171
+ def test_parse_double_semicolon()
172
+ str = "xmen=off,0,0,1;; path=\"/;;\"; domain=.excite.co.jp; expires=Wednesday, 31-Dec-2009 12:00:00 GMT"
173
+ @cm.parse(str,URI.parse('http://www.excite.co.jp'))
174
+ cookie = @cm.cookies[0]
175
+ assert_instance_of(WebAgent::Cookie, cookie)
176
+ assert_equal("xmen", cookie.name)
177
+ assert_equal("off,0,0,1", cookie.value)
178
+ assert_equal("/;;", cookie.path)
179
+ assert_equal(".excite.co.jp", cookie.domain)
180
+ assert_equal(Time.gm(2009,12,31,12,0,0), cookie.expires)
181
+ end
182
+
171
183
  # def test_make_portlist()
172
184
  # assert_equal([80,8080], @cm.instance_eval{make_portlist("80,8080")})
173
185
  # assert_equal([80], @cm.instance_eval{make_portlist("80")})
@@ -109,7 +109,7 @@ class TestClient < Test::Unit::TestCase
109
109
  assert_equal("= Request", lines[0])
110
110
  assert_equal("! CONNECTION ESTABLISHED", lines[2])
111
111
  assert_equal("GET / HTTP/1.1", lines[3])
112
- assert_equal("Host: localhost:#{Port}", lines[6])
112
+ assert_equal("Host: localhost:#{Port}", lines[5])
113
113
  @client.protocol_version = 'HTTP/1.1'
114
114
  str = ""
115
115
  @client.debug_dev = str
@@ -123,7 +123,7 @@ class TestHTTPClient < Test::Unit::TestCase
123
123
  assert_equal("= Request", lines[0])
124
124
  assert_equal("! CONNECTION ESTABLISHED", lines[2])
125
125
  assert_equal("GET / HTTP/1.1", lines[3])
126
- assert_equal("Host: localhost:#{Port}", lines[6])
126
+ assert_equal("Host: localhost:#{Port}", lines[5])
127
127
  @client.protocol_version = 'HTTP/1.1'
128
128
  assert_equal('HTTP/1.1', @client.protocol_version)
129
129
  str = ""
@@ -262,6 +262,33 @@ class TestHTTPClient < Test::Unit::TestCase
262
262
  end
263
263
  end
264
264
 
265
+ def test_cookie_update_while_authentication
266
+ escape_noproxy do
267
+ @client.test_loopback_http_response << <<EOS
268
+ HTTP/1.0 401\r
269
+ Date: Fri, 19 Dec 2008 11:57:29 GMT\r
270
+ Content-Type: text/plain\r
271
+ Content-Length: 0\r
272
+ WWW-Authenticate: Basic realm="hello"\r
273
+ Set-Cookie: foo=bar; path=/; domain=.example.org; expires=#{Time.mktime(2030, 12, 31).httpdate}\r
274
+ \r
275
+ EOS
276
+ @client.test_loopback_http_response << <<EOS
277
+ HTTP/1.1 200 OK\r
278
+ Content-Length: 5\r
279
+ Connection: close\r
280
+ \r
281
+ hello
282
+ EOS
283
+ @client.debug_dev = str = ''
284
+ @client.set_auth("http://www.example.org/baz/", 'admin', 'admin')
285
+ assert_equal('hello', @client.get('http://www.example.org/baz/foo').content)
286
+ assert_match(/^Cookie: foo=bar/, str)
287
+ assert_match(/^Authorization: Basic YWRtaW46YWRtaW4=/, str)
288
+ end
289
+ end
290
+
291
+
265
292
  def test_proxy_ssl
266
293
  escape_noproxy do
267
294
  @client.proxy = 'http://admin:admin@localhost:8080/'
@@ -770,6 +797,62 @@ EOS
770
797
  assert_match(%r(http://rubyforge.org/account/login.php foo bar 1924873200 rubyforge.org /login.php 1), str)
771
798
  end
772
799
 
800
+ def test_eof_error_length
801
+ io = StringIO.new('')
802
+ def io.gets(*arg)
803
+ @buf ||= ["HTTP/1.0 200 OK\n", "content-length: 123\n", "\n"]
804
+ @buf.shift
805
+ end
806
+ def io.readpartial(size, buf)
807
+ @second ||= false
808
+ if !@second
809
+ @second = '1st'
810
+ buf << "abc"
811
+ buf
812
+ elsif @second == '1st'
813
+ @second = '2nd'
814
+ raise EOFError.new
815
+ else
816
+ raise Exception.new
817
+ end
818
+ end
819
+ def io.eof?
820
+ true
821
+ end
822
+ @client.test_loopback_http_response << io
823
+ assert_nothing_raised do
824
+ @client.get('http://foo/bar')
825
+ end
826
+ end
827
+
828
+ def test_eof_error_rest
829
+ io = StringIO.new('')
830
+ def io.gets(*arg)
831
+ @buf ||= ["HTTP/1.0 200 OK\n", "\n"]
832
+ @buf.shift
833
+ end
834
+ def io.readpartial(size, buf)
835
+ @second ||= false
836
+ if !@second
837
+ @second = '1st'
838
+ buf << "abc"
839
+ buf
840
+ elsif @second == '1st'
841
+ @second = '2nd'
842
+ raise EOFError.new
843
+ else
844
+ raise Exception.new
845
+ end
846
+ end
847
+ def io.eof?
848
+ true
849
+ end
850
+ @client.test_loopback_http_response << io
851
+ assert_nothing_raised do
852
+ @client.get('http://foo/bar')
853
+ end
854
+ end
855
+
773
856
  def test_urify
774
857
  extend HTTPClient::Util
775
858
  assert_nil(urify(nil))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bterlson-httpclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.4
4
+ version: 2.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - NAKAMURA, Hiroshi
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2009-03-27 00:00:00 -07:00
13
+ date: 2009-07-02 00:00:00 -07:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -32,6 +32,7 @@ files:
32
32
  - lib/httpclient
33
33
  - lib/httpclient/auth.rb
34
34
  - lib/httpclient/cacert.p7s
35
+ - lib/httpclient/cacert_sha1.p7s
35
36
  - lib/httpclient/connection.rb
36
37
  - lib/httpclient/cookie.rb
37
38
  - lib/httpclient/http.rb
@@ -80,7 +81,7 @@ requirements: []
80
81
  rubyforge_project:
81
82
  rubygems_version: 1.2.0
82
83
  signing_key:
83
- specification_version: 2
84
+ specification_version: 3
84
85
  summary: gives something like the functionality of libwww-perl (LWP) in Ruby
85
86
  test_files: []
86
87