right_support 2.11.3 → 2.12.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +4 -0
- data/VERSION +1 -1
- data/lib/right_support/notifiers/airbrake.rb +194 -0
- data/lib/right_support/notifiers/base.rb +73 -0
- data/lib/right_support/notifiers/blacklisters/base.rb +48 -0
- data/lib/right_support/notifiers/blacklisters/canonical.rb +60 -0
- data/lib/right_support/notifiers/blacklisters/regular_expression.rb +86 -0
- data/{features/support/file_utils_bundler_mixin.rb → lib/right_support/notifiers/blacklisters/simple.rb} +21 -20
- data/lib/right_support/notifiers/blacklisters/snake_case.rb +60 -0
- data/lib/right_support/notifiers/blacklisters/wildcard.rb +65 -0
- data/lib/right_support/notifiers/blacklisters.rb +34 -0
- data/lib/right_support/notifiers/logger.rb +94 -0
- data/lib/right_support/notifiers/notification.rb +57 -0
- data/lib/right_support/notifiers/utilities/backtrace_decoder.rb +234 -0
- data/lib/right_support/notifiers/utilities.rb +29 -0
- data/lib/right_support/notifiers.rb +32 -0
- data/lib/right_support/rack/request_logger.rb +13 -9
- data/lib/right_support.rb +1 -0
- data/right_support.gemspec +19 -70
- metadata +17 -69
- data/.coveralls.yml +0 -2
- data/.rspec +0 -3
- data/.simplecov +0 -6
- data/.travis.yml +0 -13
- data/Gemfile +0 -51
- data/Gemfile.lock +0 -153
- data/features/balancer_error_handling.feature +0 -34
- data/features/balancer_health_check.feature +0 -33
- data/features/hash_tools.feature +0 -27
- data/features/http_client_timeout.feature +0 -19
- data/features/serialization.feature +0 -113
- data/features/step_definitions/hash_tools_steps.rb +0 -41
- data/features/step_definitions/http_client_steps.rb +0 -27
- data/features/step_definitions/request_balancer_steps.rb +0 -93
- data/features/step_definitions/ruby_steps.rb +0 -176
- data/features/step_definitions/serialization_steps.rb +0 -133
- data/features/step_definitions/server_steps.rb +0 -134
- data/features/support/env.rb +0 -148
- data/right_support.rconf +0 -9
- data/spec/config/feature_set_spec.rb +0 -83
- data/spec/crypto/signed_hash_spec.rb +0 -73
- data/spec/data/hash_tools_spec.rb +0 -602
- data/spec/data/mash_spec.rb +0 -313
- data/spec/data/token_spec.rb +0 -21
- data/spec/data/uuid_spec.rb +0 -45
- data/spec/db/cassandra_model_part1_spec.rb +0 -84
- data/spec/db/cassandra_model_part2_spec.rb +0 -73
- data/spec/db/cassandra_model_spec.rb +0 -375
- data/spec/fixtures/encrypted_priv_rsa.pem +0 -30
- data/spec/fixtures/good_priv_dsa.pem +0 -12
- data/spec/fixtures/good_priv_rsa.pem +0 -15
- data/spec/fixtures/good_pub_dsa.ssh +0 -1
- data/spec/fixtures/good_pub_rsa.pem +0 -5
- data/spec/fixtures/good_pub_rsa.ssh +0 -1
- data/spec/log/exception_logger_spec.rb +0 -76
- data/spec/log/filter_logger_spec.rb +0 -66
- data/spec/log/mixin_spec.rb +0 -141
- data/spec/log/multiplexer_spec.rb +0 -54
- data/spec/log/null_logger_spec.rb +0 -36
- data/spec/log/step_level_logger_spec.rb +0 -49
- data/spec/log/system_logger_spec.rb +0 -172
- data/spec/net/address_helper_spec.rb +0 -57
- data/spec/net/dns_spec.rb +0 -187
- data/spec/net/http_client_spec.rb +0 -181
- data/spec/net/lb/health_check_spec.rb +0 -417
- data/spec/net/lb/round_robin_spec.rb +0 -15
- data/spec/net/lb/sticky_spec.rb +0 -92
- data/spec/net/request_balancer_spec.rb +0 -690
- data/spec/net/s3_helper_spec.rb +0 -160
- data/spec/net/ssl_spec.rb +0 -42
- data/spec/net/string_encoder_spec.rb +0 -58
- data/spec/rack/log_setter_spec.rb +0 -5
- data/spec/rack/request_logger_spec.rb +0 -225
- data/spec/rack/request_tracker_spec.rb +0 -115
- data/spec/rack/runtime_spec.rb +0 -49
- data/spec/ruby/easy_singleton_spec.rb +0 -72
- data/spec/ruby/object_extensions_spec.rb +0 -27
- data/spec/ruby/string_extensions_spec.rb +0 -98
- data/spec/spec_helper.rb +0 -188
- data/spec/stats/activity_spec.rb +0 -425
- data/spec/stats/exceptions_spec.rb +0 -247
- data/spec/stats/helpers_spec.rb +0 -685
- data/spec/validation/openssl_spec.rb +0 -37
- data/spec/validation/ssh_spec.rb +0 -39
data/spec/net/s3_helper_spec.rb
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe RightSupport::Net::S3Helper do
|
4
|
-
|
5
|
-
def digest
|
6
|
-
OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, passphrase, @valid_params[:data])
|
7
|
-
end
|
8
|
-
|
9
|
-
def ciphertext
|
10
|
-
"\203\346\271\273\323\377r\246\002\204\231\374h\327!\323"
|
11
|
-
end
|
12
|
-
|
13
|
-
def passphrase
|
14
|
-
"#{@valid_params[:key]}:key"
|
15
|
-
end
|
16
|
-
|
17
|
-
before(:each) do
|
18
|
-
@valid_params = { :key => "foo", :data => "bar" }
|
19
|
-
|
20
|
-
# Mock right_aws config & objects with reasonable default behavior
|
21
|
-
@s3_config = {'creds' =>
|
22
|
-
{'aws_access_key_id' => 'knock_knock',
|
23
|
-
'aws_secret_access_key' => 'open_sesame'},
|
24
|
-
'bucket_name' => 'my_own_personal_bucket',
|
25
|
-
'master_secret' => 'if i told you i would have to kill you'}
|
26
|
-
@s3_class = flexmock("s3")
|
27
|
-
@s3_object = flexmock("s3_object")
|
28
|
-
@s3_bucket = flexmock("s3_bucket")
|
29
|
-
@s3_class.should_receive(:new).with(String, String, Hash).and_return(@s3_object)
|
30
|
-
@s3_object.should_receive(:bucket).with('my_own_personal_bucket').and_return(@s3_bucket).by_default
|
31
|
-
@s3_bucket.should_receive(:key).and_return(@s3_object).by_default
|
32
|
-
@s3_bucket.should_receive(:put).with(String, String, Hash).and_return(true).by_default
|
33
|
-
|
34
|
-
@s3_object.should_receive(:meta_headers).and_return({"digest" => digest})
|
35
|
-
@s3_object.should_receive(:data).and_return(ciphertext)
|
36
|
-
|
37
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:s3_enabled?).and_return(:true)
|
38
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:master_secret).and_return('key')
|
39
|
-
|
40
|
-
@encrypt = flexmock("encrypt")
|
41
|
-
@encrypt.should_receive(:encrypt).with(String, String, Hash).and_return(ciphertext)
|
42
|
-
@encrypt.should_receive(:encrypt).with(Hash).and_return(ciphertext)
|
43
|
-
@encrypt.should_receive(:decrypt).with(Hash).and_return(@valid_params[:data])
|
44
|
-
end
|
45
|
-
|
46
|
-
context :init do
|
47
|
-
context "when all params are valid" do
|
48
|
-
it "succeeds" do
|
49
|
-
RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt).should be_true
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when bucket does not exist" do
|
54
|
-
before(:each) do
|
55
|
-
@bad_s3_config = @s3_config.clone
|
56
|
-
@bad_s3_config['bucket_name'] = "supercallifragilisticexpialidocious"
|
57
|
-
@s3_object.should_receive(:bucket).with("supercallifragilisticexpialidocious").and_return(nil)
|
58
|
-
end
|
59
|
-
|
60
|
-
it "raises BucketNotFound" do
|
61
|
-
lambda {
|
62
|
-
RightSupport::Net::S3Helper.init(@bad_s3_config, @s3_class, @encrypt)
|
63
|
-
}.should raise_error(RightSupport::Net::S3Helper::BucketNotFound)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context :get do
|
69
|
-
before(:each) do
|
70
|
-
RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt)
|
71
|
-
end
|
72
|
-
|
73
|
-
context "with valid params" do
|
74
|
-
it 'returns plaintext' do
|
75
|
-
RightSupport::Net::S3Helper.get(@valid_params[:key]).should be_eql(@valid_params[:data])
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context :post do
|
81
|
-
before(:each) do
|
82
|
-
RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt)
|
83
|
-
end
|
84
|
-
|
85
|
-
context "with valid params" do
|
86
|
-
it 'encrypts and saves data' do
|
87
|
-
@s3_bucket.should_receive(:put).with(@valid_params[:key], ciphertext, {"digest" => digest}).and_return(true)
|
88
|
-
RightSupport::Net::S3Helper.post(@valid_params[:key], @valid_params[:data]).should be_true
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
context :health_check do
|
94
|
-
before(:each) do
|
95
|
-
RightSupport::Net::S3Helper.init(@s3_config, @s3_class, @encrypt)
|
96
|
-
end
|
97
|
-
|
98
|
-
context 'with invalid configuration' do
|
99
|
-
before :each do
|
100
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:config).and_return({'creds' => {'aws_access_key_id' => '@@AWS_ACCESS_KEY_ID@@', 'aws_secret_access_key' => '@@AWS_SECRET_ACCESS_KEY@@'}, 'bucket_name' => '@@s3_bucket_NAME@@', 'master_secret' => '@@MASTER_SECRET@@'})
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'return error' do
|
104
|
-
RightSupport::Net::S3Helper.health_check.class.should == String
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
context 'with valid configuration but invalid s3 connection credentials' do
|
109
|
-
before :each do
|
110
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:config).and_return({'creds' => {'aws_access_key_id' => 'AWS_ACCESS_KEY_ID', 'aws_secret_access_key' => 'AWS_SECRET_ACCESS_KEY'}, 'bucket_name' => 'BUCKET_NAME', 'master_secret' => 'MASTER_SECRET'})
|
111
|
-
end
|
112
|
-
|
113
|
-
it 'returns error ' do
|
114
|
-
RightSupport::Net::S3Helper.health_check.class.should == String
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context 'with valid configuration and s3 connection' do
|
119
|
-
before :each do
|
120
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:config).and_return({'creds' => {'aws_access_key_id' => 'dsfgdsfgdsfgdsfg', 'aws_secret_access_key' => 'sdghdhsdg'}, 'bucket_name' => 'dshdshdfgh', 'master_secret' => 'dshdshg'})
|
121
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:post).with('ping', 'heath check').and_return(true)
|
122
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:get).with('ping').and_return('heath check')
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'returns ok' do
|
126
|
-
RightSupport::Net::S3Helper.health_check.should == true
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
context 'test/development environment' do
|
132
|
-
|
133
|
-
before :each do
|
134
|
-
@key1 = 'aws_access_key_id'
|
135
|
-
@key2 = 'aws_secret_access_key'
|
136
|
-
@opt_with_no_subdomains = {:no_subdomains => true}
|
137
|
-
@opt_without_subdoamins = {}
|
138
|
-
@config = {}
|
139
|
-
@config["creds"] = {}
|
140
|
-
@config["creds"]["aws_access_key_id"] = @key1
|
141
|
-
@config["creds"]["aws_secret_access_key"] = @key2
|
142
|
-
@s3_class = flexmock('Rightscale::S3')
|
143
|
-
flexmock(RightSupport::Net::S3Helper).should_receive(:bucket).and_return(true)
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'works ok with :no_subdomains' do
|
147
|
-
@s3_class.should_receive(:new).with(@key1, @key2, @opt_with_no_subdomains)
|
148
|
-
RightSupport::Net::S3Helper.init(@config, @s3_class, @s3_class, :no_subdomains => true)
|
149
|
-
RightSupport::Net::S3Helper.s3
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'works ok without subdomains' do
|
153
|
-
@s3_class.should_receive(:new).with(@key1, @key2, @opt_without_subdoamins)
|
154
|
-
RightSupport::Net::S3Helper.init(@config, @s3_class, @s3_class)
|
155
|
-
RightSupport::Net::S3Helper.s3
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
159
|
-
|
160
|
-
end
|
data/spec/net/ssl_spec.rb
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RightSupport::Net::SSL do
|
4
|
-
PATCH = RightSupport::Net::SSL::OpenSSLPatch
|
5
|
-
|
6
|
-
context :with_expected_hostname do
|
7
|
-
before(:all) do
|
8
|
-
PATCH.enable!
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'works' do
|
12
|
-
OpenSSL::SSL.should respond_to(:verify_certificate_identity_without_hack)
|
13
|
-
PATCH.enabled?.should be_true
|
14
|
-
|
15
|
-
cert = flexmock('SSL certificate')
|
16
|
-
|
17
|
-
flexmock(OpenSSL::SSL).
|
18
|
-
should_receive(:verify_certificate_identity_without_hack).
|
19
|
-
with(cert, 'reposeX.rightscale.com').and_return(true)
|
20
|
-
RightSupport::Net::SSL.with_expected_hostname('reposeX.rightscale.com') do
|
21
|
-
OpenSSL::SSL.verify_certificate_identity(cert, '1.2.3.4').should be_true
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
context 'with disabled monkey-patch' do
|
26
|
-
before(:all) do
|
27
|
-
PATCH.disable!
|
28
|
-
end
|
29
|
-
it 'does not work' do
|
30
|
-
PATCH.enabled?.should be_false
|
31
|
-
cert = flexmock('SSL certificate')
|
32
|
-
flexmock(OpenSSL::SSL).
|
33
|
-
should_receive(:verify_certificate_identity_without_hack).
|
34
|
-
with(cert, '1.2.3.4').and_return(false)
|
35
|
-
|
36
|
-
RightSupport::Net::SSL.with_expected_hostname('reposeX.rightscale.com') do
|
37
|
-
OpenSSL::SSL.verify_certificate_identity(cert, '1.2.3.4').should be_false
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
@@ -1,58 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'cgi'
|
3
|
-
|
4
|
-
describe RightSupport::Net::StringEncoder do
|
5
|
-
#Alias for brevity's sake
|
6
|
-
ENCODINGS = RightSupport::Net::StringEncoder::ENCODINGS
|
7
|
-
|
8
|
-
before(:all) do
|
9
|
-
#Generate some random binary test vectors with varying
|
10
|
-
#lengths, 2-1024 bytes
|
11
|
-
@strings = []
|
12
|
-
(1..10).each do |i|
|
13
|
-
s = ''
|
14
|
-
i.times { s << rand(256) }
|
15
|
-
|
16
|
-
if RUBY_VERSION >= '1.9'
|
17
|
-
@strings << s.force_encoding(Encoding::ASCII_8BIT)
|
18
|
-
else
|
19
|
-
@strings << s
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context :initialize do
|
25
|
-
it 'accepts a glob of encodings' do
|
26
|
-
obj = RightSupport::Net::StringEncoder.new(:base64, :url)
|
27
|
-
obj.decode(obj.encode('moo')).should == 'moo'
|
28
|
-
end
|
29
|
-
|
30
|
-
it 'accepts an Array of encodings' do
|
31
|
-
obj = RightSupport::Net::StringEncoder.new([:base64, :url])
|
32
|
-
obj.decode(obj.encode('moo')).should == 'moo'
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'when unknown encodings are specified' do
|
36
|
-
it 'raises ArgumentError' do
|
37
|
-
lambda do
|
38
|
-
RightSupport::Net::StringEncoder.new(:xyzzy, :foobar)
|
39
|
-
end.should raise_error(ArgumentError)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
#Ensure that encodings are symmetrical and commutative by testing round-trip
|
45
|
-
#for all combinations.
|
46
|
-
(1..ENCODINGS.length).each do |n|
|
47
|
-
context "when using any #{n} encoding#{n > 1 ? 's' : ''}" do
|
48
|
-
ENCODINGS.combination(n).each do |list|
|
49
|
-
it "round-trips #{list.join(', ')}" do
|
50
|
-
obj = RightSupport::Net::StringEncoder.new(*list)
|
51
|
-
@strings.each do |str|
|
52
|
-
obj.decode(obj.encode(str)).should == str
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
@@ -1,225 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RightSupport::Rack::RequestLogger do
|
4
|
-
class OhNoes < Exception; end
|
5
|
-
|
6
|
-
before(:each) do
|
7
|
-
@app = flexmock('Rack app')
|
8
|
-
@app.should_receive(:call).and_return([200, {}, 'body']).by_default
|
9
|
-
@logger = mock_logger
|
10
|
-
@env = {'rack.logger' => @logger}
|
11
|
-
@options = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
subject { described_class.new(@app, @options) }
|
15
|
-
|
16
|
-
context :initialize do
|
17
|
-
context 'without :logger option' do
|
18
|
-
it 'uses rack.logger' do
|
19
|
-
@logger.should_receive(:info).at_least.once
|
20
|
-
subject.call(@env).should == [200, {}, 'body']
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
context 'with :logger option' do
|
25
|
-
it 'uses given logger' do
|
26
|
-
@env = {'rack.logger' => flexmock('overridden')}
|
27
|
-
@options[:logger] = @logger
|
28
|
-
@logger.should_receive(:info).at_least.once
|
29
|
-
subject.call(@env).should == [200, {}, 'body']
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context 'with :normalize_40x option' do
|
34
|
-
it 'omits some 40x details and disables global session Set-Cookie fields' do
|
35
|
-
@options[:normalize_40x] = true
|
36
|
-
@app = flexmock('Rack app')
|
37
|
-
body = 'insecure information'
|
38
|
-
headers = { 'TooMuch' => 'info', 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }
|
39
|
-
iterative = [nil, headers, body]
|
40
|
-
@app.should_receive(:call).and_return(iterative)
|
41
|
-
|
42
|
-
# note that sending 'X-Debug' header should have no effect on a
|
43
|
-
# normalized 40x response
|
44
|
-
@env.merge!(described_class::DEBUG_MODE_HTTP_HEADER => 'true')
|
45
|
-
(400..499).each do |code|
|
46
|
-
iterative[0] = code
|
47
|
-
if described_class::NORMALIZE_40X.include?(code)
|
48
|
-
env = @env.dup
|
49
|
-
subject.call(env).should == [code, { 'Content-Length' => '0'}, []]
|
50
|
-
env.should == @env.merge(
|
51
|
-
'global_session.req.renew' => false,
|
52
|
-
'global_session.req.update' => false,
|
53
|
-
described_class::DEBUG_MODE_ENV_KEY => false)
|
54
|
-
else
|
55
|
-
subject.call(@env).should == iterative
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'with :normalize_40x_set_cookie option' do
|
62
|
-
it 'disables global session Set-Cookie fields' do
|
63
|
-
@options[:normalize_40x_set_cookie] = true
|
64
|
-
@app = flexmock('Rack app')
|
65
|
-
body = 'whatever'
|
66
|
-
headers = { 'Content-Type' => 'text/plain', 'Content-Length' => body.bytesize.to_s }
|
67
|
-
iterative = [nil, headers, body]
|
68
|
-
@app.should_receive(:call).and_return(iterative)
|
69
|
-
|
70
|
-
(400..499).each do |code|
|
71
|
-
iterative[0] = code
|
72
|
-
if described_class::NORMALIZE_40X.include?(code)
|
73
|
-
env = @env.dup
|
74
|
-
subject.call(env).should == iterative
|
75
|
-
env.should == @env.merge(
|
76
|
-
'global_session.req.renew' => false,
|
77
|
-
'global_session.req.update' => false)
|
78
|
-
else
|
79
|
-
subject.call(@env).should == iterative
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
context :call do
|
87
|
-
context 'when the app raises an exception' do
|
88
|
-
before(:each) do
|
89
|
-
@app.should_receive(:call).and_raise(OhNoes)
|
90
|
-
end
|
91
|
-
|
92
|
-
it 'logs the exception' do
|
93
|
-
@logger.should_receive(:error).at_least.once
|
94
|
-
lambda {
|
95
|
-
subject.call(@env)
|
96
|
-
}.should raise_error
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
context 'when Sinatra stores an exception' do
|
101
|
-
before(:each) do
|
102
|
-
@app.should_receive(:call).and_return([500, {}, 'body'])
|
103
|
-
@env['sinatra.error'] = OhNoes.new
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'logs the exception' do
|
107
|
-
@logger.should_receive(:info)
|
108
|
-
@logger.should_receive(:error).at_least.once
|
109
|
-
subject.call(@env)
|
110
|
-
end
|
111
|
-
|
112
|
-
it 'skips logging the exception when already handled' do
|
113
|
-
@logger.should_receive(:info)
|
114
|
-
@logger.should_receive(:error).never
|
115
|
-
@env['sinatra.error.handled'] = true
|
116
|
-
subject.call(@env)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context 'given limiting options' do
|
121
|
-
before(:each) do
|
122
|
-
@options = {:except => [/bar/]}
|
123
|
-
@env.merge!('PATH_INFO' => '/foo/bar')
|
124
|
-
subject = described_class.new(@app, @options)
|
125
|
-
@logger.should_receive(:level).and_return(Logger::INFO).by_default
|
126
|
-
end
|
127
|
-
|
128
|
-
it 'limits if logger in debug mode' do
|
129
|
-
@logger.should_receive(:level).and_return(Logger::DEBUG)
|
130
|
-
@logger.should_receive(:info).never
|
131
|
-
subject.call(@env)
|
132
|
-
end
|
133
|
-
|
134
|
-
it 'does not limit if HTTP_X_DEBUG set' do
|
135
|
-
@logger.should_receive(:info).at_least.once
|
136
|
-
subject.call(@env.merge('HTTP_X_DEBUG' => true))
|
137
|
-
end
|
138
|
-
|
139
|
-
it 'does not log for paths matching :except option' do
|
140
|
-
@logger.should_receive(:info).never
|
141
|
-
subject.call(@env)
|
142
|
-
end
|
143
|
-
|
144
|
-
it 'does log for paths matching :only option' do
|
145
|
-
@options = {:only => [/bar/]}
|
146
|
-
subject = described_class.new(@app, @options)
|
147
|
-
@logger.should_receive(:info)
|
148
|
-
subject.call(@env)
|
149
|
-
end
|
150
|
-
|
151
|
-
it 'sets rack.logging.enabled in Rack environment' do
|
152
|
-
@logger.should_receive(:info).at_least.once
|
153
|
-
@env.merge!('PATH_INFO' => '/my/app')
|
154
|
-
subject.call(@env)
|
155
|
-
@env['rack.logging.enabled'].should be_true
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
context 'when logging the query string' do
|
160
|
-
before(:each) do
|
161
|
-
@options = {}
|
162
|
-
@env.merge!('PATH_INFO' => '/my/app', 'QUERY_STRING' => 'foo=bar')
|
163
|
-
subject = described_class.new(@app, @options)
|
164
|
-
end
|
165
|
-
|
166
|
-
it 'does not log the query string by default' do
|
167
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /\/my\/app\?\.{3}/ } )
|
168
|
-
subject.send(:log_request_begin, @logger, @env)
|
169
|
-
end
|
170
|
-
|
171
|
-
context 'when the include_query_string option is true' do
|
172
|
-
it 'logs the query string' do
|
173
|
-
@options[:include_query_string] = true
|
174
|
-
subject = described_class.new(@app, @options)
|
175
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /\/my\/app\?foo%3Dbar/ } )
|
176
|
-
subject.send(:log_request_begin, @logger, @env)
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
context 'when the include_query_string option is false' do
|
181
|
-
it 'does not log the query string' do
|
182
|
-
@options[:include_query_string] = false
|
183
|
-
subject = described_class.new(@app, @options)
|
184
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /\/my\/app\?\.{3}/ } )
|
185
|
-
subject.send(:log_request_begin, @logger, @env)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
context 'Shard ID logging' do
|
191
|
-
before(:each) do
|
192
|
-
@logger = mock_logger
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'logs X-Shard header if it is present' do
|
196
|
-
@env['HTTP_X_SHARD'] = '9'
|
197
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /Shard: 9$/ } )
|
198
|
-
subject.send(:log_request_begin, @logger, @env)
|
199
|
-
end
|
200
|
-
|
201
|
-
it 'logs "default" if X-Shard header is absent' do
|
202
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /Shard: default$/ } )
|
203
|
-
subject.send(:log_request_begin, @logger, @env)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
context 'request ID logging' do
|
208
|
-
before(:each) do
|
209
|
-
@logger = mock_logger
|
210
|
-
@env['rack.request_uuid'] = 'some-uuid'
|
211
|
-
end
|
212
|
-
|
213
|
-
it 'tags the Started line' do
|
214
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /^\[some\-uuid\] Started / } )
|
215
|
-
subject.send(:log_request_begin, @logger, @env)
|
216
|
-
end
|
217
|
-
|
218
|
-
it 'tags the Completed line' do
|
219
|
-
@logger.should_receive(:info).with(FlexMock.on { |arg| arg.should =~ /^\[some\-uuid\] Completed / } )
|
220
|
-
subject.send(:log_request_end, @logger, @env, 200, {}, '', Time.now)
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
end
|
225
|
-
end
|
@@ -1,115 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe RightSupport::Rack::RequestTracker do
|
4
|
-
|
5
|
-
let(:app) { flexmock('next middleware or rack app') }
|
6
|
-
|
7
|
-
let(:generator) { described_class::Generator }
|
8
|
-
let(:generated_request_uuid) { 'generated-uuid' }
|
9
|
-
let(:request_uuid) { 'given-uuid' }
|
10
|
-
|
11
|
-
subject { described_class.new(app) }
|
12
|
-
|
13
|
-
context :call do
|
14
|
-
context 'when ID is missing from request headers' do
|
15
|
-
it 'generates a new request ID and responds as UUID for legacy reasons' do
|
16
|
-
flexmock(generator).
|
17
|
-
should_receive(:generate).
|
18
|
-
and_return(generated_request_uuid).
|
19
|
-
once
|
20
|
-
original_env = {}
|
21
|
-
expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => generated_request_uuid)
|
22
|
-
app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
|
23
|
-
|
24
|
-
actual = subject.call(original_env)
|
25
|
-
|
26
|
-
expected_headers = { described_class::REQUEST_UUID_HEADER => generated_request_uuid }
|
27
|
-
actual[1].should == expected_headers
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'when ID sent with request' do
|
32
|
-
it 'passes incoming request ID and responds as ID' do
|
33
|
-
flexmock(generator).should_receive(:generate).never
|
34
|
-
original_env = { described_class::HTTP_REQUEST_ID_HEADER => request_uuid }
|
35
|
-
expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => request_uuid)
|
36
|
-
app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
|
37
|
-
|
38
|
-
actual = subject.call(original_env)
|
39
|
-
|
40
|
-
expected_headers = { described_class::REQUEST_ID_HEADER => request_uuid }
|
41
|
-
actual[1].should == expected_headers
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
context 'when UUID sent with request' do
|
46
|
-
it 'passes incoming request UUID and responds as UUID' do
|
47
|
-
flexmock(generator).should_receive(:generate).never
|
48
|
-
original_env = { described_class::HTTP_REQUEST_UUID_HEADER => request_uuid }
|
49
|
-
expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => request_uuid)
|
50
|
-
app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
|
51
|
-
|
52
|
-
actual = subject.call(original_env)
|
53
|
-
|
54
|
-
expected_headers = { described_class::REQUEST_UUID_HEADER => request_uuid }
|
55
|
-
actual[1].should == expected_headers
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
context 'when lineage sent with request' do
|
60
|
-
it 'passes all UUIDs in header under length limit' do
|
61
|
-
uuids = []
|
62
|
-
3.times do
|
63
|
-
uuids << ::RightSupport::Data::UUID.generate
|
64
|
-
end
|
65
|
-
lineage_uuid = uuids.join(described_class::UUID_SEPARATOR)
|
66
|
-
flexmock(generator).should_receive(:generate).never
|
67
|
-
original_env = { described_class::REQUEST_LINEAGE_UUID_HEADER => lineage_uuid }
|
68
|
-
expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => lineage_uuid)
|
69
|
-
app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
|
70
|
-
|
71
|
-
actual = subject.call(original_env)
|
72
|
-
|
73
|
-
expected_headers = { described_class::REQUEST_UUID_HEADER => lineage_uuid }
|
74
|
-
actual[1].should == expected_headers
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
context 'when sent ID exceeds length limit' do
|
79
|
-
it 'passes truncated request ID' do
|
80
|
-
flexmock(generator).should_receive(:generate).never
|
81
|
-
too_long_id = 'x' * 1024
|
82
|
-
truncated_id = 'x' * described_class::MAX_REQUEST_UUID_LENGTH
|
83
|
-
original_env = { described_class::HTTP_REQUEST_ID_HEADER => too_long_id }
|
84
|
-
expected_env = original_env.merge(described_class::REQUEST_UUID_ENV_NAME => truncated_id)
|
85
|
-
app.should_receive(:call).with(expected_env).and_return([200, {}, 'body']).once
|
86
|
-
|
87
|
-
actual = subject.call(original_env)
|
88
|
-
|
89
|
-
expected_headers = { described_class::REQUEST_ID_HEADER => truncated_id }
|
90
|
-
actual[1].should == expected_headers
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
end
|
95
|
-
|
96
|
-
context :copy_request_uuid do
|
97
|
-
it 'does nothing when request UUID is missing' do
|
98
|
-
described_class.copy_request_uuid(nil, nil).should be_empty
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'copies request UUID to target hash when present' do
|
102
|
-
env = {
|
103
|
-
described_class::REQUEST_UUID_ENV_NAME => request_uuid,
|
104
|
-
'other' => 'stuff'
|
105
|
-
}
|
106
|
-
other_headers = { 'Foo' => 'bar' }
|
107
|
-
expected = {
|
108
|
-
described_class::REQUEST_ID_HEADER => request_uuid
|
109
|
-
}.merge(other_headers)
|
110
|
-
actual = described_class.copy_request_uuid(env, other_headers)
|
111
|
-
actual.should == expected
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
data/spec/rack/runtime_spec.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
class FasterApp
|
4
|
-
def self.call(env)
|
5
|
-
sleep 0.05; [200, {}, "50ms"]
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
class SlowerApp
|
10
|
-
def self.call(env)
|
11
|
-
sleep 0.2; [200, {}, "200ms"]
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
describe RightSupport::Rack::Runtime do
|
16
|
-
before(:each) do
|
17
|
-
@app = flexmock('Rack app')
|
18
|
-
@app.should_receive(:call).and_return([200, {}, 'body']).by_default
|
19
|
-
@env = {'rack.logger' => @logger}
|
20
|
-
@middleware = RightSupport::Rack::Runtime.new(@app)
|
21
|
-
end
|
22
|
-
|
23
|
-
context :call do
|
24
|
-
it 'sets an X-Runtime header in response' do
|
25
|
-
@middleware.call(@env).should == [200, {"X-Runtime"=>"0"}, 'body']
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'sets a correct X-Runtime value for 50 ms app' do
|
29
|
-
faster = RightSupport::Rack::Runtime.new(FasterApp)
|
30
|
-
result = faster.call(@env)
|
31
|
-
result[1].keys.should == ['X-Runtime']
|
32
|
-
result[1]['X-Runtime'].to_i.should >= 50
|
33
|
-
result[1]['X-Runtime'].to_i.should < 70
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'sets a correct X-Runtime value for 200 ms app' do
|
37
|
-
slower = RightSupport::Rack::Runtime.new(SlowerApp)
|
38
|
-
result = slower.call(@env)
|
39
|
-
result[1].keys.should == ['X-Runtime']
|
40
|
-
result[1]['X-Runtime'].to_i.should >= 200
|
41
|
-
result[1]['X-Runtime'].to_i.should < 270
|
42
|
-
end
|
43
|
-
|
44
|
-
it 'allows appending custom name to X-Runtime header' do
|
45
|
-
customized = RightSupport::Rack::Runtime.new(@app, "Test")
|
46
|
-
customized.call(@env).should == [200, {"X-Runtime-Test"=>"0"}, 'body']
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|