Last active
June 3, 2023 00:05
-
-
Save mreinsch/4460446 to your computer and use it in GitHub Desktop.
the way we are catching errors and rendering custom error pages for http://www.doorkeeperhq.com/
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: UTF-8 | |
# | |
# This file is in: lib/rescue_from_defaults.rb | |
# | |
# To use it, include the RescueFromDefaults in the ApplicationController (see below for example) | |
# | |
# To test it we are using rspec and steak. See below for examples. | |
# | |
class AccessDenied < RuntimeError | |
end | |
class ResourceGone < RuntimeError | |
end | |
module RescueFromDefaults | |
def self.catch_all_404_route_installed | |
@catch_all_404_route_installed | |
end | |
def self.catch_all_404_route_installed! | |
@catch_all_404_route_installed = true | |
end | |
def self.included(base) | |
base.rescue_from ::Exception, :with => :handle_internal_server_error | |
base.rescue_from ::ActionController::RoutingError, :with => :handle_not_found | |
base.rescue_from ::ActionController::UnknownController, :with => :handle_not_found | |
base.rescue_from ::AbstractController::ActionNotFound, :with => :render_not_found | |
base.rescue_from ::ActiveRecord::RecordNotFound, :with => :handle_not_found | |
base.rescue_from ::AccessDenied, :with => :handle_access_denied | |
base.rescue_from ::ResourceGone, :with => :handle_resource_gone | |
# 404 catch all route if not already installed | |
unless RescueFromDefaults.catch_all_404_route_installed | |
Rails.application.config.after_initialize do |app| | |
Rails.logger.debug "installing 404 catch all route" | |
app.routes.append { match '*path' => 'application#not_found' } | |
end | |
RescueFromDefaults.catch_all_404_route_installed! | |
end | |
end | |
# for "catch it all" route | |
def not_found | |
head_or_file(:not_found) | |
end | |
private | |
def handle_not_found(err) | |
logger.warn("not found: #{err}") | |
raise err if local_request? | |
head_or_file(:not_found) | |
end | |
def handle_resource_gone(err) | |
logger.warn("resource gone: #{err}") | |
raise err if local_request? | |
head_or_file(:gone) | |
end | |
def handle_access_denied(err) | |
logger.warn("access denied: #{err}") | |
raise err if local_request? | |
send_error_notifications(err) | |
head_or_file(:forbidden) | |
end | |
def handle_internal_server_error(err) | |
logger.warn("internal server error: #{err}") | |
raise err if local_request? | |
send_error_notifications(err) | |
head_or_file(:internal_server_error) | |
end | |
def local_request? | |
Rails.application.config.consider_all_requests_local || request.local? | |
end | |
def send_error_notifications(err) | |
notify_coalmine(err) | |
NewRelic::Agent.notice_error(err) | |
end | |
def head_or_file(status_code) | |
respond_to do |f| | |
f.html { render :file => "exceptions/#{status_code}", :status => status_code, :layout => "exceptions" } | |
f.any { head status_code } | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# example usge in ApplicationController | |
require "rescue_from_defaults" | |
class ApplicationController < ActionController::Base | |
include RescueFromDefaults | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: UTF-8 | |
# for acceptance tests using rspec and steak | |
module ErrorPagesHelperMethods | |
module RspecHelper | |
def with_error_pages_enabled(&block) | |
context "enabled error pages" do | |
around(:each) do |example| | |
begin | |
ActionDispatch::Request.force_not_local = true | |
example.call | |
ensure | |
ActionDispatch::Request.force_not_local = false | |
# workaround for rails issue | |
ActiveRecord::Base.connection.disable_query_cache! | |
end | |
end | |
block.bind(self).call | |
end | |
end | |
end | |
module RequestExtension | |
def self.included(klass) | |
Rails.application.config.consider_all_requests_local = false | |
klass.class_eval do | |
# set this to true if you want to get error pages | |
cattr_accessor :force_not_local | |
remove_method :local? | |
def local? | |
! self.class.force_not_local | |
end | |
end | |
end | |
end | |
end | |
RSpec.configuration.extend ErrorPagesHelperMethods::RspecHelper, :type => :acceptance | |
ActionDispatch::Request.send(:include, ErrorPagesHelperMethods::RequestExtension) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: UTF-8 | |
# for acceptance tests using rspec and steak | |
require "acceptance/acceptance_helper" | |
ApplicationController.class_eval do | |
before_filter :test_error | |
def test_error | |
if params[:test_error] == 'internal' | |
raise "testing error" | |
elsif params[:test_error] == 'RecordNotFound' | |
raise ActiveRecord::RecordNotFound | |
elsif params[:test_error] == 'AccessDenied' | |
raise AccessDenied | |
elsif params[:test_error] == 'ResourceGone' | |
raise ResourceGone | |
end | |
end | |
end | |
feature "errors" do | |
with_error_pages_enabled do | |
scenario "visiting page that doesn't exist" do | |
visit "http://www.doorkeeperhq.com/foobar" | |
page.status_code.should == 404 | |
page.find("#main h1").text.should == "The page you were looking for doesn't exist." | |
page.find("title").text.should match("404") | |
end | |
scenario "visiting page that doesn't exist with non-standard format" do | |
visit "http://www.doorkeeperhq.com/foobar.gif" | |
page.status_code.should == 404 | |
end | |
scenario "visiting page with internal error" do | |
visit "http://www.doorkeeperhq.com/?test_error=internal" | |
page.status_code.should == 500 | |
page.find("#main h1").text.should == "We're sorry, but something went wrong." | |
page.find("title").text.should match("500") | |
end | |
scenario "visiting page with record not found" do | |
visit "http://www.doorkeeperhq.com/?test_error=RecordNotFound" | |
page.status_code.should == 404 | |
page.find("#main h1").text.should == "The page you were looking for doesn't exist." | |
page.find("title").text.should match("404") | |
end | |
scenario "visiting page with AccessDenied" do | |
visit "http://www.doorkeeperhq.com/?test_error=AccessDenied" | |
page.status_code.should == 403 | |
page.find("#main h1").text.should == "We're sorry, but you don't have access to this resource." | |
page.find("title").text.should match("403") | |
end | |
scenario "visiting page with ResourceGone" do | |
visit "http://www.doorkeeperhq.com/?test_error=ResourceGone" | |
page.status_code.should == 410 | |
page.find("#main h1").text.should == "We're sorry, but this resource no longer exists." | |
page.find("title").text.should match("410") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment