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.
- data/README.txt +56 -2
- data/VERSION.yml +1 -1
- data/lib/httpclient.rb +30 -18
- data/lib/httpclient/auth.rb +18 -7
- data/lib/httpclient/cacert.p7s +670 -30
- data/lib/httpclient/cacert_sha1.p7s +1579 -0
- data/lib/httpclient/cookie.rb +3 -1
- data/lib/httpclient/http.rb +8 -4
- data/lib/httpclient/session.rb +12 -4
- data/lib/httpclient/ssl_config.rb +69 -31
- data/test/test_cookie.rb +12 -0
- data/test/test_http-access2.rb +1 -1
- data/test/test_httpclient.rb +84 -1
- metadata +4 -3
data/lib/httpclient/cookie.rb
CHANGED
@@ -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(
|
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
|
data/lib/httpclient/http.rb
CHANGED
@@ -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 =
|
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
|
-
|
649
|
-
|
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
|
|
data/lib/httpclient/session.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
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
|
|
data/test/test_cookie.rb
CHANGED
@@ -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")})
|
data/test/test_http-access2.rb
CHANGED
@@ -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[
|
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
|
data/test/test_httpclient.rb
CHANGED
@@ -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[
|
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
|
+
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-
|
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:
|
84
|
+
specification_version: 3
|
84
85
|
summary: gives something like the functionality of libwww-perl (LWP) in Ruby
|
85
86
|
test_files: []
|
86
87
|
|