diff options
author | Derek Prior <derekprior@gmail.com> | 2015-12-15 20:17:32 -0500 |
---|---|---|
committer | Derek Prior <derekprior@gmail.com> | 2015-12-16 11:42:05 -0500 |
commit | 13fd5586cef628a71e0e2900820010742a911099 (patch) | |
tree | b6a82887247a24b6877e63156cf002df5028c856 /actionpack/lib/action_controller/metal | |
parent | d95351236071215a931c626ec2fe7059270f606c (diff) | |
download | rails-13fd5586cef628a71e0e2900820010742a911099.tar.gz rails-13fd5586cef628a71e0e2900820010742a911099.tar.bz2 rails-13fd5586cef628a71e0e2900820010742a911099.zip |
Add `redirect_back` for safer referrer redirects
`redirect_to :back` is a somewhat common pattern in Rails apps, but it
is not completely safe. There are a number of circumstances where HTTP
referrer information is not available on the request. This happens often
with bot traffic and occasionally to user traffic depending on browser
security settings.
When there is no referrer available on the request, `redirect_to :back`
will raise `ActionController::RedirectBackError`, usually resulting in
an application error.
`redirect_back` takes a required `fallback_location` keyword argument
that specifies the redirect when the referrer information is not
available. This prevents 500 errors caused by
`ActionController::RedirectBackError`.
Diffstat (limited to 'actionpack/lib/action_controller/metal')
-rw-r--r-- | actionpack/lib/action_controller/metal/redirecting.rb | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb index 0febc905f1..72ceb9a5bc 100644 --- a/actionpack/lib/action_controller/metal/redirecting.rb +++ b/actionpack/lib/action_controller/metal/redirecting.rb @@ -75,6 +75,29 @@ module ActionController self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(location)}\">redirected</a>.</body></html>" end + # Redirects the browser to the page that issued the request if possible, + # otherwise redirects to provided default fallback location. + # + # This avoids the <tt>ActionController::RedirectBackError</tt> that can + # occur if the request has no associated <tt>HTTP_REFERER</tt>. + # + # redirect_back fallback_location: { action: "show", id: 5 } + # redirect_back fallback_location: post + # redirect_back fallback_location: "http://www.rubyonrails.org" + # redirect_back fallback_location: "/images/screenshot.jpg" + # redirect_back fallback_location: articles_url + # redirect_back fallback_location: proc { edit_post_url(@post) } + # + # All options that can be passed to <tt>redirect_to</tt> are accepted as + # options and the behavior is indetical. + def redirect_back(fallback_location:, **args) + if referer = request.headers["Referer"] + redirect_to referer, **args + else + redirect_to fallback_location, **args + end + end + def _compute_redirect_to_location(request, options) #:nodoc: case options # The scheme name consist of a letter followed by any combination of |