vamsi pavan mahesh gunturu
Posted on May 7, 2020
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
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
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
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>%
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
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
Posted on May 7, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.