Geocoder, how to test locally when ip is 127.0.0.1?
Asked Answered
C

6

13

I can't get geocoder to work correct as my local ip address is 127.0.0.1 so it can't located where I am correctly.

The request.location.ip shows "127.0.0.1"

How can I use a different ip address (my internet connection ip) so it will bring break more relevant data?

Cotoneaster answered 24/5, 2011 at 19:11 Comment(0)
I
21

A nice clean way to do it is using MiddleWare. Add this class to your lib directory:

# lib/spoof_ip.rb

class SpoofIp
  def initialize(app, ip)
    @app = app
    @ip = ip
  end

  def call(env)
    env['HTTP_X_FORWARDED_FOR'] = nil
    env['REMOTE_ADDR'] = env['action_dispatch.remote_ip'] = @ip
    @status, @headers, @response = @app.call(env)
    [@status, @headers, @response]
  end
end

Then find an IP address you want to use for your development environment and add this to your development.rb file:

config.middleware.use('SpoofIp', '64.71.24.19')
Incapacious answered 18/1, 2012 at 20:51 Comment(7)
probably a noob point, but you would have to add something in eg config/application.rb to auto load that class, eg: config.autoload_paths += Dir["#{config.root}/lib/**/"]Gagman
I tried this method ages ago was worked amazingly. Tried it again recently on another app didnt work. About 2 hours later i tried downgrading the version of geocoder... and it worked! Version of geocoder i did it with originally was 1.1.2 version i installed today was 1.1.6 so something must have changed within these versionsAnatollo
@DickieBoy, you're right, that method doesn't work with Geocoder 1.1.6 due to the following change. The solution makes env['HTTP_X_FORWARDED_FOR'] = nil, but it doesn't delete the key from the hash so it gets selected by the location method and a search for nil is performed by geocoder. Commenting that line works in my case.Proser
FWIW I can confirm @deivid's above fix for Rails 4.0.0 using the Geocoder 1.1.8 gem. Following @Ruckstar's answer and commenting out the line env['HTTP_X_FORWARDED_FOR'] = nil does the trick.Tears
It doesn't work for me, with or without commenting out the Jason line, I meet the following error : .rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.0.rc1/lib/active_support/inflector/methods.rb:226:in 'const_get': uninitialized constant SpoofIp (NameError)Pedicure
This works in rails 4, either add the autoload path for lib or move it into the initializer directory.Glennisglennon
If you're running into issues try reloading spring (if you're using it). That fixed it for meUrochrome
R
5

For this I usually use params[:ip] or something in development. That allows me to test other ip addresses for functionality and pretend I'm anywhere in the world.

For example

class ApplicationController < ActionController::Base
  def request_ip
    if Rails.env.development? && params[:ip]
      params[:ip]
    else
      request.remote_ip
    end 
  end
end
Rattlebrain answered 24/5, 2011 at 19:37 Comment(2)
I'm unfamiliar with "geocoder" which I assume is a gem or something, but I imagine there's some way to configure it. I use GeoIP for geocoding : geoip.rubyforge.org and that's easy enough to work with using this method.Rattlebrain
You're in a development environment, so there's no way to use the real requests ip address. You need to find someway to tell "geocoder" that in development it should use another value.Rattlebrain
U
4

I implemented this slightly different, and this works well for my case.

In application_controller.rb i have a lookup method which calls the Geocoder IP lookup directly passing in the results of request.remote_ip.

def lookup_ip_location
  if Rails.env.development?
    Geocoder.search(request.remote_ip).first
  else
    request.location
  end
end

Then in config/environments/development.rb i monkey-patched the remote_ip call:

class ActionDispatch::Request
  def remote_ip
    "71.212.123.5" # ipd home (Denver,CO or Renton,WA)                                                                                                                                                                                                                                                                        
    # "208.87.35.103" # websiteuk.com -- Nassau, Bahamas                                                                                                                                                                                                                                                                      
    # "50.78.167.161" # HOL Seattle, WA                                                                                                                                                                                                                                                                                       
  end
end

I just hard code some addresses, but you could do whatever you'd like here.

Underwaist answered 11/6, 2013 at 0:46 Comment(1)
I found that to get request.location to work properly I had to modify this answer to rename the lookup_ip_location method to just location and place it within that ActionDispatch::Request class.Porbeagle
A
1

I had the same question. Here is how I implemented with geocoder.

#gemfile
gem 'httparty', :require => 'httparty', :group => :development 

#application_controller
def request_ip
  if Rails.env.development? 
     response = HTTParty.get('http://api.hostip.info/get_html.php')
     ip = response.split("\n")
     ip.last.gsub /IP:\s+/, ''      
   else
     request.remote_ip
   end 
end

#controller
ip = request_ip
response = Geocoder.search(ip)

( code part with hostip.info from geo_magic gem, and based on the other answer to this question. )

now you can do something like response.first.state

Anisette answered 21/6, 2011 at 22:16 Comment(0)
C
1

This is an updated answer for geocoder 1.2.9 to provide a hardcoded IP for development and test environments. Just place this at the bottom of your config/initilizers/geocoder.rb:

if %w(development test).include? Rails.env
  module Geocoder
    module Request
      def geocoder_spoofable_ip_with_localhost_override
        ip_candidate = geocoder_spoofable_ip_without_localhost_override
        if ip_candidate == '127.0.0.1'
          '1.2.3.4'
        else
          ip_candidate
        end
      end
      alias_method_chain :geocoder_spoofable_ip, :localhost_override
    end
  end
end
Chauncey answered 24/8, 2015 at 20:16 Comment(1)
alias_method_chain is deprecated in Rails 5, so this answer is not actual anymorePoi
R
-1

you may also do this

request.safe_location
Rondure answered 10/3, 2016 at 5:12 Comment(1)
This returns the same result as request.location for me. What difference are you seeing?Kwarteng

© 2022 - 2024 — McMap. All rights reserved.