3 April Finding the correct IP address in Rails
Today, I have added a server switch to Floorplanner.com. Now, it will load the floorplanner elements from the server that is nearest to you, which can yield a significant improvement in the initial loading time of your floorplans.
To determine your location, your IP address is matched against a table of locations. This worked fine in our development version, but it didn’t work at all on the production server. After some searching, I found that our server configuration was causing this. We use Apache as our web server, which uses mod_proxy to send the request to our Mongrel cluster. This intermediary step caused the IP address that Rails would receive to always be the IP address of the Apache server: 127.0.0.1. Therefore, the location matching did not work.
However, I found that mod_proxy adds an additional header to the request with the original IP address: HTTP_X_FORWARDED_FOR. This header can be used for our purpose. Now, I use the following function to determine the correct IP address:
1 2 3 4 5 | def determine_ip(request) # use HTTP_X_FORWARDED_FOR if available # otherwise fall back to default header request.env["HTTP_X_FORWARDED_FOR"] || request.remote_addr end |
On a related note: to match an IP address against ranges of IP addresses in our location table, it must be converted from a string (”1.2.3.4″) to a number (16909060). I use the following oneliner, which uses some nice functional programming tricks and an application of bit-shifting:
1 2 3 4 | def numeric_ip(ip_str) ip_str.split('.').inject(0) { |ip_num, part| ( ip_num << 8 ) + part.to_i } end |
Yes, I am really proud if this function!
UPDATE: I just found out that request.remote_ip does the same as my determine_ip-function. Unfortunately, it only works in Rails 2.0.
2 Comments - Tags: ip adress, proxy, rails


