honeybadger 1.9.5 → 1.10.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/Appraisals +0 -12
  2. data/CHANGELOG.md +19 -5
  3. data/Gemfile.lock +1 -5
  4. data/MIT-LICENSE +6 -5
  5. data/README.md +6 -596
  6. data/Rakefile +5 -5
  7. data/features/rails.feature +37 -12
  8. data/features/step_definitions/rails_steps.rb +20 -0
  9. data/features/support/honeybadger_shim.rb.template +3 -5
  10. data/gemfiles/rack.gemfile +0 -1
  11. data/gemfiles/rack.gemfile.lock +1 -8
  12. data/gemfiles/rails2.3.gemfile +0 -1
  13. data/gemfiles/rails2.3.gemfile.lock +1 -8
  14. data/gemfiles/rails3.0.gemfile +0 -2
  15. data/gemfiles/rails3.0.gemfile.lock +2 -12
  16. data/gemfiles/rails3.1.gemfile +0 -2
  17. data/gemfiles/rails3.1.gemfile.lock +3 -13
  18. data/gemfiles/rails3.2.gemfile +0 -2
  19. data/gemfiles/rails3.2.gemfile.lock +4 -14
  20. data/gemfiles/rails4.gemfile +0 -2
  21. data/gemfiles/rails4.gemfile.lock +4 -14
  22. data/gemfiles/rake.gemfile +0 -1
  23. data/gemfiles/rake.gemfile.lock +1 -8
  24. data/gemfiles/sinatra.gemfile +0 -1
  25. data/gemfiles/sinatra.gemfile.lock +1 -8
  26. data/honeybadger.gemspec +7 -3
  27. data/lib/honeybadger.rb +7 -5
  28. data/lib/honeybadger/configuration.rb +7 -3
  29. data/lib/honeybadger/monitor/sender.rb +4 -6
  30. data/lib/honeybadger/notice.rb +30 -4
  31. data/lib/honeybadger/rails.rb +2 -0
  32. data/lib/honeybadger/rails3_tasks.rb +2 -2
  33. data/lib/honeybadger/railtie.rb +3 -1
  34. data/lib/honeybadger/sender.rb +63 -53
  35. data/lib/honeybadger/templates/feedback_form.html.erb +82 -0
  36. data/lib/honeybadger/user_feedback.rb +42 -0
  37. data/lib/honeybadger/user_informer.rb +26 -0
  38. data/spec/honeybadger/configuration_spec.rb +4 -1
  39. data/spec/honeybadger/logger_spec.rb +25 -2
  40. data/spec/honeybadger/notice_spec.rb +69 -3
  41. data/spec/honeybadger/sender_spec.rb +77 -54
  42. data/spec/honeybadger/user_feedback_spec.rb +55 -0
  43. data/spec/honeybadger/user_informer_spec.rb +30 -0
  44. data/spec/support/helpers.rb +9 -6
  45. metadata +63 -39
  46. checksums.yaml +0 -7
