Exception Pages when behind a proxy

I am not sure if this desired feature or not but when we are behind a local proxy ie. Nginx/Varnish then the new ShowException middleware doesn't seem to properly detect the remote IP address and it appears as if every browser gets a local error page with a stack trace, etc.

I've opened up a ticket on the rails bug tracker but I also would like to verify that this is in fact a problem.

The bug is here: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/5166-actiondispatchshowexception-always-calls-rescue_action_locally-if-there-is-a-reverse_proxy

I believe there is a workaround - you could use rescue_from with StandardError but then you are having to reproduce the exception type to http error code logic. I also think this issue will/should be affecting a bunch of other users as well.

Thanks, Adam

I took a quick glance at http://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/remote_ip.rb, and if I understand your description of the problem on the ticket, it may very well be the same old behavior that's been in Rails for ages. I wrote about it in detail a couple of years ago (at http://metautonomo.us/2008/05/30/the-local_request-that-isnt/) but the short version is that Rails removes IPs that are on reserved subnets (see the regexp in the initialize method on GitHub) when checking for a remote IP. Since you mention that you encounter the problem on your staging server (presumably being tested from your internal network), you may be running into this.

-Ernie

Thanks Ernie.

I should have provided some links and specific code segments in detail...

The middleware in question is this one: http://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/show_exceptions.rb

If you take a look at the call method you can see that it wraps all exceptions and basically calls the #render_exception method which boils down to this if statement (same statement from the rails 2.X branch):

        if @consider_all_requests_local || local_request?(request)           rescue_action_locally(request, exception)         else           rescue_action_in_public(exception)         end

Now, the @consider_all_request_local gets set from the standard config value but the local_request? method is only available in this middleware and looks like this:

      LOCALHOST = [/^127\.0\.0\.\d{1,3}$/, "::1", / ^0:0:0:0:0:0:0:1(%.*)?$/].freeze       def local_request?(request)         LOCALHOST.any? { |local_ip| local_ip === request.remote_addr && local_ip === request.remote_ip }       end

Even though Rails has the nice RemoteIP middleware it isn't useful here for a couple of reasons:

1. All the RemoteIP middleware does is set it in the env hash as 'action_dispatch.remote_ip' which does get used further upstream in the actual controllers but not in the ShowException middleware 2. The RemoteIP Middleware comes after the ShowException middleware in the default rails stack

I think the ultimate problem and bug with the Rails3 refactor into middleware is that there is no easy way to override this default because it is not a method on the ActionController::Base but buried deep in the middleware stack. It is also not exposed via a configuration setting.

Thanks, Adam