Rails has a convenient way of going back to the URI you just came from: redirect_to :back. Internally this redirect is done by a redirect to the referring URI using the HTTP-Referer-Header . While this is convenient and works most of the time, it relies on the fact that the client’s browser sends the referer-header field. If it doesn’t, the redirect_back method throws a RedirectBackError .

The Rails source itself suggests that we should catch this exception if we want to impelement some kind of fallback behavoir. Apparently not many people have ever done this. At least noone seemes to talk about it. So I will.

Most of the browsers will send a Referer header, but the main problem, I see, is corporate firewalls. Most of them are configured to eleminate the Referer-Header for outgoing requests. So if someone behind such a firewall tried to access your web application which is relying on a Referer-based redirect, it won’t work.

And the Referer field is optional (at least as I understand rfc2616 ).

Now for the solution I went for. It may not be perfect, but it works.

And this in your application.rb (Inspired by this post)


before_filter :jumpback
protected
  def jumpback
    session[:jumpback] = session[:jumpcurrent]
    session[:jumpcurrent] = request.request_uri
  end  

 def rescue_action_in_public(exception)
    case exception
     when ::ActionController::RedirectBackError
       jumpto = session[:jumpback] || {:controller => "/my_overview"}
       redirect_to jumpto
     else
       super
     end
  end

Now the redirect_to :back will work without referer header.

Update: It’s obviously a bad idea to overwrite rescue_action in ActionController::Base. And it’s not really neccessary. There’s rescue_action_in_public for exactly that purpose. I updated the code above to reflect that change.

Related Posts