DEV Community

vamsi pavan mahesh gunturu
vamsi pavan mahesh gunturu

Posted on • Edited on

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

Top comments (4)

Collapse
 
vishaltps profile image
vishaltps

Great post. Really liked it.

Collapse
 
cescquintero profile image
Francisco Quintero 🇨🇴

Great! I love this kind of post where people dissect Rails methods. Thanks for sharing!

Collapse
 
gvpmahesh profile image
vamsi pavan mahesh gunturu

Glad you liked it, after getting comfortable with Rails, one has to look at what the magic is getting translated to!

Collapse
 
versacodes profile image
Franz Amersian

Saw this gem of an article. I know this is and old post but still helps. Thanks for this!