exception_no 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OGYwNDYzMDA0NmQzN2U4YTU2MGYxMzQ3OTQ5YTY5NTQ5Y2JiNTExNA==
4
+ NDMwNTRkNzExMWNiOWQ0OGQ5NzFmYmJhYmM2MTBhNGYzMWZiZWZkMg==
5
5
  data.tar.gz: !binary |-
6
- NWY4ODFiOGIwNDI3YzcwZjBkOGE3YjE0ZGY4NTQ3MzEzNDM5ZDM2OQ==
6
+ NTY4YmJhNjUzZWU5YTJjMmUyODI5M2ZiMTVkYTZmOGJmNWE2MWIwNw==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- N2Q3NWE4ZGEyZDI4NTg4MTA5Y2ZkMTQ0MmU4MWQyODUxMzAyMzYwZTk3ZjFm
10
- NjBhZTFmZTcxMTg4M2JjN2NlZjEwNzAyZGNiNTQyMGI4MmNhNzEzMzBiMDQ4
11
- YzRlYjI1ZGVkNzBkMzM0MTUzYzFkY2I3YzZhYjk4NjRhMDFkMDc=
9
+ MDI3ZTY2NjhkYjk2NjU3ODZmNGNhNTMyNjczZDUwYWRiZDE1NmFmZjdhOWI4
10
+ YWNjYmIzYjAyMGM5MzhmOTdkMWUyMGYyNGIwNjFlMzQxMWJlMTUxMzU1ZTYx
11
+ NTU2YTc2NDY5NDBmNzAzN2I4M2RjNjlhYzA4YWY2MDUwODFkMzU=
12
12
  data.tar.gz: !binary |-
13
- MWI4YWI5MzQwNTU3ZjNiYzZjYmU1ZDBhNjUwNDkxYmIwMTI3OGMzNDJiYTgz
14
- Y2Y3ZDk5OGQzYTU3OTViNmNiMTc2MGUyODBjY2MxYzFjOTNmNTMyY2UwYzhl
15
- ZjBlYjJkMGM2MmFjMmQ0MmNhMDQ5NWFhOTZkMGMxNjU0MWEyZDk=
13
+ M2RmMjc2ZjQyNjg1MzRlN2M0OTUyNDY1MTVjNjM2ODNjZjk4ZjNmNmZjNTU5
14
+ NzFlYjU0ODNkZmY1NjNiMDVkYzdkNzkwZWVhYzBhMjdmNzY1Y2NhM2E0YjE2
15
+ ZDkxMmZjMDgyOTFhYjY4MTAzNzM4NDYzZmYyYmFlMWY5NzBiYWI=
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ 0.0.5 - 2014-09-10
2
+ ==================
3
+
4
+ * The middleware now extracts the request IP address.
5
+
6
+ * The middleware now extracts the request body.
7
+
8
+ * Added `ExceptionNo#run` which takes a block and notifies about errors.
9
+
1
10
  0.0.3 - 2013-09-18
2
11
  ==================
3
12
 
data/exception_no.gemspec CHANGED
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.license = "Unlicense"
15
15
 
16
- s.add_development_dependency "mini-smtp-server"
17
16
  s.add_development_dependency "cutest"
17
+ s.add_development_dependency "mini-smtp-server"
18
+ s.add_development_dependency "rack"
18
19
  end
data/lib/exception_no.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require "net/smtp"
2
2
  require "erb"
3
+ require "pp"
3
4
 
4
5
  class ExceptionNo
5
- VERSION = "0.0.4"
6
+ VERSION = "0.0.5"
6
7
 
7
8
  attr_accessor :backtrace_filter
8
9
  attr_accessor :behaviors
@@ -15,7 +16,7 @@ class ExceptionNo
15
16
  @backtrace_filter = -> line { true }
16
17
  end
17
18
 
18
- def _deliver(exception, options = {})
19
+ def _deliver(exception, env = {})
19
20
  body = @template.result(binding)
20
21
 
21
22
  Net::SMTP.start(@config.fetch(:host), @config.fetch(:port, 25)) do |smtp|
@@ -42,12 +43,20 @@ class ExceptionNo
42
43
  raise exception if @behaviors.include?(:raise)
43
44
  end
44
45
 
46
+ def run(env = {})
47
+ begin
48
+ yield
49
+ rescue Exception => ex
50
+ notify(ex, env)
51
+ end
52
+ end
53
+
45
54
  TEMPLATE = (<<-'EMAIL').gsub(/^ {2}/, '')
46
55
  From: <%= @config[:from_alias] %> <<%= @config[:from] %>>
47
56
  To: <<%= @config[:to] %>>
48
57
  Subject: <%= exception.class %>: <%= exception.message.split.join(" ") %>
49
58
 
50
- <%= options[:body] %>
59
+ <%= env.map { |*parts| parts.join(": ") }.join("\n") %>
51
60
 
52
61
  <%= "~" * 80 %>
53
62
 
@@ -66,7 +75,7 @@ class ExceptionNo
66
75
  begin
67
76
  @app.call(env)
