Skip to content

Commit

Permalink
Merge 8566af1 into f9dee5b
Browse files Browse the repository at this point in the history
  • Loading branch information
Eric Tipton committed Feb 13, 2015
2 parents f9dee5b + 8566af1 commit 14e7659
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 2 deletions.
11 changes: 11 additions & 0 deletions README.md
Expand Up @@ -719,6 +719,17 @@ Whatever::Application.config.middleware.use ExceptionNotification::Rack,

You can make use of both the environment and the exception inside the lambda to decide wether to avoid or not sending the notification.

## Rack X-Cascade Header

Some rack apps (Rails in particular) utilize the "X-Cascade" header to pass the request-handling responsibility to the next middleware in the stack.

Rails' routing middleware uses this strategy, rather than raising an exception, to handle routing errors (e.g. 404s); to be notified whenever a 404 occurs, set this option to "false."

### :ignore_cascade_pass

*Boolean, default: true*

Set to false to trigger notifications when another rack middleware sets the "X-Cascade" header to "pass."

## Background Notifications

Expand Down
18 changes: 16 additions & 2 deletions lib/exception_notification/rack.rb
@@ -1,5 +1,7 @@
module ExceptionNotification
class Rack
class CascadePassException < Exception; end

def initialize(app, options = {})
@app = app

Expand All @@ -19,18 +21,30 @@ def initialize(app, options = {})
end
end

@ignore_cascade_pass = options.delete(:ignore_cascade_pass) { true }

options.each do |notifier_name, options|
ExceptionNotifier.register_exception_notifier(notifier_name, options)
end
end

def call(env)
@app.call(env)
_, headers, _ = response = @app.call(env)

if !@ignore_cascade_pass && headers['X-Cascade'] == 'pass'
msg = "This exception means that the preceding Rack middleware set the 'X-Cascade' header to 'pass' -- in " <<
"Rails, this often means that the route was not found (404 error)."
raise CascadePassException, msg
end

response
rescue Exception => exception
if ExceptionNotifier.notify_exception(exception, :env => env)
env['exception_notifier.delivered'] = true
end
raise exception

raise exception unless exception.is_a?(CascadePassException)
response
end

private
Expand Down
20 changes: 20 additions & 0 deletions test/exception_notification/rack_test.rb
@@ -0,0 +1,20 @@
require 'test_helper'

class RackTest < ActiveSupport::TestCase

setup do
@pass_app = Object.new
@pass_app.stubs(:call).returns([nil, { 'X-Cascade' => 'pass' }, nil])
end

test "should ignore \"X-Cascade\" header by default" do
ExceptionNotifier.expects(:notify_exception).never
ExceptionNotification::Rack.new(@pass_app).call({})
end

test "should notify on \"X-Cascade\" = \"pass\" if ignore_cascade_pass option is false" do
ExceptionNotifier.expects(:notify_exception).once
ExceptionNotification::Rack.new(@pass_app, :ignore_cascade_pass => false).call({})
end

end

0 comments on commit 14e7659

Please sign in to comment.