stella 0.7.0.004 → 0.7.0.005
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/bin/stella +16 -20
- data/examples/essentials/logo.png +0 -0
- data/examples/{basic → essentials}/plan.rb +7 -3
- data/examples/{basic → essentials}/search_terms.csv +0 -0
- data/examples/example_webapp.rb +7 -4
- data/examples/example_webapp.ru +3 -0
- data/lib/stella.rb +18 -26
- data/lib/stella/cli.rb +4 -1
- data/lib/stella/client.rb +49 -26
- data/lib/stella/data.rb +35 -9
- data/lib/stella/data/http.rb +1 -1
- data/lib/stella/data/http/request.rb +3 -14
- data/lib/stella/engine.rb +10 -4
- data/lib/stella/engine/functional.rb +2 -4
- data/lib/stella/engine/load.rb +24 -21
- data/lib/stella/mixins.rb +1 -1
- data/lib/stella/stats.rb +17 -4
- data/lib/stella/testplan/usecase.rb +2 -2
- data/lib/stella/utils.rb +16 -1
- data/lib/stella/version.rb +1 -1
- data/stella.gemspec +17 -4
- data/vendor/httpclient-2.1.5.2/httpclient.rb +1025 -0
- data/vendor/httpclient-2.1.5.2/httpclient/auth.rb +522 -0
- data/vendor/httpclient-2.1.5.2/httpclient/cacert.p7s +1579 -0
- data/vendor/httpclient-2.1.5.2/httpclient/cacert_sha1.p7s +1579 -0
- data/vendor/httpclient-2.1.5.2/httpclient/connection.rb +84 -0
- data/vendor/httpclient-2.1.5.2/httpclient/cookie.rb +562 -0
- data/vendor/httpclient-2.1.5.2/httpclient/http.rb +867 -0
- data/vendor/httpclient-2.1.5.2/httpclient/session.rb +864 -0
- data/vendor/httpclient-2.1.5.2/httpclient/ssl_config.rb +417 -0
- data/vendor/httpclient-2.1.5.2/httpclient/stats.rb +90 -0
- data/vendor/httpclient-2.1.5.2/httpclient/timeout.rb +136 -0
- data/vendor/httpclient-2.1.5.2/httpclient/util.rb +86 -0
- metadata +18 -5
- data/lib/stella/dsl.rb +0 -5
@@ -0,0 +1,417 @@
|
|
1
|
+
# HTTPClient - HTTP client library.
|
2
|
+
# Copyright (C) 2000-2009 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
|
+
class HTTPClient
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'openssl'
|
13
|
+
SSLEnabled = true
|
14
|
+
rescue LoadError
|
15
|
+
SSLEnabled = false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Represents SSL configuration for HTTPClient instance.
|
19
|
+
# The implementation depends on OpenSSL.
|
20
|
+
#
|
21
|
+
# == Trust Anchor Control
|
22
|
+
#
|
23
|
+
# SSLConfig loads 'httpclient/cacert.p7s' as a trust anchor
|
24
|
+
# (trusted certificate(s)) with set_trust_ca in initialization time.
|
25
|
+
# This means that HTTPClient instance trusts some CA certificates by default,
|
26
|
+
# like Web browsers. 'httpclient/cacert.p7s' is created by the author and
|
27
|
+
# included in released package.
|
28
|
+
#
|
29
|
+
# 'cacert.p7s' is automatically generated from JDK 1.6.
|
30
|
+
#
|
31
|
+
# You may want to change trust anchor by yourself. Call clear_cert_store
|
32
|
+
# then set_trust_ca for that purpose.
|
33
|
+
class SSLConfig
|
34
|
+
include OpenSSL if SSLEnabled
|
35
|
+
|
36
|
+
# OpenSSL::X509::Certificate:: certificate for SSL client authenticateion.
|
37
|
+
# nil by default. (no client authenticateion)
|
38
|
+
attr_reader :client_cert
|
39
|
+
# OpenSSL::PKey::PKey:: private key for SSL client authentication.
|
40
|
+
# nil by default. (no client authenticateion)
|
41
|
+
attr_reader :client_key
|
42
|
+
|
43
|
+
# A number which represents OpenSSL's verify mode. Default value is
|
44
|
+
# OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT.
|
45
|
+
attr_reader :verify_mode
|
46
|
+
# A number of verify depth. Certification path which length is longer than
|
47
|
+
# this depth is not allowed.
|
48
|
+
attr_reader :verify_depth
|
49
|
+
# A callback handler for custom certificate verification. nil by default.
|
50
|
+
# If the handler is set, handler.call is invoked just after general
|
51
|
+
# OpenSSL's verification. handler.call is invoked with 2 arguments,
|
52
|
+
# ok and ctx; ok is a result of general OpenSSL's verification. ctx is a
|
53
|
+
# OpenSSL::X509::StoreContext.
|
54
|
+
attr_reader :verify_callback
|
55
|
+
# SSL timeout in sec. nil by default.
|
56
|
+
attr_reader :timeout
|
57
|
+
# A number of OpenSSL's SSL options. Default value is
|
58
|
+
# OpenSSL::SSL::OP_ALL | OpenSSL::SSL::OP_NO_SSLv2
|
59
|
+
attr_reader :options
|
60
|
+
# A String of OpenSSL's cipher configuration. Default value is
|
61
|
+
# ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH
|
62
|
+
# See ciphers(1) man in OpenSSL for more detail.
|
63
|
+
attr_reader :ciphers
|
64
|
+
|
65
|
+
# OpenSSL::X509::X509::Store used for verification. You can reset the
|
66
|
+
# store with clear_cert_store and set the new store with cert_store=.
|
67
|
+
attr_reader :cert_store # don't use if you don't know what it is.
|
68
|
+
|
69
|
+
# For server side configuration. Ignore this.
|
70
|
+
attr_reader :client_ca # :nodoc:
|
71
|
+
|
72
|
+
# Creates a SSLConfig.
|
73
|
+
def initialize(client)
|
74
|
+
return unless SSLEnabled
|
75
|
+
@client = client
|
76
|
+
@cert_store = X509::Store.new
|
77
|
+
@client_cert = @client_key = @client_ca = nil
|
78
|
+
@verify_mode = SSL::VERIFY_PEER | SSL::VERIFY_FAIL_IF_NO_PEER_CERT
|
79
|
+
@verify_depth = nil
|
80
|
+
@verify_callback = nil
|
81
|
+
@dest = nil
|
82
|
+
@timeout = nil
|
83
|
+
@options = defined?(SSL::OP_ALL) ? SSL::OP_ALL | SSL::OP_NO_SSLv2 : nil
|
84
|
+
@ciphers = "ALL:!ADH:!LOW:!EXP:!MD5:+SSLv2:@STRENGTH"
|
85
|
+
load_cacerts
|
86
|
+
end
|
87
|
+
|
88
|
+
# Sets certificate (OpenSSL::X509::Certificate) for SSL client
|
89
|
+
# authentication.
|
90
|
+
# client_key and client_cert must be a pair.
|
91
|
+
#
|
92
|
+
# Calling this method resets all existing sessions.
|
93
|
+
def client_cert=(client_cert)
|
94
|
+
@client_cert = client_cert
|
95
|
+
change_notify
|
96
|
+
end
|
97
|
+
|
98
|
+
# Sets private key (OpenSSL::PKey::PKey) for SSL client authentication.
|
99
|
+
# client_key and client_cert must be a pair.
|
100
|
+
#
|
101
|
+
# Calling this method resets all existing sessions.
|
102
|
+
def client_key=(client_key)
|
103
|
+
@client_key = client_key
|
104
|
+
change_notify
|
105
|
+
end
|
106
|
+
|
107
|
+
# Sets certificate and private key for SSL client authentication.
|
108
|
+
# cert_file:: must be a filename of PEM/DER formatted file.
|
109
|
+
# key_file:: must be a filename of PEM/DER formatted file. Key must be an
|
110
|
+
# RSA key. If you want to use other PKey algorithm,
|
111
|
+
# use client_key=.
|
112
|
+
#
|
113
|
+
# Calling this method resets all existing sessions.
|
114
|
+
def set_client_cert_file(cert_file, key_file)
|
115
|
+
@client_cert = X509::Certificate.new(File.open(cert_file).read)
|
116
|
+
@client_key = PKey::RSA.new(File.open(key_file).read)
|
117
|
+
change_notify
|
118
|
+
end
|
119
|
+
|
120
|
+
# Drops current certificate store (OpenSSL::X509::Store) for SSL and create
|
121
|
+
# new one for the next session.
|
122
|
+
#
|
123
|
+
# Calling this method resets all existing sessions.
|
124
|
+
def clear_cert_store
|
125
|
+
@cert_store = X509::Store.new
|
126
|
+
change_notify
|
127
|
+
end
|
128
|
+
|
129
|
+
# Sets new certificate store (OpenSSL::X509::Store).
|
130
|
+
# don't use if you don't know what it is.
|
131
|
+
#
|
132
|
+
# Calling this method resets all existing sessions.
|
133
|
+
def cert_store=(cert_store)
|
134
|
+
@cert_store = cert_store
|
135
|
+
change_notify
|
136
|
+
end
|
137
|
+
|
138
|
+
# Sets trust anchor certificate(s) for verification.
|
139
|
+
# trust_ca_file_or_hashed_dir:: a filename of a PEM/DER formatted
|
140
|
+
# OpenSSL::X509::Certificate or
|
141
|
+
# a 'c-rehash'eddirectory name which stores
|
142
|
+
# trusted certificate files.
|
143
|
+
#
|
144
|
+
# Calling this method resets all existing sessions.
|
145
|
+
def set_trust_ca(trust_ca_file_or_hashed_dir)
|
146
|
+
if FileTest.directory?(trust_ca_file_or_hashed_dir)
|
147
|
+
@cert_store.add_path(trust_ca_file_or_hashed_dir)
|
148
|
+
else
|
149
|
+
@cert_store.add_file(trust_ca_file_or_hashed_dir)
|
150
|
+
end
|
151
|
+
change_notify
|
152
|
+
end
|
153
|
+
|
154
|
+
# Adds CRL for verification.
|
155
|
+
# crl:: a OpenSSL::X509::CRL or a filename of a PEM/DER formatted
|
156
|
+
# OpenSSL::X509::CRL.
|
157
|
+
#
|
158
|
+
# Calling this method resets all existing sessions.
|
159
|
+
def set_crl(crl)
|
160
|
+
unless crl.is_a?(X509::CRL)
|
161
|
+
crl = X509::CRL.new(File.open(crl).read)
|
162
|
+
end
|
163
|
+
@cert_store.add_crl(crl)
|
164
|
+
@cert_store.flags = X509::V_FLAG_CRL_CHECK | X509::V_FLAG_CRL_CHECK_ALL
|
165
|
+
change_notify
|
166
|
+
end
|
167
|
+
|
168
|
+
# Sets verify mode of OpenSSL. New value must be a combination of
|
169
|
+
# constants OpenSSL::SSL::VERIFY_*
|
170
|
+
#
|
171
|
+
# Calling this method resets all existing sessions.
|
172
|
+
def verify_mode=(verify_mode)
|
173
|
+
@verify_mode = verify_mode
|
174
|
+
change_notify
|
175
|
+
end
|
176
|
+
|
177
|
+
# Sets verify depth. New value must be a number.
|
178
|
+
#
|
179
|
+
# Calling this method resets all existing sessions.
|
180
|
+
def verify_depth=(verify_depth)
|
181
|
+
@verify_depth = verify_depth
|
182
|
+
change_notify
|
183
|
+
end
|
184
|
+
|
185
|
+
# Sets callback handler for custom certificate verification.
|
186
|
+
# See verify_callback.
|
187
|
+
#
|
188
|
+
# Calling this method resets all existing sessions.
|
189
|
+
def verify_callback=(verify_callback)
|
190
|
+
@verify_callback = verify_callback
|
191
|
+
change_notify
|
192
|
+
end
|
193
|
+
|
194
|
+
# Sets SSL timeout in sec.
|
195
|
+
#
|
196
|
+
# Calling this method resets all existing sessions.
|
197
|
+
def timeout=(timeout)
|
198
|
+
@timeout = timeout
|
199
|
+
change_notify
|
200
|
+
end
|
201
|
+
|
202
|
+
# Sets SSL options. New value must be a combination of # constants
|
203
|
+
# OpenSSL::SSL::OP_*
|
204
|
+
#
|
205
|
+
# Calling this method resets all existing sessions.
|
206
|
+
def options=(options)
|
207
|
+
@options = options
|
208
|
+
change_notify
|
209
|
+
end
|
210
|
+
|
211
|
+
# Sets cipher configuration. New value must be a String.
|
212
|
+
#
|
213
|
+
# Calling this method resets all existing sessions.
|
214
|
+
def ciphers=(ciphers)
|
215
|
+
@ciphers = ciphers
|
216
|
+
change_notify
|
217
|
+
end
|
218
|
+
|
219
|
+
def client_ca=(client_ca) # :nodoc:
|
220
|
+
@client_ca = client_ca
|
221
|
+
change_notify
|
222
|
+
end
|
223
|
+
|
224
|
+
# interfaces for SSLSocketWrap.
|
225
|
+
def set_context(ctx) # :nodoc:
|
226
|
+
# Verification: Use Store#verify_callback instead of SSLContext#verify*?
|
227
|
+
ctx.cert_store = @cert_store
|
228
|
+
ctx.verify_mode = @verify_mode
|
229
|
+
ctx.verify_depth = @verify_depth if @verify_depth
|
230
|
+
ctx.verify_callback = @verify_callback || method(:default_verify_callback)
|
231
|
+
# SSL config
|
232
|
+
ctx.cert = @client_cert
|
233
|
+
ctx.key = @client_key
|
234
|
+
ctx.client_ca = @client_ca
|
235
|
+
ctx.timeout = @timeout
|
236
|
+
ctx.options = @options
|
237
|
+
ctx.ciphers = @ciphers
|
238
|
+
end
|
239
|
+
|
240
|
+
# post connection check proc for ruby < 1.8.5.
|
241
|
+
# this definition must match with the one in ext/openssl/lib/openssl/ssl.rb
|
242
|
+
def post_connection_check(peer_cert, hostname) # :nodoc:
|
243
|
+
check_common_name = true
|
244
|
+
cert = peer_cert
|
245
|
+
cert.extensions.each{|ext|
|
246
|
+
next if ext.oid != "subjectAltName"
|
247
|
+
ext.value.split(/,\s+/).each{|general_name|
|
248
|
+
if /\ADNS:(.*)/ =~ general_name
|
249
|
+
check_common_name = false
|
250
|
+
reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+")
|
251
|
+
return true if /\A#{reg}\z/i =~ hostname
|
252
|
+
elsif /\AIP Address:(.*)/ =~ general_name
|
253
|
+
check_common_name = false
|
254
|
+
return true if $1 == hostname
|
255
|
+
end
|
256
|
+
}
|
257
|
+
}
|
258
|
+
if check_common_name
|
259
|
+
cert.subject.to_a.each{|oid, value|
|
260
|
+
if oid == "CN"
|
261
|
+
reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+")
|
262
|
+
return true if /\A#{reg}\z/i =~ hostname
|
263
|
+
end
|
264
|
+
}
|
265
|
+
end
|
266
|
+
raise SSL::SSLError, "hostname was not match with the server certificate"
|
267
|
+
end
|
268
|
+
|
269
|
+
# Default callback for verification: only dumps error.
|
270
|
+
def default_verify_callback(is_ok, ctx)
|
271
|
+
if $DEBUG
|
272
|
+
puts "#{ is_ok ? 'ok' : 'ng' }: #{ctx.current_cert.subject}"
|
273
|
+
end
|
274
|
+
if !is_ok
|
275
|
+
depth = ctx.error_depth
|
276
|
+
code = ctx.error
|
277
|
+
msg = ctx.error_string
|
278
|
+
STDERR.puts "at depth #{depth} - #{code}: #{msg}"
|
279
|
+
end
|
280
|
+
is_ok
|
281
|
+
end
|
282
|
+
|
283
|
+
# Sample callback method: CAUTION: does not check CRL/ARL.
|
284
|
+
def sample_verify_callback(is_ok, ctx)
|
285
|
+
unless is_ok
|
286
|
+
depth = ctx.error_depth
|
287
|
+
code = ctx.error
|
288
|
+
msg = ctx.error_string
|
289
|
+
STDERR.puts "at depth #{depth} - #{code}: #{msg}" if $DEBUG
|
290
|
+
return false
|
291
|
+
end
|
292
|
+
|
293
|
+
cert = ctx.current_cert
|
294
|
+
self_signed = false
|
295
|
+
ca = false
|
296
|
+
pathlen = nil
|
297
|
+
server_auth = true
|
298
|
+
self_signed = (cert.subject.cmp(cert.issuer) == 0)
|
299
|
+
|
300
|
+
# Check extensions whatever its criticality is. (sample)
|
301
|
+
cert.extensions.each do |ex|
|
302
|
+
case ex.oid
|
303
|
+
when 'basicConstraints'
|
304
|
+
/CA:(TRUE|FALSE), pathlen:(\d+)/ =~ ex.value
|
305
|
+
ca = ($1 == 'TRUE')
|
306
|
+
pathlen = $2.to_i
|
307
|
+
when 'keyUsage'
|
308
|
+
usage = ex.value.split(/\s*,\s*/)
|
309
|
+
ca = usage.include?('Certificate Sign')
|
310
|
+
server_auth = usage.include?('Key Encipherment')
|
311
|
+
when 'extendedKeyUsage'
|
312
|
+
usage = ex.value.split(/\s*,\s*/)
|
313
|
+
server_auth = usage.include?('Netscape Server Gated Crypto')
|
314
|
+
when 'nsCertType'
|
315
|
+
usage = ex.value.split(/\s*,\s*/)
|
316
|
+
ca = usage.include?('SSL CA')
|
317
|
+
server_auth = usage.include?('SSL Server')
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
if self_signed
|
322
|
+
STDERR.puts 'self signing CA' if $DEBUG
|
323
|
+
return true
|
324
|
+
elsif ca
|
325
|
+
STDERR.puts 'middle level CA' if $DEBUG
|
326
|
+
return true
|
327
|
+
elsif server_auth
|
328
|
+
STDERR.puts 'for server authentication' if $DEBUG
|
329
|
+
return true
|
330
|
+
end
|
331
|
+
|
332
|
+
return false
|
333
|
+
end
|
334
|
+
|
335
|
+
private
|
336
|
+
|
337
|
+
def change_notify
|
338
|
+
@client.reset_all
|
339
|
+
end
|
340
|
+
|
341
|
+
def load_cacerts
|
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
|
356
|
+
end
|
357
|
+
end
|
358
|
+
STDERR.puts("cacerts loading failed")
|
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__
|
414
|
+
end
|
415
|
+
|
416
|
+
|
417
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
|
2
|
+
class HTTPClient
|
3
|
+
|
4
|
+
# Based on Mongrel::Stats, Copyright (c) 2005 Zed A. Shaw
|
5
|
+
class Stats
|
6
|
+
|
7
|
+
attr_reader :sum, :sumsq, :n, :min, :max
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
reset
|
11
|
+
end
|
12
|
+
|
13
|
+
def +(obj)
|
14
|
+
puts obj.class
|
15
|
+
end
|
16
|
+
|
17
|
+
# Resets the internal counters so you can start sampling again.
|
18
|
+
def reset
|
19
|
+
@n, @sum, @sumsq = 0.0, 0.0, 0.0
|
20
|
+
@last_time = Time.new
|
21
|
+
@min, @max = 0.0, 0.0
|
22
|
+
end
|
23
|
+
|
24
|
+
# Adds a sampling to the calculations.
|
25
|
+
def sample(s)
|
26
|
+
@sum += s
|
27
|
+
@sumsq += s * s
|
28
|
+
if @n == 0
|
29
|
+
@min = @max = s
|
30
|
+
else
|
31
|
+
@min = s if @min > s
|
32
|
+
@max = s if @max < s
|
33
|
+
end
|
34
|
+
@n+=1
|
35
|
+
end
|
36
|
+
|
37
|
+
# Dump this Stats object with an optional additional message.
|
38
|
+
def dump(msg = "", out=STDERR)
|
39
|
+
out.puts "#{msg}: #{self.to_s}"
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a common display (used by dump)
|
43
|
+
def to_s
|
44
|
+
"[#{@name}]: SUM=%0.4f, SUMSQ=%0.4f, N=%0.4f, MEAN=%0.4f, SD=%0.4f, MIN=%0.4f, MAX=%0.4f" % [@sum, @sumsq, @n, mean, sd, @min, @max]
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# Calculates and returns the mean for the data passed so far.
|
49
|
+
def mean
|
50
|
+
@sum / @n
|
51
|
+
end
|
52
|
+
|
53
|
+
# Calculates the standard deviation of the data so far.
|
54
|
+
def sd
|
55
|
+
return 0.0 if @n <= 1
|
56
|
+
# (sqrt( ((s).sumsq - ( (s).sum * (s).sum / (s).n)) / ((s).n-1) ))
|
57
|
+
begin
|
58
|
+
return Math.sqrt( (@sumsq - ( @sum * @sum / @n)) / (@n-1) )
|
59
|
+
rescue Errno::EDOM
|
60
|
+
return 0.0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# Adds a time delta between now and the last time you called this. This
|
66
|
+
# will give you the average time between two activities.
|
67
|
+
#
|
68
|
+
# An example is:
|
69
|
+
#
|
70
|
+
# t = Stats.new("do_stuff")
|
71
|
+
# 10000.times { do_stuff(); t.tick }
|
72
|
+
# t.dump("time")
|
73
|
+
#
|
74
|
+
def tick
|
75
|
+
now = Time.now
|
76
|
+
sample(now - @last_time)
|
77
|
+
@last_time = now
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Timer
|
82
|
+
attr_reader :initialized
|
83
|
+
attr_reader :stats
|
84
|
+
def initialized
|
85
|
+
@initialized = Time.now
|
86
|
+
@stats = Stats.new
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|