@@ -0,0 +1,82 @@
1
+ <style>
2
+ #honeybadger_feedback_form *, #honeybadger_feedback_form *:before, #honeybadger_feedback_form *:after { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; }
3
+ #honeybadger_feedback_form h2 { font-size: 110%; line-height: 1.5em; }
4
+ #honeybadger_feedback_form label { font-weight: bold; }
5
+ #honeybadger_feedback_name, #honeybadger_feedback_email, #honeybadger_feedback_comment { width: 100%; padding: 0.5em; }
6
+ #honeybadger_feedback_comment { height: 10em; }
7
+ #honeybadger_feedback_submit { height: 1em; }
8
+ #honeybadger_feedback_form .honeybadger-feedback-phone { display: none; }
9
+ </style>
10
+
11
+ <script>
12
+ function honeybadgerFeedbackResponse(data) {
13
+ if (data['result'] == 'OK') {
14
+ var form = document.getElementById('honeybadger_feedback_form');
15
+ var success = document.getElementById('honeybadger_feedback_success');
16
+
17
+ form.style.display = 'none';
18
+ success.style.display = 'block';
19
+ } else {
20
+ var message;
21
+
22
+ if (data['error']) {
23
+ message = data['error'];
24
+ } else {
25
+ message = "An unknown error occurred. Please try again.";
26
+ }
27
+
28
+ alert(message);
29
+ }
30
+ }
31
+
32
+ function sendHoneybadgerFeedback() {
33
+ try {
34
+ var script = document.createElement('script');
35
+ var form = document.getElementById('honeybadger_feedback_form');
36
+ script.src = '<%= action %>?format=js&token=<%= error_id %>&name=' + encodeURIComponent(form.name.value) + '&email=' + encodeURIComponent(form.email.value) + '&comment=' + encodeURIComponent(form.comment.value);
37
+ form.appendChild(script);
38
+ return false;
39
+ } catch(e) {
40
+ if (window.console) {
41
+ console.log('Error caught while processing Honeybadger feedback form: ' + e);
42
+ console.log('Submitting form normally...');
43
+ }
44
+ return true;
45
+ }
46
+ }
47
+ </script>
48
+
49
+ <div id="honeybadger_feedback_success" style="display:none;">
50
+ <p><strong>Thanks for the feedback!</strong></p>
51
+ </div>
52
+
53
+ <form action="<%= action %>" method="POST" id="honeybadger_feedback_form" onsubmit="return sendHoneybadgerFeedback();">
54
+ <input type="hidden" name="token" id="honeybadger_feedback_token" value="<%= error_id %>">
55
+
56
+ <h2>Care to help us fix this?</h2>
57
+ <p>Any information you can provide will help our technical team get to the bottom of this issue.</p>
58
+
59
+ <p class="honeybadger-feedback-name">
60
+ <label for="honeybadger_feedback_name">Your name</label><br>
61
+ <input type="text" name="name" id="honeybadger_feedback_name" size="60">
62
+ </p>
63
+
64
+ <p class="honeybadger-feedback-phone">
65
+ <label for="honeybadger_feedback_phone">Your phone number</label><br>
66
+ <input type="text" name="phone" id="honeybadger_feedback_phone" size="60">
67
+ </p>
68
+
69
+ <p class="honeybadger-feedback-email">
70
+ <label for="honeybadger_feedback_email">Your email address</label><br>
71
+ <input type="email" name="email" id="honeybadger_feedback_email" size="60">
72
+ </p>
73
+
74
+ <p class="honeybadger-feedback-comment">
75
+ <label for="honeybadger_feedback_comment">Comment (required)</label><br>
76
+ <textarea name="comment" id="honeybadger_feedback_comment" cols="50" rows="6" required></textarea>
77
+ </p>
78
+
79
+ <p class="honeybadger-feedback-submit">
80
+ <input type="submit" id="honeybadger_feedback_submit" value="Send">
81
+ </p>
82
+ </form>
@@ -0,0 +1,42 @@
1
+ require 'erb'
2
+ require 'uri'
3
+
4
+ module Honeybadger
5
+ class UserFeedback
6
+ TEMPLATE = File.read(File.expand_path('../templates/feedback_form.html.erb', __FILE__)).freeze
7
+
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def action
13
+ config = Honeybadger.configuration
14
+ URI.parse("#{config.protocol}://#{config.host}:#{config.port}/v1/feedback/").to_s
15
+ rescue URI::InvalidURIError
16
+ nil
17
+ end
18
+
19
+ def render_form(error_id, action = action)
20
+ return unless action
21
+ ERB.new(TEMPLATE).result(binding)
22
+ end
23
+
24
+ def enabled?
25
+ Honeybadger.configuration.feedback && Honeybadger.configuration.features['feedback']
26
+ end
27
+
28
+ def call(env)
29
+ status, headers, body = @app.call(env)
30
+ if enabled? && env['honeybadger.error_id'] && form = render_form(env['honeybadger.error_id'])
31
+ new_body = []
32
+ body.each do |chunk|
33
+ new_body << chunk.gsub("<!-- HONEYBADGER FEEDBACK -->", form)
34
+ end
35
+ body.close if body.respond_to?(:close)
36
+ headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
37
+ body = new_body
38
+ end
39
+ [status, headers, body]
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,26 @@
1
+ module Honeybadger
2
+ class UserInformer
3
+ def initialize(app)
4
+ @app = app
5
+ end
6
+
7
+ def replacement(with)
8
+ Honeybadger.configuration.user_information.gsub(/\{\{\s*error_id\s*\}\}/, with.to_s)
9
+ end
10
+
11
+ def call(env)
12
+ status, headers, body = @app.call(env)
13
+ if env['honeybadger.error_id'] && Honeybadger.configuration.user_information
14
+ new_body = []
15
+ replace = replacement(env['honeybadger.error_id'])
16
+ body.each do |chunk|
17
+ new_body << chunk.gsub("<!-- HONEYBADGER ERROR -->", replace)
18
+ end
19
+ body.close if body.respond_to?(:close)
20
+ headers['Content-Length'] = new_body.reduce(0) { |a,e| a += e.bytesize }.to_s
21
+ body = new_body
22
+ end
23
+ [status, headers, body]
24
+ end
25
+ end
26
+ end
@@ -32,6 +32,7 @@ describe Honeybadger::Configuration do
32
32
  assert_config_default :debug, false
