I don't use sentry, just replace p
with whatever command for sentry. But I can make up for it with 3 solutions:
Rescue
For production only, this is required: config.consider_all_requests_local = false
.
# config/initializers/report_routing_error.rb
class ReportRoutingErrorMiddleware
def initialize app
@app = app
end
def call(env)
@app.call(env)
rescue ActionController::RoutingError => e
p ["NOT FOUND", e]
raise
end
end
# DebugExceptions raises RoutingError when consider_all_requests_local is false
# insert_before - to catch the error
Rails.application.config.middleware.insert_before ActionDispatch::DebugExceptions, ReportRoutingErrorMiddleware
#=> ["NOT FOUND", #<ActionController::RoutingError: No route matches [GET] "/asdf">]
404
In development, DebugExceptions
middleware technically raises the error but it also rescues it and renders the full error page. Until response gets to that middleware it is just a 404 response from the router:
https://github.com/rails/rails/blob/v7.0.7/actionpack/lib/action_dispatch/routing/route_set.rb#L37
# config/initializers/report_routing_error.rb
class ReportRoutingErrorMiddleware
def initialize app
@app = app
end
def call(env)
status, headers, body = response = @app.call(env)
if status == 404
# no error, so get what you need from env
p ["NOT FOUND", env["REQUEST_METHOD"], env["PATH_INFO"]]
end
response
end
end
# insert_after - to get response first, because it doesn't go past DebugExceptions
Rails.application.config.middleware.insert_after ActionDispatch::DebugExceptions, ReportRoutingErrorMiddleware
#=> ["NOT FOUND", "GET", "/asdf"]
Intercept
Apparently, they've figured it out a long time ago register_interceptor
:
# config/initializers/report_routing_error.rb
ActionDispatch::DebugExceptions.register_interceptor do |req, exception|
if exception.is_a? ActionController::RoutingError
p ["NOT FOUND", req, exception]
end
end
#=> ["NOT FOUND", #<ActionDispatch::Request GET "http://0.0.0.0:3000/asdf" for 127.0.0.1>, #<ActionController::RoutingError: No route matches [GET] "/asdf">]
Introduce ActionDispatch::DebugExceptions.register_interceptor
, a way to hook into DebugExceptions
and process the exception, before being rendered.
https://github.com/rails/rails/pull/23868