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 +8 -8
- data/CHANGELOG.md +9 -0
- data/exception_no.gemspec +2 -1
- data/lib/exception_no.rb +29 -5
- data/test/exception_no.rb +32 -9
- data/test/middleware.rb +43 -2
- data/test/prelude.rb +44 -3
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NDMwNTRkNzExMWNiOWQ0OGQ5NzFmYmJhYmM2MTBhNGYzMWZiZWZkMg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NTY4YmJhNjUzZWU5YTJjMmUyODI5M2ZiMTVkYTZmOGJmNWE2MWIwNw==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
MDI3ZTY2NjhkYjk2NjU3ODZmNGNhNTMyNjczZDUwYWRiZDE1NmFmZjdhOWI4
|
10
|
+
YWNjYmIzYjAyMGM5MzhmOTdkMWUyMGYyNGIwNjFlMzQxMWJlMTUxMzU1ZTYx
|
11
|
+
NTU2YTc2NDY5NDBmNzAzN2I4M2RjNjlhYzA4YWY2MDUwODFkMzU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
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.
|
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,
|
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
|
-
<%=
|
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,
|
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
|
-
|
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.
|
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.
|
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.
|
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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
99
|
-
|
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.
|
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
|
-
|
8
|
-
|
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
|
+
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-
|
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:
|
43
|
+
name: rack
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
31
45
|
requirements:
|
32
46
|
- - ! '>='
|