33
33
  assert_config_default :fingerprint, nil
34
34
  assert_config_default :hostname, Socket.gethostname
35
+ assert_config_default :feedback, true
35
36
  end
36
37
 
37
38
  it "configures async as Proc" do
@@ -113,6 +114,8 @@ describe Honeybadger::Configuration do
113
114
  assert_config_overridable :send_request_session
114
115
  assert_config_overridable :debug
115
116
  assert_config_overridable :hostname
117
+ assert_config_overridable :metrics
118
+ assert_config_overridable :feedback
116
119
  end
117
120
 
118
121
  it "has an api key" do
@@ -128,7 +131,7 @@ describe Honeybadger::Configuration do
128
131
  :notifier_version, :params_filters, :project_root, :port, :protocol,
129
132
  :proxy_host, :proxy_pass, :proxy_port, :proxy_user, :secure,
130
133
  :source_extract_radius, :async, :send_request_session, :debug,
131
- :fingerprint, :hostname].each do |option|
134
+ :fingerprint, :hostname, :metrics, :feedback].each do |option|
132
135
  expect(hash[option]).to eq config[option]
133
136
  end
134
137
  end
@@ -28,7 +28,7 @@ describe Honeybadger do
28
28
  it "prints environment info on a failed notification without a body" do
29
29
  reset_config
30
30
  stub_verbose_log
31
- stub_http(:response => Faraday::Response.new(:status => 500), :body => nil)
31
+ stub_http(:response => Net::HTTPError, :body => nil)
32
32
  Honeybadger.should_receive(:write_verbose_log).with(/Environment Info:/)
33
33
  Honeybadger.should_not_receive(:write_verbose_log).with(/Response from Honeybadger:/, anything)
34
34
  send_notice
@@ -46,9 +46,32 @@ describe Honeybadger do
46
46
  it "prints environment info and response on a failure with a body" do
47
47
  reset_config
48
48
  stub_verbose_log
49
- stub_http(:response => Faraday::Response.new(:status => 500))
49
+ stub_http(:response => Net::HTTPError)
50
50
  Honeybadger.should_receive(:write_verbose_log).with(/Environment Info:/)
51
51
  Honeybadger.should_receive(:write_verbose_log).with(/Response from Honeybadger:/)
52
52
  send_notice
53
53
  end
