How redirect_to works in Rails?

gvpmahesh

vamsi pavan mahesh gunturu

Posted on May 7, 2020

How redirect_to works in Rails?

If you are a Rails developer, chances are you have already used redirect_to bunch of times. But have you ever wondered, how it works?

Suppose if you put this in your controller code and set the appropriate routing

def index
  redirect_to "https://www.google.com"
end
Enter fullscreen mode Exit fullscreen mode

Your browser will redirect you to google.com, which is fine. But how does your browser know to redirect to google.com?

The magic lies here https://github.com/rails/rails/blob/b738f1930f3c82f51741ef7241c1fee691d7deb2/actionpack/lib/action_controller/metal/redirecting.rb#L58

The code is this

    def redirect_to(options = {}, response_options = {})
      raise ActionControllerError.new("Cannot redirect to nil!") unless options
      raise AbstractController::DoubleRenderError if response_body

      self.status        = _extract_redirect_to_status(options, response_options)
      self.location      = _compute_redirect_to_location(request, options)
      self.response_body = "<html><body>You are being <a href=\"#{ERB::Util.unwrapped_html_escape(response.location)}\">redirected</a>.</body></html>"
    end
Enter fullscreen mode Exit fullscreen mode

Basically, the above code is setting the status as 302 by default. And location header to https://www.google.com. And the response body to

You are being <a href="https://www.google.com">redirected</a>.

So when the browser receives a status of 3xx with a location header, it redirects!

In the browser, if you see the network, it looks like this

Alt Text

As you can see it's setting the status to 302
and Location to https://www.google.com

I was unsuccessful in seeing the response body in the browser, maybe that's just the browser's behavior. Someone can confirm this?

But I could see response body in curl request

It looks like this

curl http://localhost:3000 -v
* Rebuilt URL to: http://localhost:3000/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 3000 (#0)
> GET / HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 302 Found
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Download-Options: noopen
< X-Permitted-Cross-Domain-Policies: none
< Referrer-Policy: strict-origin-when-cross-origin
< Location: https://www.google.com
< Content-Type: text/html; charset=utf-8
< Cache-Control: no-cache
< X-Request-Id: 660668ae-1176-4770-8e82-a6bb303efbbc
< X-Runtime: 0.029982
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact
<html><body>You are being <a href="https://www.google.com">redirected</a>.</body></html>%
Enter fullscreen mode Exit fullscreen mode

So with our new-found knowledge, how about making our own redirect_to behaviour in Rails? All we need to do is set a status and Location header

def index
  render plain: "You are being redirected to google.com", status: 302
  response.headers['Location'] = 'https://www.google.com'
end
Enter fullscreen mode Exit fullscreen mode

The above method also works like redirect_to but looks a little ugly. But who cares :p

You can read more about how redirect works here https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections

💖 💪 🙅 🚩
gvpmahesh
vamsi pavan mahesh gunturu

Posted on May 7, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related