68
77
  rescue Exception => e
69
- @notifier.notify(e, body: extract_env(env))
78
+ @notifier.notify(e, extract_env(env))
70
79
 
71
80
  raise e
72
81
  end
@@ -80,9 +89,24 @@ class ExceptionNo
80
89
  parts << "#{req.request_method} #{req.url}"
81
90
  parts << "User-Agent: #{req.user_agent}" if req.user_agent
82
91
  parts << "Referrer: #{req.referrer}" if req.referrer
92
+ parts << "IP: #{req.ip}" if req.ip
83
93
  parts << "Cookie: #{req.env["HTTP_COOKIE"]}" if req.cookies.size > 0
84
94
 
85
- parts.join("\n")
95
+ if req.form_data?
96
+ body = req.POST.pretty_inspect
97
+ else
98
+ req.body.rewind
99
+
100
+ body = req.body.read
101
+
102
+ body = nil if body.empty?
103
+ end
104
+
105
+ if body
106
+ parts << "Body: \n#{body.gsub(/^/, " ")}"
107
+ end
108
+
109
+ parts
86
110
  end
87
111
  end
88
112
  end
data/test/exception_no.rb CHANGED
@@ -16,7 +16,7 @@ test "deliver exception notification" do |notifier|
16
16
 
17
17
  notifier.notify(ex)
18
18
 
19
- email = $smtp.outbox.last
19
+ email = $smtp.outbox.pop
20
20
 
21
21
  assert_equal email[:to], "<root@localhost>"
22
22
  assert_equal email[:from], "<service@localhost>"
@@ -32,7 +32,7 @@ test "exception messages with multiple lines" do |notifier|
32
32
 
33
33
  notifier.notify(ArgumentError.new("A really\nbad\nargument"))
34
34
 
35
- headers, body = parse_email($smtp.outbox.last[:data])
35
+ headers, body = parse_email($smtp.outbox.pop[:data])
36
36
 
37
37
  assert_equal headers["Subject"], "ArgumentError: A really bad argument"
38
38
  end
@@ -46,7 +46,7 @@ test "includes backtrace information" do |notifier|
46
46
  notifier.notify(ex)
47
47
  end
48
48
 
49
- headers, body = parse_email($smtp.outbox.last[:data])
49
+ headers, body = parse_email($smtp.outbox.pop[:data])
50
50
 
51
51
  assert body.include?(__FILE__)
52
52
  assert body.include?(Gem.path.first)
@@ -65,7 +65,7 @@ test "allows to filter the backtrace" do |notifier|
65
65
  notifier.notify(ex)
66
66
  end
67
67
 
68
- headers, body = parse_email($smtp.outbox.last[:data])
68
+ headers, body = parse_email($smtp.outbox.pop[:data])
69
69
 
70
70
  assert body.include?(__FILE__)
71
71
  assert !body.include?(Gem.path.first)
@@ -76,7 +76,9 @@ test "disable delivery" do |notifier|
76
76
 
77
77
  notifier.notify(ArgumentError.new)
78
78
 
79
- assert_equal $smtp.outbox.size, 0
79
+ assert_raise(QueueWithTimeout::Timeout) do
80
+ $smtp.outbox.pop(0.5)
81
+ end
80
82
  end
81
83
 
82
84
  test "raise exception" do |notifier|
@@ -84,7 +86,9 @@ test "raise exception" do |notifier|
84
86
 
85
87
  assert_raise(ArgumentError) { notifier.notify(ArgumentError.new) }
86
88
 
87
- assert_equal $smtp.outbox.size, 0
89
+ assert_raise(QueueWithTimeout::Timeout) do
90
+ $smtp.outbox.pop(0.5)
91
+ end
88
92
  end
89
93
 
90
94
  test "raise exception and deliver notification" do |notifier|
@@ -92,8 +96,27 @@ test "raise exception and deliver notification" do |notifier|
92
96
 
93
97
  assert_raise(ArgumentError) { notifier.notify(ArgumentError.new) }
94
98
 
95
- assert_equal $smtp.outbox.size, 1
99
+ assert $smtp.outbox.pop
100
+ end
101
+
102
+ test "block behavior" do |notifier|
103
+ notifier.behaviors = [:deliver]
104
+
105
+ notifier.run do
106
+ raise ArgumentError, "A bad argument"
107
+ end
108
+
109
+ assert $smtp.outbox.pop
96
110
  end
97
111
 
98
- $smtp.stop
99
- $smtp.join
112
+ test "block with environment" do |notifier|
113
+ notifier.behaviors = [:deliver]
114
+
115
+ notifier.run("Foo" => "Bar") do
116
+ raise ArgumentError, "A bad argument"
117
+ end
118
+
119
+ headers, body = parse_email($smtp.outbox.pop[:data])
120
+
121
+ assert body.include?("Foo: Bar")
122
+ end
data/test/middleware.rb CHANGED
@@ -26,6 +26,7 @@ test "extracts interesting stuff from the request" do |app|
26
26
  "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)",
27
27
  "HTTP_REFERER" => "/other",