54
+
55
+ context "429 error response" do
56
+ let(:failure_class) do
57
+ if RUBY_VERSION !~ /^1/
58
+ 'Net::HTTPTooManyRequests'
59
+ else
60
+ 'Net::HTTPClientError'
61
+ end
62
+ end
63
+
64
+ before do
65
+ reset_config
66
+ stub_verbose_log
67
+ stub_request(:post, /api\.honeybadger\.io\/v1\/notices/).to_return(:status => 429, :body => '{"error":"something went wrong"}')
68
+ end
69
+
70
+ it "logs the response" do
71
+ Honeybadger.should_receive(:write_verbose_log).with(/Failure: #{failure_class}/, :error)
72
+ Honeybadger.should_receive(:write_verbose_log).with(/Environment Info:/)
73
+ Honeybadger.should_receive(:write_verbose_log).with(/something went wrong/)
74
+ Honeybadger.notify(RuntimeError.new('oops!'))
75
+ end
76
+ end
54
77
  end
@@ -95,6 +95,16 @@ describe Honeybadger::Notice do
95
95
  expect(notice.hostname).to eq 'asdf'
96
96
  end
97
97
 
98
+ it "defaults api key to configuration" do
99
+ notice = build_notice
100
+ expect(notice.api_key).to eq 'abc123def456'
101
+ end
102
+
103
+ it "sets the api key" do
104
+ notice = build_notice({ :api_key => 'asdf' })
105
+ expect(notice.api_key).to eq 'asdf'
106
+ end
107
+
98
108
  context "custom fingerprint" do
99
109
  it "includes nil fingerprint when no fingerprint is specified" do
100
110
  notice = build_notice
@@ -303,6 +313,56 @@ describe Honeybadger::Notice do
303
313
  assert_filters_hash(:session_data)
304
314
  end
305
315
 
316
+ describe 'url' do
317
+ let(:params_filters) { [] }
318
+ let(:notice) { build_notice(:params_filters => params_filters, :url => url) }
319
+
320
+ context 'filtered params in query' do
321
+ let(:params_filters) { [:bar] }
322
+ let(:url) { 'https://www.honeybadger.io/?foo=1&bar=2&baz=3' }
323
+
324
+ it 'filters query' do
325
+ expect(notice.url).to eq 'https://www.honeybadger.io/?foo=1&bar=[FILTERED]&baz=3'
326
+ end
327
+ end
328
+
329
+ context 'malformed query' do
330
+ let(:url) { 'https://www.honeybadger.io/?foobar12' }
331
+
332
+ it 'maintains query' do
333
+ expect(notice.url).to eq url
334
+ end
335
+ end
336
+
337
+ context 'no query' do
338
+ let(:url) { 'https://www.honeybadger.io' }
339
+
340
+ it 'keeps original URL' do
341
+ expect(notice.url).to eq url
342
+ end
343
+ end
344
+
345
+ context 'malformed url' do
346
+ let(:url) { 'http s ! honeybadger' }
347
+
348
+ before do
349
+ expect { URI.parse(url) }.to raise_error
350
+ end
351
+
352
+ it 'keeps original URL' do
353
+ expect(notice.url).to eq url
354
+ end
355
+ end
356
+
357
+ context 'complex url' do
358
+ let(:url) { 'https://foo:bar@www.honeybadger.io:123/asdf/?foo=1&bar=2&baz=3' }
359
+
360
+ it 'keeps original URL' do
361
+ expect(notice.url).to eq url
362
+ end
363
+ end
364
+ end
365
+
306
366
  it "removes rack.request.form_vars" do
307
367
  original = {
308
368
  "rack.request.form_vars" => "story%5Btitle%5D=The+TODO+label",
@@ -559,14 +619,20 @@ describe Honeybadger::Notice do
559
619
  end
560
620
 
561
621
  def assert_filters_hash(attribute)
562
- filters = ["abc", :def]
622
+ filters = ["abc", :def, /private/, /^foo_.*$/]
563
623
  original = { 'abc' => "123", 'def' => "456", 'ghi' => "789", 'nested' => { 'abc' => '100' },
564
- 'something_with_abc' => 'match the entire string'}
624
+ 'something_with_abc' => 'match the entire string', 'private_param' => 'prra',
625
+ 'foo_param' => 'bar', 'not_foo_param' => 'baz', 'nested_foo' => { 'foo_nested' => 'bla'} }
565
626
  filtered = { 'abc' => "[FILTERED]",
566
627
  'def' => "[FILTERED]",
567
628
  'something_with_abc' => "match the entire string",
568
629
  'ghi' => "789",
569
- 'nested' => { 'abc' => '[FILTERED]' } }
630
+ 'nested' => { 'abc' => '[FILTERED]' },
631
+ 'private_param' => '[FILTERED]',
632
+ 'foo_param' => '[FILTERED]',
633
+ 'not_foo_param' => 'baz',
634
+ 'nested_foo' => { 'foo_nested' => '[FILTERED]'}
635
+ }
570
636
 
571
637
  notice = build_notice(:params_filters => filters, attribute => original)
572
638
 
@@ -1,27 +1,24 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Honeybadger::Sender do
4
- before(:each) { reset_config }
4
+ before { reset_config }
5
5
 
6
- it "it makes a single request when sending notices" do
7
- stub_request(:post, /api\.honeybadger\.io/)
6
+ before do
7
+ stub_request(:post, /api\.honeybadger\.io\/v1\/notices/).to_return(:body => '{"id":"123"}')
8
+ end
9
+
10
+ it "makes a single request when sending notices" do
8
11
  Honeybadger.notify(RuntimeError.new('oops!'))
9
12
  assert_requested :post, 'https://api.honeybadger.io/v1/notices/', :times => 1
10
13
  end
11
14
 
