Techblog

Tech Blog

Our latest geek adventures!

Posts Tagged ‘ip adress’

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: , ,