28
28
  "HTTP_COOKIE" => "foo=bar",
29
+ "REMOTE_ADDR" => "127.0.0.2",
29
30
  )
30
31
 
31
32
  begin
@@ -33,13 +34,53 @@ test "extracts interesting stuff from the request" do |app|
33
34
  rescue ZeroDivisionError
34
35
  end
35
36
 
36
- headers, body = parse_email($smtp.outbox.last[:data])
37
+ headers, body = parse_email($smtp.outbox.pop[:data])
37
38
 
38
39
  assert_equal headers["Subject"], "ZeroDivisionError: divided by 0"
39
- assert body.include?("GET http://example.org/baz")
40
+ assert body.include?("GET http://example.org/baz\r\n")
40
41
  assert body.include?("User-Agent: Mozilla/4.0 (compatible)")
41
42
  assert body.include?("Referrer: /other")
42
43
  assert body.include?("Cookie: foo=bar")
44
+ assert body.include?("IP: 127.0.0.2")
45
+ end
46
+
47
+ test "extracts the posted form" do |app|
48
+ env = Rack::MockRequest.env_for(
49
+ "/baz",
50
+ "REQUEST_METHOD" => "POST",
51
+ input: "foo=bar&baz=qux",
52
+ )
53
+
54
+ begin
55
+ app.call(env)
56
+ rescue ZeroDivisionError
57
+ end
58
+
59
+ headers, body = parse_email($smtp.outbox.pop[:data])
60
+
61
+ assert_equal headers["Subject"], "ZeroDivisionError: divided by 0"
62
+ assert body.include?("POST http://example.org/baz\r\n")
63
+ assert body.include?(%Q[ {"foo"=>"bar", "baz"=>"qux"}])
64
+ end
65
+
66
+ test "extracts the request body" do |app|
67
+ env = Rack::MockRequest.env_for(
68
+ "/baz",
69
+ "REQUEST_METHOD" => "POST",
70
+ "CONTENT_TYPE" => "text/plain; charset=utf-8",
71
+ input: "foo:bar",
72
+ )
73
+
74
+ begin
75
+ app.call(env)
76
+ rescue ZeroDivisionError
77
+ end
78
+
79
+ headers, body = parse_email($smtp.outbox.pop[:data])
80
+
81
+ assert_equal headers["Subject"], "ZeroDivisionError: divided by 0"
82
+ assert body.include?("POST http://example.org/baz\r\n")
83
+ assert body.include?(%Q[ foo:bar])
43
84
  end
44
85
 
45
86
  test "doesn't raise when the notification fails" do |app|
data/test/prelude.rb CHANGED
@@ -4,16 +4,57 @@ require "mini-smtp-server"
4
4
  require_relative "../lib/exception_no"
5
5
 
6
6
  class SMTPServer < MiniSmtpServer
7
- def outbox
8
- @outbox ||= []
7
+ attr :outbox
8
+
9
+ def initialize(*args)
10
+ @outbox = QueueWithTimeout.new
11
+ super(*args)
9
12
  end
10
13
 
11
14
  def new_message_event(message)
12
- outbox << message
15
+ @outbox << message
13
16
  true
14
17
  end
15
18
  end
16
19
 
20
+ # Source: http://spin.atomicobject.com/2014/07/07/ruby-queue-pop-timeout
21
+ class QueueWithTimeout
22
+ Timeout = Class.new(StandardError)
23
+
24
+ def initialize
25
+ @mutex = Mutex.new
26
+ @queue = []
27
+ @recieved = ConditionVariable.new
28
+ end
29
+
30
+ def <<(x)
31
+ @mutex.synchronize do
32
+ @queue << x
33
+ @recieved.signal
34
+ end
35
+ end
36
+
37
+ def size
38
+ @queue.size
39
+ end
40
+
41
+ def clear
42
+ @mutex.synchronize do
43
+ @queue.clear
44
+ end
45
+ end
46
+
47
+ def pop(timeout = 2)
48
+ @mutex.synchronize do
49
+ if @queue.empty?
50
+ @recieved.wait(@mutex, timeout) if timeout != 0
51
+ raise Timeout, "queue empty" if @queue.empty?
52
+ end
53
+ @queue.pop
54
+ end
55
+ end
56
+ end
57
+
17
58
  def parse_email(raw)
18
59
  headers = {}
19
60
  body = []
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exception_no
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Educabilia
@@ -9,8 +9,22 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-28 00:00:00.000000000 Z
12
+ date: 2014-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: cutest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ! '>='
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
14
28
  - !ruby/object:Gem::Dependency
15
29
  name: mini-smtp-server
16
30
  requirement: !ruby/object:Gem::Requirement
@@ -26,7 +40,7 @@ dependencies:
26
40
  - !ruby/object:Gem::Version
27
41
  version: '0'
28
42
  - !ruby/object:Gem::Dependency
29
- name: cutest
43
+ name: rack
30
44
  requirement: !ruby/object:Gem::Requirement
31
45
  requirements:
32
46
  - - ! '>='