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