honeybadger 1.9.5 → 1.10.0.beta1

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.
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