12
15
  it "posts to Honeybadger when using an HTTP proxy" do
13
- post = double()
14
- http = stub_http
15
- http.stub(:post).and_yield(post).and_return(false)
16
-
17
- url = "http://api.honeybadger.io:80#{Honeybadger::Sender::NOTICES_URI}"
18
- uri = URI.parse(url)
16
+ http = stub_http
17
+ proxy = double(:new => http)
18
+ Net::HTTP.stub(:Proxy).and_return(proxy)
19
19
 
20
- post.should_receive(:url).with(uri.path)
21
- post.should_receive(:body=).with('asdf')
22
-
23
- Faraday.should_receive(:new).
24
- with(hash_including(:proxy => { :uri => 'https://some.host:88', :user => 'login', :password => 'passwd' })).and_return(http)
20
+ http.should_receive(:post).with(Honeybadger::Sender::NOTICES_URI, kind_of(String), Honeybadger::HEADERS.merge({ 'X-API-Key' => 'abc123'}))
21
+ Net::HTTP.should_receive(:Proxy).with('some.host', 88, 'login', 'passwd')
25
22
 
26
23
  send_exception(:proxy_host => 'some.host',
27
24
  :proxy_port => 88,
@@ -36,27 +33,47 @@ describe Honeybadger::Sender do
36
33
  end
37
34
 
38
35
  it "returns nil on failed posting" do
39
- stub_http(:response => Faraday::Response.new(:status => 500))
36
+ stub_http(:response => Net::HTTPError)
40
37
  expect(send_exception(:secure => false)).to be_nil
41
38
  end
42
39
 
43
- it "logs missing API key and return nil" do
44
- sender = build_sender(:api_key => nil)
45
- sender.should_receive(:log).with(:error, /API key/)
46
- expect(send_exception(:sender => sender, :secure => false)).to be_nil
40
+ describe '#api_key' do
41
+ context 'api_key is missing' do
42
+ it "logs missing API key and return nil" do
43
+ sender = build_sender(:api_key => nil)
44
+ sender.should_receive(:log).with(:error, /API key/)
45
+ expect(send_exception(:sender => sender, :secure => false)).to be_nil
46
+ end
47
+ end
48
+
49
+ context 'notice is a hash' do
50
+ it 'uses api_key from hash when present' do
51
+ sender = build_sender(:api_key => 'asdf')
52
+ send_exception(:sender => sender, :notice => { 'api_key' => 'zxcv' })
53
+ assert_requested :post, 'https://api.honeybadger.io/v1/notices/', :times => 1, :headers => { 'x-api-key' => 'zxcv' }
54
+ end
55
+ end
56
+
57
+ context 'notice is a Honeybadger::Notice' do
58
+ it 'uses api_key from notice when present' do
59
+ sender = build_sender(:api_key => 'asdf')
60
+ send_exception(:sender => sender, :notice => Honeybadger::Notice.new(:api_key => 'zxcv'))
61
+ assert_requested :post, 'https://api.honeybadger.io/v1/notices/', :times => 1, :headers => { 'x-api-key' => 'zxcv' }
62
+ end
63
+ end
47
64
  end
48
65
 
49
66
  it "logs success" do
50
67
  stub_http
51
68
  sender = build_sender
52
- sender.should_receive(:log).with(:debug, /Success/, kind_of(Faraday::Response), kind_of(String))
69
+ sender.should_receive(:log).with(:debug, /Success/, kind_of(Net::HTTPSuccess), kind_of(String))
53
70
  send_exception(:sender => sender, :secure => false)
54
71
  end
55
72
 
56
73
  it "logs failure" do
57
- stub_http(:response => Faraday::Response.new(:status => 500))
74
+ stub_http(:response => Net::HTTPServerError.new('1.2', '500', 'Internal Error'))
58
75
  sender = build_sender
59
- sender.should_receive(:log).with(:error, /Failure/, kind_of(Faraday::Response), kind_of(String))
76
+ sender.should_receive(:log).with(:error, /Failure/, kind_of(Net::HTTPServerError), kind_of(String))
60
77
  send_exception(:sender => sender, :secure => false)
61
78
  end
62
79
 
@@ -64,24 +81,28 @@ describe Honeybadger::Sender do
64
81
  # TODO: Figure out why nested groups aren't running
65
82
  context "HTTP connection setup problems" do
66
83
  it "should not be rescued" do
67
- Faraday.should_receive(:new).and_raise(NoMemoryError)
68
- expect { build_sender.send(:client) }.to raise_error(NoMemoryError)
84
+ proxy = double()
85
+ proxy.stub(:new).and_raise(NoMemoryError)
86
+ Net::HTTP.stub(:Proxy).and_return(proxy)
87
+ expect { build_sender.send(:setup_http_connection) }.to raise_error(NoMemoryError)
69
88
  end
70
89
 
71
90
  it "should be logged" do
72
- Faraday.should_receive(:new).and_raise(RuntimeError)
91
+ proxy = double()
92
+ proxy.stub(:new).and_raise(RuntimeError)
93
+ Net::HTTP.stub(:Proxy).and_return(proxy)
73
94
 
74
95
  sender = build_sender
75
96
  sender.should_receive(:log).with(:error, /Failure initializing the HTTP connection/)
76
97
 
77
- expect { sender.send(:client) }.to raise_error(RuntimeError)
98
+ expect { sender.send(:setup_http_connection) }.to raise_error(RuntimeError)
78
99
  end
79
100
  end
80
101
 
81
102
  context "unexpected exception sending problems" do
82
103
  it "should be logged" do
83
104
  sender = build_sender
84
- sender.should_receive(:client).and_raise(RuntimeError)
105
+ sender.should_receive(:setup_http_connection).and_raise(RuntimeError)
85
106
 
86
107
  sender.should_receive(:log).with(:error, /Error/)
87
108
  sender.send_to_honeybadger("stuff")
@@ -89,7 +110,7 @@ describe Honeybadger::Sender do
89
110
 
90
111
  it "returns nil no matter what" do
91
112
  sender = build_sender
92
- sender.should_receive(:client).and_raise(LocalJumpError)
113
+ sender.should_receive(:setup_http_connection).and_raise(LocalJumpError)
93
114
 
94
115
  expect { sender.send_to_honeybadger("stuff").should be_nil }.not_to raise_error
95
116
  end
@@ -127,34 +148,32 @@ describe Honeybadger::Sender do
127
148
  http = stub_http
128
149
  url = "http://api.honeybadger.io:80#{Honeybadger::Sender::NOTICES_URI}"
129
150
  uri = URI.parse(url)
130
- post = double(:body= => nil)
131
- http.should_receive(:post).and_yield(post)
132
- post.should_receive(:url).with(uri.path)
151
+ http.should_receive(:post).with(uri.path, anything, Honeybadger::HEADERS.merge({ 'X-API-Key' => 'abc123'}))
133
152
  send_exception(:secure => false)
134
153
  end
135
154
 
136
155
  it "post to the right path for ssl" do
137
156
  http = stub_http
138
- post = double(:body= => nil)
139
- http.should_receive(:post).and_yield(post)
140
- post.should_receive(:url).with(Honeybadger::Sender::NOTICES_URI)
157
+ http.should_receive(:post).with(Honeybadger::Sender::NOTICES_URI, anything, Honeybadger::HEADERS.merge({ 'X-API-Key' => 'abc123'}))
141
158
  send_exception(:secure => true)
142
159
  end
143
160
 
144
161
  it "verifies the SSL peer when the use_ssl option is set to true" do
145
162
  url = "https://api.honeybadger.io#{Honeybadger::Sender::NOTICES_URI}"
163
+ uri = URI.parse(url)
146
164
 
147
- real_http = Faraday.new(:url => url)
165
+ real_http = Net::HTTP.new(uri.host, uri.port)
148
166
  real_http.stub(:post => nil)
149
- Faraday.stub(:new).and_return(real_http)
167
+ proxy = double(:new => real_http)
168
+ Net::HTTP.stub(:Proxy => proxy)
150
169
 
151
170
  File.stub(:exist?).with(OpenSSL::X509::DEFAULT_CERT_FILE).and_return(false)
152
171
 
153
172
  send_exception(:secure => true)
154
173
 
155
- expect(real_http.ssl).not_to be_empty
156
- expect(real_http.ssl[:verify_mode]).to eq OpenSSL::SSL::VERIFY_PEER
157
- expect(real_http.ssl[:ca_file]).to eq Honeybadger.configuration.local_cert_path
174
+ expect(real_http.use_ssl?).to be_true
175
+ expect(real_http.verify_mode).to eq OpenSSL::SSL::VERIFY_PEER
176
+ expect(real_http.ca_file).to eq Honeybadger.configuration.local_cert_path
158
177
  end
159
178
 
160
179
  it "uses the default DEFAULT_CERT_FILE if asked to" do
@@ -169,61 +188,65 @@ describe Honeybadger::Sender do
169
188
 
170
189
  expect(sender.use_system_ssl_cert_chain?).to be_true
171
190
 
172
- http = sender.send(:client)
173
- expect(http.ssl[:ca_file]).not_to eq Honeybadger.configuration.local_cert_path
191
+ http = sender.send(:setup_http_connection)
192
+ expect(http.ca_file).not_to eq Honeybadger.configuration.local_cert_path
174
193
  end
175
194
 
176
195
  it "verifies the connection when the use_ssl option is set (VERIFY_PEER)" do
177
196
  sender = build_sender(:secure => true)
178
- http = sender.send(:client)
179
- expect(http.ssl[:verify_mode]).to eq OpenSSL::SSL::VERIFY_PEER
197
+ http = sender.send(:setup_http_connection)
198
+ expect(http.verify_mode).to eq OpenSSL::SSL::VERIFY_PEER
180
199
  end
181
200
 
182
201
  it "uses the default cert (OpenSSL::X509::DEFAULT_CERT_FILE) only if explicitly told to" do
183
202
  sender = build_sender(:secure => true)
184
- http = sender.send(:client)
203
+ http = sender.send(:setup_http_connection)
185
204
 
186
- expect(http.ssl[:ca_file]).to eq Honeybadger.configuration.local_cert_path
205
+ expect(http.ca_file).to eq Honeybadger.configuration.local_cert_path
187
206
 
188
207
  File.stub(:exist?).with(OpenSSL::X509::DEFAULT_CERT_FILE).and_return(true)
189
208
  sender = build_sender(:secure => true, :use_system_ssl_cert_chain => true)
190
- http = sender.send(:client)
209
+ http = sender.send(:setup_http_connection)
191
210
 
192
- expect(http.ssl[:ca_file]).not_to eq Honeybadger.configuration.local_cert_path
193
- expect(http.ssl[:ca_file]).to eq OpenSSL::X509::DEFAULT_CERT_FILE
211
+ expect(http.ca_file).not_to eq Honeybadger.configuration.local_cert_path
212
+ expect(http.ca_file).to eq OpenSSL::X509::DEFAULT_CERT_FILE
194
213
  end
195
214
 
196
215
  it "uses ssl if secure" do
197
216
  sender = build_sender(:secure => true)
198
- http = sender.send(:client)
217
+ http = sender.send(:setup_http_connection)
199
218
  expect(http.port).to eq 443
200
219
  end
201
220
 
202
221
  it "does not use ssl if not secure" do
203
222
  sender = build_sender(:secure => false)
204
- http = sender.send(:client)
223
+ http = sender.send(:setup_http_connection)
205
224
  expect(http.port).to eq 80
206
225
  end
207
226
  end
208
227
 
209
228
  context "network timeouts" do
210
229
  it "default the open timeout to 2 seconds" do
211
- Faraday.should_receive(:new).with(hash_including({ :request => hash_including({ :open_timeout => 2 }) }))
230
+ http = stub_http
231
+ http.should_receive(:open_timeout=).with(2)
212
232
  send_exception
213
233
  end
214
234
 
215
235
  it "default the read timeout to 5 seconds" do
216
- Faraday.should_receive(:new).with(hash_including({ :request => hash_including({ :timeout => 5 }) }))
236
+ http = stub_http
237
+ http.should_receive(:read_timeout=).with(5)
217
238
  send_exception
218
239
  end
219
240
 
220
241
  it "allow override of the open timeout" do
221
- Faraday.should_receive(:new).with(hash_including({ :request => hash_including({ :open_timeout => 4 }) }))
242
+ http = stub_http
243
+ http.should_receive(:open_timeout=).with(4)
222
244
  send_exception(:http_open_timeout => 4)
223
245
  end
224
246
 
225
247
  it "allow override of the read timeout" do
226
- Faraday.should_receive(:new).with(hash_including({ :request => hash_including({ :timeout => 10 }) }))
248
+ http = stub_http
249
+ http.should_receive(:read_timeout=).with(10)
227
250
  send_exception(:http_read_timeout => 10)
228
251
  end
229
252
  end