Getting a user country name from originating IP address with Ruby on Rails

前端 未结 11 1530
一整个雨季
一整个雨季 2020-12-04 08:26

I want to extract a user country name from visitors\' IP addresses.

I could get the IP address with remote_ip. But what could be the easiest way to get

相关标签:
11条回答
  • 2020-12-04 08:40

    Here's a Ruby example calling the ipdata.co API.

    It's fast and has reliable performance thanks to having 10 global endpoints each able to handle >10,000 requests per second!

    This answer uses a 'test' API Key that is very limited and only meant for testing a few calls. Signup for your own Free API Key and get up to 1500 requests daily for development.

    Replace 78.8.53.5 with any ip you want to look up

    require 'rubygems' if RUBY_VERSION < '1.9'
    require 'rest_client'
    
    headers = {
      :accept => 'application/json'
    }
    
    response = RestClient.get 'https://api.ipdata.co/78.8.53.5?api-key=test', headers
    puts response
    

    That'd give you

    {
        "ip": "78.8.53.5",
        "is_eu": true,
        "city": "G\u0142og\u00f3w",
        "region": "Lower Silesia",
        "region_code": "DS",
        "country_name": "Poland",
        "country_code": "PL",
        "continent_name": "Europe",
        "continent_code": "EU",
        "latitude": 51.6557,
        "longitude": 16.089,
        "asn": "AS12741",
        "organisation": "Netia SA",
        "postal": "67-200",
        "calling_code": "48",
        "flag": "https://ipdata.co/flags/pl.png",
        "emoji_flag": "\ud83c\uddf5\ud83c\uddf1",
        "emoji_unicode": "U+1F1F5 U+1F1F1",
        "carrier": {
            "name": "Netia",
            "mcc": "260",
            "mnc": "07"
        },
        "languages": [
            {
                "name": "Polish",
                "native": "Polski"
            }
        ],
        "currency": {
            "name": "Polish Zloty",
            "code": "PLN",
            "symbol": "z\u0142",
            "native": "z\u0142",
            "plural": "Polish zlotys"
        },
        "time_zone": {
            "name": "Europe/Warsaw",
            "abbr": "CEST",
            "offset": "+0200",
            "is_dst": true,
            "current_time": "2018-08-29T15:34:23.518065+02:00"
        },
        "threat": {
            "is_tor": false,
            "is_proxy": false,
            "is_anonymous": false,
            "is_known_attacker": false,
            "is_known_abuser": false,
            "is_threat": false,
            "is_bogon": false
        },
    }
    
    0 讨论(0)
  • 2020-12-04 08:41

    You can use geoip gem.

    environment.rb

    config.gem 'geoip'
    

    Download GeoIP.dat.gz from http://www.maxmind.com/app/geolitecountry. unzip the file. The below assumes under #{RAILS_ROOT}/db dir.

    @geoip ||= GeoIP.new("#{RAILS_ROOT}/db/GeoIP.dat")    
    remote_ip = request.remote_ip 
    if remote_ip != "127.0.0.1" #todo: check for other local addresses or set default value
      location_location = @geoip.country(remote_ip)
      if location_location != nil     
        @model.country = location_location[2]
      end
    end
    
    0 讨论(0)
  • 2020-12-04 08:43

    You can try Yandex locator gem, service returns longitude, latitude and precision.

    conn = YandexLocator::Client.new
    result = conn.lookup(ip: "109.252.52.39")
    # => {"position"=>{"altitude"=>0.0, "altitude_precision"=>30.0, "latitude"=>55.75395965576172, "longitude"=>37.62039184570312, "precision"=>100000.0, "type"=>"ip"}}
    
    0 讨论(0)
  • 2020-12-04 08:44

    One service you could use to do this is my own, https://ipinfo.io. It gives you country code and a bunch of other details:

    $ curl ipinfo.io
    {
      "ip": "24.6.61.239",
      "hostname": "c-24-6-61-239.hsd1.ca.comcast.net",
      "city": "Mountain View",
      "region": "California",
      "country": "US",
      "loc": "37.3845,-122.0881",
      "org": "AS7922 Comcast Cable Communications, LLC",
      "postal": "94040"
    }
    

    If you just want the country you can get that by requesting /country

    $ curl ipinfo.io/country
    US
    

    You can then map from a country code to a name using the data from http://country.io, or using the example at http://ipinfo.io/developers/full-country-names

    0 讨论(0)
  • 2020-12-04 08:45

    The geoip gem no longer works with the new MaxMind databases. There is a new gem that does this, MaxMind-DB-Reader-ruby.

    Simply download the City or Country binary, gzipped databases from MaxMind, unzip, and use the following sort of code:

    require 'maxmind/db'
    
    reader = MaxMind::DB.new('GeoIP2-City.mmdb', mode: MaxMind::DB::MODE_MEMORY)
    
    # you probably want to replace 1.1.1.1 with  request.remote_ip
    # or request.env['HTTP_X_FORWARDED_FOR']
    ip_addr = '1.1.1.1'
    record = reader.get(ip_addr)
    if record.nil?
      puts '#{ip_addr} was not found in the database'
    else
      puts record['country']['iso_code']
      puts record['country']['names']['en']
    end
    
    reader.close
    

    Adapt based on your needs. I created a method in an initializer which I can call as necessary.

    0 讨论(0)
  • 2020-12-04 08:47

    You can also use "Geocoder"

    It will just make you life easier. Put the following line in your Gemfile and issue the bundle install command

    gem 'geocoder'
    

    Using this Gem, you can easily get the country, ip or even city of the originating IP. See an example below

    request.ip  # =>    "182.185.141.75"
    request.location.city   # =>    ""
    request.location.country    # =>    "Pakistan"
    
    0 讨论(0)
提交回复
热议问题