httpclient-fixcerts 2.8.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.
- checksums.yaml +7 -0
- data/README.md +98 -0
- data/bin/httpclient +77 -0
- data/bin/jsonclient +85 -0
- data/lib/hexdump.rb +50 -0
- data/lib/http-access2/cookie.rb +1 -0
- data/lib/http-access2/http.rb +1 -0
- data/lib/http-access2.rb +55 -0
- data/lib/httpclient/auth.rb +924 -0
- data/lib/httpclient/cacert.pem +3952 -0
- data/lib/httpclient/cacert1024.pem +3866 -0
- data/lib/httpclient/connection.rb +88 -0
- data/lib/httpclient/cookie.rb +220 -0
- data/lib/httpclient/http.rb +1082 -0
- data/lib/httpclient/include_client.rb +85 -0
- data/lib/httpclient/jruby_ssl_socket.rb +594 -0
- data/lib/httpclient/session.rb +960 -0
- data/lib/httpclient/ssl_config.rb +433 -0
- data/lib/httpclient/ssl_socket.rb +150 -0
- data/lib/httpclient/timeout.rb +140 -0
- data/lib/httpclient/util.rb +222 -0
- data/lib/httpclient/version.rb +3 -0
- data/lib/httpclient/webagent-cookie.rb +459 -0
- data/lib/httpclient.rb +1332 -0
- data/lib/jsonclient.rb +66 -0
- data/lib/oauthclient.rb +111 -0
- data/sample/async.rb +8 -0
- data/sample/auth.rb +11 -0
- data/sample/cookie.rb +18 -0
- data/sample/dav.rb +103 -0
- data/sample/howto.rb +49 -0
- data/sample/jsonclient.rb +67 -0
- data/sample/oauth_buzz.rb +57 -0
- data/sample/oauth_friendfeed.rb +59 -0
- data/sample/oauth_twitter.rb +61 -0
- data/sample/ssl/0cert.pem +22 -0
- data/sample/ssl/0key.pem +30 -0
- data/sample/ssl/1000cert.pem +19 -0
- data/sample/ssl/1000key.pem +18 -0
- data/sample/ssl/htdocs/index.html +10 -0
- data/sample/ssl/ssl_client.rb +22 -0
- data/sample/ssl/webrick_httpsd.rb +29 -0
- data/sample/stream.rb +21 -0
- data/sample/thread.rb +27 -0
- data/sample/wcat.rb +21 -0
- data/test/ca-chain.pem +44 -0
- data/test/ca.cert +23 -0
- data/test/client-pass.key +18 -0
- data/test/client.cert +19 -0
- data/test/client.key +15 -0
- data/test/helper.rb +131 -0
- data/test/htdigest +1 -0
- data/test/htpasswd +2 -0
- data/test/jruby_ssl_socket/test_pemutils.rb +32 -0
- data/test/runner.rb +2 -0
- data/test/server.cert +19 -0
- data/test/server.key +15 -0
- data/test/sslsvr.rb +65 -0
- data/test/subca.cert +21 -0
- data/test/test_auth.rb +492 -0
- data/test/test_cookie.rb +309 -0
- data/test/test_hexdump.rb +14 -0
- data/test/test_http-access2.rb +508 -0
- data/test/test_httpclient.rb +2145 -0
- data/test/test_include_client.rb +52 -0
- data/test/test_jsonclient.rb +98 -0
- data/test/test_ssl.rb +562 -0
- data/test/test_webagent-cookie.rb +465 -0
- metadata +124 -0
@@ -0,0 +1,140 @@
|
|
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 'timeout'
|
10
|
+
require 'thread'
|
11
|
+
|
12
|
+
|
13
|
+
class HTTPClient
|
14
|
+
|
15
|
+
|
16
|
+
# Replaces timeout.rb to avoid Thread creation and scheduling overhead.
|
17
|
+
#
|
18
|
+
# You should check another timeout replace in WEBrick.
|
19
|
+
# See lib/webrick/utils.rb in ruby/1.9.
|
20
|
+
#
|
21
|
+
# About this implementation:
|
22
|
+
# * Do not create Thread for each timeout() call. Just create 1 Thread for
|
23
|
+
# timeout scheduler.
|
24
|
+
# * Do not wakeup the scheduler thread so often. Let scheduler thread sleep
|
25
|
+
# until the nearest period.
|
26
|
+
if !defined?(JRUBY_VERSION) and RUBY_VERSION < '1.9'
|
27
|
+
class TimeoutScheduler
|
28
|
+
|
29
|
+
# Represents timeout period.
|
30
|
+
class Period
|
31
|
+
attr_reader :thread, :time
|
32
|
+
|
33
|
+
# Creates new Period.
|
34
|
+
def initialize(thread, time, ex)
|
35
|
+
@thread, @time, @ex = thread, time, ex
|
36
|
+
@lock = Mutex.new
|
37
|
+
end
|
38
|
+
|
39
|
+
# Raises if thread exists and alive.
|
40
|
+
def raise(message)
|
41
|
+
@lock.synchronize do
|
42
|
+
if @thread and @thread.alive?
|
43
|
+
@thread.raise(@ex, message)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Cancel this Period. Mutex is needed to avoid too-late exception.
|
49
|
+
def cancel
|
50
|
+
@lock.synchronize do
|
51
|
+
@thread = nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Creates new TimeoutScheduler.
|
57
|
+
def initialize
|
58
|
+
@pool = {}
|
59
|
+
@next = nil
|
60
|
+
@thread = start_timer_thread
|
61
|
+
end
|
62
|
+
|
63
|
+
# Registers new timeout period.
|
64
|
+
def register(thread, sec, ex)
|
65
|
+
period = Period.new(thread, Time.now + sec, ex || ::Timeout::Error)
|
66
|
+
@pool[period] = true
|
67
|
+
if @next.nil? or period.time < @next
|
68
|
+
begin
|
69
|
+
@thread.wakeup
|
70
|
+
rescue ThreadError
|
71
|
+
# Thread may be dead by fork.
|
72
|
+
@thread = start_timer_thread
|
73
|
+
end
|
74
|
+
end
|
75
|
+
period
|
76
|
+
end
|
77
|
+
|
78
|
+
# Cancels the given period.
|
79
|
+
def cancel(period)
|
80
|
+
@pool.delete(period)
|
81
|
+
period.cancel
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def start_timer_thread
|
87
|
+
thread = Thread.new {
|
88
|
+
while true
|
89
|
+
if @pool.empty?
|
90
|
+
@next = nil
|
91
|
+
sleep
|
92
|
+
else
|
93
|
+
min, = @pool.min { |a, b| a[0].time <=> b[0].time }
|
94
|
+
@next = min.time
|
95
|
+
sec = @next - Time.now
|
96
|
+
if sec > 0
|
97
|
+
sleep(sec)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
now = Time.now
|
101
|
+
@pool.keys.each do |period|
|
102
|
+
if period.time < now
|
103
|
+
period.raise('execution expired')
|
104
|
+
cancel(period)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
}
|
109
|
+
Thread.pass while thread.status != 'sleep'
|
110
|
+
thread
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class << self
|
115
|
+
# CAUTION: caller must aware of race condition.
|
116
|
+
def timeout_scheduler
|
117
|
+
@timeout_scheduler ||= TimeoutScheduler.new
|
118
|
+
end
|
119
|
+
end
|
120
|
+
timeout_scheduler # initialize at first time.
|
121
|
+
end
|
122
|
+
|
123
|
+
module Timeout
|
124
|
+
if !defined?(JRUBY_VERSION) and RUBY_VERSION < '1.9'
|
125
|
+
def timeout(sec, ex = nil, &block)
|
126
|
+
return yield if sec == nil or sec.zero?
|
127
|
+
scheduler = nil
|
128
|
+
begin
|
129
|
+
scheduler = HTTPClient.timeout_scheduler
|
130
|
+
period = scheduler.register(Thread.current, sec, ex)
|
131
|
+
yield(sec)
|
132
|
+
ensure
|
133
|
+
scheduler.cancel(period) if scheduler and period
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,222 @@
|
|
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
|
+
unless ''.respond_to?(:bytesize)
|
10
|
+
class String
|
11
|
+
alias bytesize size
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
if RUBY_VERSION < "1.9.3"
|
16
|
+
require 'uri'
|
17
|
+
module URI
|
18
|
+
class Generic
|
19
|
+
def hostname
|
20
|
+
v = self.host
|
21
|
+
/\A\[(.*)\]\z/ =~ v ? $1 : v
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
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
|
+
|
49
|
+
class HTTPClient
|
50
|
+
|
51
|
+
|
52
|
+
# A module for common function.
|
53
|
+
module Util
|
54
|
+
|
55
|
+
# URI abstraction; Addressable::URI or URI
|
56
|
+
require 'uri'
|
57
|
+
begin
|
58
|
+
require 'addressable/uri'
|
59
|
+
# Older versions doesn't have #default_port
|
60
|
+
unless Addressable::URI.instance_methods.include?(:default_port) # 1.9 only
|
61
|
+
raise LoadError
|
62
|
+
end
|
63
|
+
class AddressableURI < Addressable::URI
|
64
|
+
# Overwrites the original definition just for one line...
|
65
|
+
def authority
|
66
|
+
self.host && @authority ||= (begin
|
67
|
+
authority = ""
|
68
|
+
if self.userinfo != nil
|
69
|
+
authority << "#{self.userinfo}@"
|
70
|
+
end
|
71
|
+
authority << self.host
|
72
|
+
if self.port != self.default_port # ...HERE! Compares with default_port because self.port is not nil in this wrapper.
|
73
|
+
authority << ":#{self.port}"
|
74
|
+
end
|
75
|
+
authority
|
76
|
+
end)
|
77
|
+
end
|
78
|
+
|
79
|
+
# HTTPClient expects urify("http://foo/").port to be not nil but 80 like URI.
|
80
|
+
def port
|
81
|
+
super || default_port
|
82
|
+
end
|
83
|
+
|
84
|
+
# Captured from uri/generic.rb
|
85
|
+
def hostname
|
86
|
+
v = self.host
|
87
|
+
/\A\[(.*)\]\z/ =~ v ? $1 : v
|
88
|
+
end
|
89
|
+
end
|
90
|
+
AddressableEnabled = true
|
91
|
+
rescue LoadError
|
92
|
+
AddressableEnabled = false
|
93
|
+
end
|
94
|
+
|
95
|
+
# Keyword argument helper.
|
96
|
+
# args:: given arguments.
|
97
|
+
# *field:: a list of arguments to be extracted.
|
98
|
+
#
|
99
|
+
# You can extract 3 arguments (a, b, c) with:
|
100
|
+
#
|
101
|
+
# include Util
|
102
|
+
# def my_method(*args)
|
103
|
+
# a, b, c = keyword_argument(args, :a, :b, :c)
|
104
|
+
# ...
|
105
|
+
# end
|
106
|
+
# my_method(1, 2, 3)
|
107
|
+
# my_method(:b => 2, :a = 1)
|
108
|
+
#
|
109
|
+
# instead of;
|
110
|
+
#
|
111
|
+
# def my_method(a, b, c)
|
112
|
+
# ...
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
def keyword_argument(args, *field)
|
116
|
+
if args.size == 1 and Hash === args[0]
|
117
|
+
h = args[0]
|
118
|
+
if field.any? { |f| h.key?(f) }
|
119
|
+
return h.values_at(*field)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
args
|
123
|
+
end
|
124
|
+
|
125
|
+
# Keyword argument to hash helper.
|
126
|
+
# args:: given arguments.
|
127
|
+
# *field:: a list of arguments to be extracted.
|
128
|
+
#
|
129
|
+
# Returns hash which has defined keys. When a Hash given, returns it
|
130
|
+
# including undefined keys. When an Array given, returns a Hash which only
|
131
|
+
# includes defined keys.
|
132
|
+
def argument_to_hash(args, *field)
|
133
|
+
return nil if args.empty?
|
134
|
+
if args.size == 1 and Hash === args[0]
|
135
|
+
h = args[0]
|
136
|
+
if field.any? { |f| h.key?(f) }
|
137
|
+
return h
|
138
|
+
end
|
139
|
+
end
|
140
|
+
h = {}
|
141
|
+
field.each_with_index do |e, idx|
|
142
|
+
h[e] = args[idx]
|
143
|
+
end
|
144
|
+
h
|
145
|
+
end
|
146
|
+
|
147
|
+
# Gets an URI instance.
|
148
|
+
def urify(uri)
|
149
|
+
if uri.nil?
|
150
|
+
nil
|
151
|
+
elsif uri.is_a?(URI)
|
152
|
+
uri
|
153
|
+
elsif AddressableEnabled
|
154
|
+
AddressableURI.parse(uri.to_s)
|
155
|
+
else
|
156
|
+
URI.parse(uri.to_s)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
module_function :urify
|
160
|
+
|
161
|
+
# Returns true if the given 2 URIs have a part_of relationship.
|
162
|
+
# * the same scheme
|
163
|
+
# * the same host String (no host resolution or IP-addr conversion)
|
164
|
+
# * the same port number
|
165
|
+
# * target URI's path starts with base URI's path.
|
166
|
+
def uri_part_of(uri, part)
|
167
|
+
((uri.scheme == part.scheme) and
|
168
|
+
(uri.host == part.host) and
|
169
|
+
(uri.port == part.port) and
|
170
|
+
uri.path.upcase.index(part.path.upcase) == 0)
|
171
|
+
end
|
172
|
+
module_function :uri_part_of
|
173
|
+
|
174
|
+
# Returns parent directory URI of the given URI.
|
175
|
+
def uri_dirname(uri)
|
176
|
+
uri = uri.clone
|
177
|
+
uri.path = uri.path.sub(/\/[^\/]*\z/, '/')
|
178
|
+
uri
|
179
|
+
end
|
180
|
+
module_function :uri_dirname
|
181
|
+
|
182
|
+
# Finds a value of a Hash.
|
183
|
+
def hash_find_value(hash, &block)
|
184
|
+
v = hash.find(&block)
|
185
|
+
v ? v[1] : nil
|
186
|
+
end
|
187
|
+
module_function :hash_find_value
|
188
|
+
|
189
|
+
# Try to require a feature and returns true/false if loaded
|
190
|
+
#
|
191
|
+
# It returns 'true' for the second require in contrast of the standard
|
192
|
+
# require returns false if the feature is already loaded.
|
193
|
+
def try_require(feature)
|
194
|
+
require feature
|
195
|
+
true
|
196
|
+
rescue LoadError
|
197
|
+
false
|
198
|
+
end
|
199
|
+
module_function :try_require
|
200
|
+
|
201
|
+
# show one warning message only once by caching message
|
202
|
+
#
|
203
|
+
# it cached all messages in memory so be careful not to show many kinds of warning message.
|
204
|
+
@@__warned = {}
|
205
|
+
def warning(message)
|
206
|
+
return if @@__warned.key?(message)
|
207
|
+
warn(message)
|
208
|
+
@@__warned[message] = true
|
209
|
+
end
|
210
|
+
|
211
|
+
# Checks if the given URI is https.
|
212
|
+
def https?(uri)
|
213
|
+
uri.scheme && uri.scheme.downcase == 'https'
|
214
|
+
end
|
215
|
+
|
216
|
+
def http?(uri)
|
217
|
+
uri.scheme && uri.scheme.downcase == 'http'
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
|
222
|
+
end
|