rack-geoipcity 0.0.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +49 -1
- data/CHANGES.md +11 -0
- data/Gemfile +16 -0
- data/README.md +56 -0
- data/Rakefile +6 -0
- data/examples/config.ru +41 -0
- data/examples/views/layout.haml +15 -0
- data/lib/rack/geoipcity.rb +40 -57
- data/lib/rack/geoipcity/version.rb +2 -2
- data/rack-geoipcity.gemspec +1 -0
- data/spec/geoipcity_spec.rb +41 -0
- data/spec/spec_helper.rb +45 -0
- data/spec/support/shared/app.rb +58 -0
- metadata +41 -15
- data/README +0 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 20d4c9f7f5da4c49e72e3109eb566a57fa37f53c
|
4
|
+
data.tar.gz: 9090d1130020227c502a0b9b7fb2abd6fadee717
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1fba05767d17158dc0f3a2f8d662f6f813737397b08d315f3e55558a726389f51aa35a81152e41f36cf266cff76811fa24be03442d8b53ca0d813ad54bb51b95
|
7
|
+
data.tar.gz: a4697c3cfa17d1a78ab7bbfbd776ff051c9e5092e21ccc9aff7775ec1f5f3d6d591669f7073a711712321690f24bb0740c6c74428c2899d0b23d56d9fb1cbed0
|
data/.gitignore
CHANGED
@@ -1,3 +1,51 @@
|
|
1
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
2
|
+
#
|
3
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
4
|
+
# or operating system, you probably want to add a global ignore instead:
|
5
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
6
|
+
.bundle
|
7
|
+
db/*.sqlite3*
|
8
|
+
log/*.log
|
9
|
+
*.log
|
10
|
+
/tmp/
|
11
|
+
doc/
|
12
|
+
docs/
|
13
|
+
.yardoc/
|
14
|
+
*.swp
|
15
|
+
*~
|
16
|
+
.project
|
1
17
|
.DS_Store
|
18
|
+
.rvm
|
19
|
+
.DS_Store
|
20
|
+
*.log
|
21
|
+
*.swp
|
22
|
+
*.db
|
23
|
+
*.old
|
24
|
+
photos/
|
25
|
+
attachments/
|
26
|
+
.sass-cache/
|
27
|
+
run/
|
28
|
+
spec/fixtures/images/
|
29
|
+
spec/html/
|
2
30
|
.rvmrc
|
3
|
-
|
31
|
+
.bundle
|
32
|
+
db/*.sqlite3*
|
33
|
+
log/*.log
|
34
|
+
*.log
|
35
|
+
/tmp/
|
36
|
+
doc/
|
37
|
+
*.swp
|
38
|
+
*~
|
39
|
+
.project
|
40
|
+
.rspec
|
41
|
+
vendor/ruby/
|
42
|
+
vendor.noindex
|
43
|
+
bin/
|
44
|
+
db/backups/
|
45
|
+
*.rdb
|
46
|
+
config/redis.conf
|
47
|
+
Gemfile.lock
|
48
|
+
*.gem
|
49
|
+
examples/assets/GeoLiteCity.dat
|
50
|
+
spec/support/assets/GeoLiteCity.dat
|
51
|
+
coverage/
|
data/CHANGES.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# A sample Gemfile
|
2
|
+
source "https://rubygems.org"
|
3
|
+
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem "haml"
|
8
|
+
gem "simplecov"
|
9
|
+
gem "yard"
|
10
|
+
gem "rake"
|
11
|
+
gem "redcarpet"
|
12
|
+
gem "rspec"
|
13
|
+
gem "rspec-its"
|
14
|
+
gem "rack-test"
|
15
|
+
gem "rack-fake_ip", :git => "git://github.com/yb66/rack-fake_ip.git", :branch => "master"
|
16
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
## Rack GeoIPCity ##
|
2
|
+
|
3
|
+
Rack::GeoIPCity uses the geoip gem and the GeoIP database to lookup the geographical info of a request by its IP address.
|
4
|
+
The database can be downloaded from:
|
5
|
+
|
6
|
+
(Lite version) http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz, instructions are here http://www.maxmind.com/app/geolitecity.
|
7
|
+
|
8
|
+
http://www.maxmind.com/app/city for full version.
|
9
|
+
|
10
|
+
*NOTE!* If you're using the country database you'll get a different struct returned, so use the GeoIPCountry gem, rack-geoipcountry. I'd make this middleware do both but:
|
11
|
+
|
12
|
+
a) It would be slower
|
13
|
+
b) there's already a country gem and
|
14
|
+
c) you can do the branching yourself if you really want, but why would you?
|
15
|
+
|
16
|
+
## Usage: ##
|
17
|
+
|
18
|
+
`use Rack::GeoIPCity, :db => "path/to/GeoIP.dat"`
|
19
|
+
|
20
|
+
By default all requests are looked up and the X_GEOIP_* headers are added to the request. The headers can then be read in the application.
|
21
|
+
The country name is added to the request header as `X_GEOIP_COUNTRY`, eg:
|
22
|
+
`X_GEOIP_COUNTRY: United Kingdom`
|
23
|
+
|
24
|
+
The full set of GEOIP request headers is below:
|
25
|
+
`X_GEOIP_COUNTRY_CODE` - The ISO3166-1 two-character country code, if not found set to --
|
26
|
+
`X_GEOIP_COUNTRY_CODE3` - The ISO3166-2 three-character country code, if not found set to --
|
27
|
+
`X_GEOIP_COUNTRY` - The ISO3166 English-language name of the country, if not found set to an empty string
|
28
|
+
`X_GEOIP_CONTINENT` if not found set to an empty string
|
29
|
+
`X_GEOIP_REGION_NAME` if not found set to an empty string
|
30
|
+
`X_GEOIP_CITY_NAME` if not found set to an empty string
|
31
|
+
`X_GEOIP_POSTAL_CODE` if not found set to an empty string
|
32
|
+
`X_GEOIP_LATITUDE` if not found won't be returned as I can't think of another good return value to signify "not found"
|
33
|
+
`X_GEOIP_LONGITUDE` if not found won't be returned as I can't think of another good return value to signify "not found"
|
34
|
+
`X_GEOIP_DMA_CODE` The metropolitan code (this is for the USA, see http://code.google.com/apis/adwords/docs/appendix/metrocodes.html if you're interested), default 0 for not found.
|
35
|
+
`X_GEOIP_AREA_CODE` if not found set to an empty string
|
36
|
+
`X_GEOIP_TIMEZONE` if not found set to an empty string
|
37
|
+
`X_GEOIP_CONTINENT` - The two-character continent code, if not found set to an empty string
|
38
|
+
|
39
|
+
|
40
|
+
You can use the included Mapping class to trigger lookup only for certain requests by specifying matching path prefix in options, eg:
|
41
|
+
`use Rack::GeoIPCity::Mapping, :prefix => '/video_tracking'`
|
42
|
+
The above will lookup IP addresses only for requests matching `/video_tracking` etc.
|
43
|
+
|
44
|
+
## Running the specs and examples ##
|
45
|
+
|
46
|
+
You'll need a copy of the database, so download it and place it in:
|
47
|
+
|
48
|
+
* examples/assets for the examples
|
49
|
+
* spec/support/assets for the specs
|
50
|
+
|
51
|
+
## License ##
|
52
|
+
|
53
|
+
MIT License -
|
54
|
+
Originally by Karol Hosiawa ( http://twitter.com/hosiawak )
|
55
|
+
Converted to a gem by Thomas Maurer
|
56
|
+
This one by Iain Barnett
|
data/Rakefile
ADDED
data/examples/config.ru
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
Bundler.require
|
6
|
+
|
7
|
+
|
8
|
+
require 'rack/geoipcity'
|
9
|
+
require 'haml'
|
10
|
+
|
11
|
+
root = File.expand_path File.dirname(__FILE__)
|
12
|
+
|
13
|
+
# everything was moved into a separate module/file to make it easier to set up tests
|
14
|
+
|
15
|
+
class FakeIps
|
16
|
+
def ip
|
17
|
+
@ips.sample
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@ips = ["87.237.57.28","89.145.84.82","119.63.193.39","122.152.129.9","193.26.222.136","202.165.96.142","209.198.242.61","212.209.54.40","216.239.41.97"]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
use Rack::GeoIPCity, :db => File.join(root, "assets/GeoLiteCity.dat"), :ips => FakeIps.new#, :path => %r{^/geo}#, :prefix => "/ge"
|
26
|
+
|
27
|
+
|
28
|
+
layout = ->(){
|
29
|
+
File.read File.join(root, "views/layout.haml" )
|
30
|
+
}
|
31
|
+
|
32
|
+
app = lambda do |env|
|
33
|
+
request = Rack::Request.new(env)
|
34
|
+
stuff_here = env.select{|x| x =~ /^GEOIP/ }.inspect
|
35
|
+
output = Haml::Engine.new(layout.call).render( Object.new,
|
36
|
+
:stuff_here => stuff_here
|
37
|
+
)
|
38
|
+
Rack::Response.new( output ).finish
|
39
|
+
end
|
40
|
+
|
41
|
+
run app
|
data/lib/rack/geoipcity.rb
CHANGED
@@ -2,68 +2,51 @@ require 'geoip'
|
|
2
2
|
|
3
3
|
module Rack
|
4
4
|
|
5
|
-
# See the README for more docs
|
5
|
+
# See the README for more docs.
|
6
|
+
# @example
|
7
|
+
# use Rack::GeoIPCity, :db => "/PATH/TO/GeoLiteCity.dat")
|
6
8
|
class GeoIPCity
|
9
|
+
|
10
|
+
# Setting the db. Let the app do this, hands away!
|
11
|
+
# @param [GeoIP] :db
|
12
|
+
def self.db=( db )
|
13
|
+
@db = db
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Use this from another app, say a Sinatra or Rack app, when you want to use the GeoIP database for something other than the referrer's IP.
|
18
|
+
# @return [GeoIP]
|
19
|
+
def self.db
|
20
|
+
@db
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param [Hash] options
|
24
|
+
# @option options [String] :db Path to the GeoIP database
|
25
|
+
# @option options [#ip] :ips ('Rack::Request.new(env)') An object that responds to `ip` and gives an IP address. You'll probably want to use this when you're developing/testing locally and want to pass in fake addresses to get the GeoIP to fire something other than blanks.
|
26
|
+
# @option options [Regexp] :path
|
27
|
+
# @option options [String] :prefix
|
7
28
|
def initialize(app, options = {})
|
8
29
|
options[:db] ||= 'GeoIP.dat'
|
9
|
-
@
|
10
|
-
@
|
30
|
+
@ips = options[:ips]
|
31
|
+
@path = ->(env){ env['PATH_INFO'].start_with? options[:prefix] } unless options[:prefix].nil?
|
32
|
+
@path = ->(env){ env['PATH_INFO'] =~ options[:path] } unless options[:path].nil?
|
33
|
+
@path ||= ->(_){ true }
|
34
|
+
self.class.db = GeoIP.new(options[:db])
|
35
|
+
@app = app
|
11
36
|
end
|
12
|
-
|
13
|
-
DEFAULTS = {
|
14
|
-
'X_GEOIP_COUNTRY_CODE' => 0,
|
15
|
-
'X_GEOIP_COUNTRY_CODE3' => 0,
|
16
|
-
'X_GEOIP_COUNTRY' => '',
|
17
|
-
'X_GEOIP_CONTINENT' => '',
|
18
|
-
'X_GEOIP_REGION_NAME' => '',
|
19
|
-
'X_GEOIP_CITY_NAME' => '',
|
20
|
-
'X_GEOIP_POSTAL_CODE' => '' ,
|
21
|
-
'X_GEOIP_LATITUDE' => nil,
|
22
|
-
'X_GEOIP_LONGITUDE' => nil,
|
23
|
-
'X_GEOIP_DMA_CODE' => 0,
|
24
|
-
'X_GEOIP_AREA_CODE' => 0,
|
25
|
-
'X_GEOIP_TIMEZONE' => '',
|
26
|
-
}
|
27
|
-
|
37
|
+
|
28
38
|
def call(env)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
hash['X_GEOIP_CITY_NAME'] = res.city_name unless res.city_name.nil?
|
39
|
-
hash['X_GEOIP_POSTAL_CODE'] = res.postal_code unless res.postal_code.nil?
|
40
|
-
hash['X_GEOIP_LATITUDE'] = res.latitude
|
41
|
-
hash['X_GEOIP_LONGITUDE'] = res.longitude
|
42
|
-
hash['X_GEOIP_DMA_CODE'] = res.dma_code unless res.dma_code.nil?
|
43
|
-
hash['X_GEOIP_AREA_CODE'] = res.area_code unless res.area_code.nil?
|
44
|
-
hash['X_GEOIP_TIMEZONE'] = res.timezone unless res.timezone.nil?
|
45
|
-
|
46
|
-
hash.delete_if{|k,v| v.nil? } # remove latitude and longitude and any other stragglers
|
47
|
-
env.merge!( DEFAULTS.merge hash )
|
48
|
-
end
|
49
|
-
|
39
|
+
if @path.call(env)
|
40
|
+
ips = @ips || Rack::Request.new(env)
|
41
|
+
res = self.class.db.city ips.ip
|
42
|
+
unless res.nil? # won't bork on local or bad ip's
|
43
|
+
h = Hash[ [:country_code2, :country_code3, :country_name, :continent_code, :region_name, :city_name, :postal_code, :latitude, :longitude, :dma_code, :area_code, :timezone, :ip,].map{|x| [ "GEOIP_#{x.upcase}", res.__send__(x) ] } ].delete_if{|k,v| v.nil? }
|
44
|
+
|
45
|
+
env.merge! h
|
46
|
+
end
|
47
|
+
end
|
50
48
|
@app.call(env)
|
51
49
|
end
|
52
|
-
|
53
|
-
class Mapping
|
54
|
-
def initialize(app, options = {})
|
55
|
-
@app, @prefix = app, /^#{options.delete(:prefix)}/
|
56
|
-
@geoip = GeoIPCity.new(app, options)
|
57
|
-
end
|
58
|
-
|
59
|
-
def call(env)
|
60
|
-
if env['PATH_INFO'] =~ @prefix
|
61
|
-
@geoip.call(env)
|
62
|
-
else
|
63
|
-
@app.call(env)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
50
|
|
68
|
-
end
|
69
|
-
end
|
51
|
+
end # GeoIPCity
|
52
|
+
end # Rack
|
data/rack-geoipcity.gemspec
CHANGED
@@ -13,6 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.description = %q{Rack::GeoIPCity uses the geoip gem and the GeoIP database to lookup the city of a request by its IP address}
|
14
14
|
s.license = 'MIT'
|
15
15
|
|
16
|
+
s.add_dependency 'rack'
|
16
17
|
s.add_dependency 'geoip'
|
17
18
|
|
18
19
|
s.files = `git ls-files`.split("\n")
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
|
5
|
+
describe "A normal route" do
|
6
|
+
# set a known static ip to help with testing
|
7
|
+
# i.e. Wikipedia
|
8
|
+
include_context "All routes", :ip => "208.80.152.201"
|
9
|
+
before do
|
10
|
+
get "/"
|
11
|
+
end
|
12
|
+
it_should_behave_like "Any route"
|
13
|
+
subject { Marshal.load last_response.body }
|
14
|
+
it { should respond_to :keys }
|
15
|
+
its(:keys) { should include "country_code2", "country_code3", "country_name", "continent_code", "region_name", "city_name", "postal_code", "latitude", "longitude", "timezone", "ip" }
|
16
|
+
its(:values) { should include "US", "USA", "United States", "NA", "CA", "San Francisco", "94105", 37.789800000000014, -122.3942, 807, 415, "America/Los_Angeles", "208.80.152.201" }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "Using the database from inside another app." do
|
20
|
+
include_context "All routes"
|
21
|
+
subject { Rack::GeoIPCity.db }
|
22
|
+
it { should_not be_nil }
|
23
|
+
it { should respond_to :city }
|
24
|
+
|
25
|
+
context "Given an IP" do
|
26
|
+
subject { Rack::GeoIPCity.db.city "208.80.152.201" }
|
27
|
+
it { should respond_to :members }
|
28
|
+
its(:members) { should include :country_code2, :country_code3, :country_name, :continent_code, :region_name, :city_name, :postal_code, :latitude, :longitude, :timezone, :ip }
|
29
|
+
its(:values) { should include "US", "USA", "United States", "NA", "CA", "San Francisco", "94105", 37.789800000000014, -122.3942, 807, 415, "America/Los_Angeles", "208.80.152.201" }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "Called from inside a route" do
|
33
|
+
before do
|
34
|
+
get "/ip/208.80.152.201"
|
35
|
+
end
|
36
|
+
subject { Marshal.load last_response.body }
|
37
|
+
it { should respond_to :keys }
|
38
|
+
its(:keys) { should include :country_code2, :country_code3, :country_name, :continent_code, :region_name, :city_name, :postal_code, :latitude, :longitude, :timezone, :ip }
|
39
|
+
its(:values) { should include "US", "USA", "United States", "NA", "CA", "San Francisco", "94105", 37.789800000000014, -122.3942, 807, 415, "America/Los_Angeles", "208.80.152.201" }
|
40
|
+
end
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'rspec'
|
4
|
+
require 'rspec/its'
|
5
|
+
Spec_dir = File.expand_path( File.dirname __FILE__ )
|
6
|
+
|
7
|
+
unless Kernel.respond_to?(:require_relative)
|
8
|
+
module Kernel
|
9
|
+
def require_relative(path)
|
10
|
+
require File.join(File.dirname(caller[0]), path.to_str)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# code coverage
|
16
|
+
require 'simplecov'
|
17
|
+
SimpleCov.start do
|
18
|
+
add_filter "/bin/"
|
19
|
+
add_filter "/vendor/"
|
20
|
+
add_filter "/vendor.noindex/"
|
21
|
+
end
|
22
|
+
|
23
|
+
require "rack/test"
|
24
|
+
ENV['RACK_ENV'] ||= 'test'
|
25
|
+
ENV["EXPECT_WITH"] ||= "racktest"
|
26
|
+
|
27
|
+
|
28
|
+
require "logger"
|
29
|
+
logger = Logger.new STDOUT
|
30
|
+
logger.level = Logger::DEBUG
|
31
|
+
logger.datetime_format = '%a %d-%m-%Y %H%M '
|
32
|
+
LOgger = logger
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
Dir[ File.join( Spec_dir, "/support/**/*.rb")].each do |f|
|
37
|
+
logger.info "requiring #{f}"
|
38
|
+
require f
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
RSpec.configure do |config|
|
43
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rack/fake_ip'
|
2
|
+
require_relative "../../../lib/rack/geoipcity.rb"
|
3
|
+
|
4
|
+
|
5
|
+
module App
|
6
|
+
|
7
|
+
def self.app( options={} )
|
8
|
+
Rack::Builder.app do
|
9
|
+
ip_opts = {}
|
10
|
+
ip_opts.merge!( {ip: options[:ip] } ) if options[:ip]
|
11
|
+
use Rack::FakeIP, ip_opts
|
12
|
+
use Rack::GeoIPCity, :db => File.expand_path( File.join(File.dirname(__FILE__), "../assets/GeoLiteCity.dat"))
|
13
|
+
|
14
|
+
geo_info = ->(env) {
|
15
|
+
h = {}
|
16
|
+
env.select{|x| x =~ /^GEOIP/ }.each {|k,v|
|
17
|
+
h[k.split("GEOIP_").last.downcase] = v
|
18
|
+
}
|
19
|
+
h
|
20
|
+
}
|
21
|
+
|
22
|
+
routes = lambda { |e|
|
23
|
+
request = Rack::Request.new(e)
|
24
|
+
response = if request.path == "/"
|
25
|
+
Rack::Response.new(
|
26
|
+
[Marshal.dump(geo_info.(e))],
|
27
|
+
200,
|
28
|
+
{"Content-Type" => "text/html"}
|
29
|
+
).finish
|
30
|
+
elsif request.path.start_with? "/ip/"
|
31
|
+
ip_in_route = request.path.split("/ip/").last
|
32
|
+
ip = Rack::GeoIPCity.db.city ip_in_route
|
33
|
+
Rack::Response.new(
|
34
|
+
[Marshal.dump(Hash[ip.each_pair.to_a])],
|
35
|
+
200,
|
36
|
+
{"Content-Type" => "text/html"}
|
37
|
+
).finish
|
38
|
+
end
|
39
|
+
response
|
40
|
+
}
|
41
|
+
run routes
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
shared_context "All routes" do |options={}|
|
48
|
+
include Rack::Test::Methods
|
49
|
+
warn "options = #{options.inspect}"
|
50
|
+
let(:app){ App.app( options ) }
|
51
|
+
end
|
52
|
+
|
53
|
+
shared_examples_for "Any route" do
|
54
|
+
subject {
|
55
|
+
last_response
|
56
|
+
}
|
57
|
+
it { should be_ok }
|
58
|
+
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-geoipcity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Karol Hosiawa
|
@@ -11,19 +10,36 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date:
|
13
|
+
date: 2016-04-10 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rack
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - '>='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '0'
|
16
29
|
- !ruby/object:Gem::Dependency
|
17
30
|
name: geoip
|
18
|
-
requirement:
|
19
|
-
none: false
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
20
32
|
requirements:
|
21
|
-
- -
|
33
|
+
- - '>='
|
22
34
|
- !ruby/object:Gem::Version
|
23
35
|
version: '0'
|
24
36
|
type: :runtime
|
25
37
|
prerelease: false
|
26
|
-
version_requirements:
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
27
43
|
description: Rack::GeoIPCity uses the geoip gem and the GeoIP database to lookup the
|
28
44
|
city of a request by its IP address
|
29
45
|
email:
|
@@ -33,33 +49,43 @@ extensions: []
|
|
33
49
|
extra_rdoc_files: []
|
34
50
|
files:
|
35
51
|
- .gitignore
|
36
|
-
-
|
52
|
+
- CHANGES.md
|
53
|
+
- Gemfile
|
54
|
+
- README.md
|
55
|
+
- Rakefile
|
56
|
+
- examples/config.ru
|
57
|
+
- examples/views/layout.haml
|
37
58
|
- lib/rack/geoipcity.rb
|
38
59
|
- lib/rack/geoipcity/version.rb
|
39
60
|
- rack-geoipcity.gemspec
|
61
|
+
- spec/geoipcity_spec.rb
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- spec/support/shared/app.rb
|
40
64
|
homepage: https://github.com/yb66/Rack-GeoIPCity
|
41
65
|
licenses:
|
42
66
|
- MIT
|
67
|
+
metadata: {}
|
43
68
|
post_install_message:
|
44
69
|
rdoc_options: []
|
45
70
|
require_paths:
|
46
71
|
- lib
|
47
72
|
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
-
none: false
|
49
73
|
requirements:
|
50
|
-
- -
|
74
|
+
- - '>='
|
51
75
|
- !ruby/object:Gem::Version
|
52
76
|
version: '0'
|
53
77
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
-
none: false
|
55
78
|
requirements:
|
56
|
-
- -
|
79
|
+
- - '>='
|
57
80
|
- !ruby/object:Gem::Version
|
58
81
|
version: '0'
|
59
82
|
requirements: []
|
60
83
|
rubyforge_project:
|
61
|
-
rubygems_version:
|
84
|
+
rubygems_version: 2.0.14
|
62
85
|
signing_key:
|
63
|
-
specification_version:
|
86
|
+
specification_version: 4
|
64
87
|
summary: Rack middleware for Geo IP city lookup
|
65
|
-
test_files:
|
88
|
+
test_files:
|
89
|
+
- spec/geoipcity_spec.rb
|
90
|
+
- spec/spec_helper.rb
|
91
|
+
- spec/support/shared/app.rb
|
data/README
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
Rack::GeoIPCity uses the geoip gem and the GeoIP database to lookup the geographical info of a request by its IP address
|
2
|
-
The database can be downloaded from:
|
3
|
-
|
4
|
-
(Lite version) http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz, instructions are here http://www.maxmind.com/app/geolitecity.
|
5
|
-
|
6
|
-
http://www.maxmind.com/app/city for full version.
|
7
|
-
|
8
|
-
*NOTE!* If you're using the country database you'll get a different struct returned, so use the GeoIPCountry gem, rack-geoipcountry. I'd make this middleware do both but:
|
9
|
-
|
10
|
-
a) It would be slower
|
11
|
-
b) there's already a country gem and
|
12
|
-
c) you can do the branching yourself if you really want, but why would you?
|
13
|
-
|
14
|
-
Usage:
|
15
|
-
======
|
16
|
-
|
17
|
-
use Rack::GeoIPCity, :db => "path/to/GeoIP.dat"
|
18
|
-
|
19
|
-
By default all requests are looked up and the X\_GEOIP\_* headers are added to the request
|
20
|
-
The headers can then be read in the application
|
21
|
-
The country name is added to the request header as X\_GEOIP\_COUNTRY, eg:
|
22
|
-
X\_GEOIP\_COUNTRY: United Kingdom
|
23
|
-
|
24
|
-
The full set of GEOIP request headers is below:
|
25
|
-
X\_GEOIP\_COUNTRY\_CODE - The ISO3166-1 two-character country code, if not found set to --
|
26
|
-
X\_GEOIP\_COUNTRY\_CODE3 - The ISO3166-2 three-character country code, if not found set to --
|
27
|
-
X\_GEOIP\_COUNTRY - The ISO3166 English-language name of the country, if not found set to an empty string
|
28
|
-
X\_GEOIP\_CONTINENT if not found set to an empty string
|
29
|
-
X\_GEOIP\_REGION\_NAME if not found set to an empty string
|
30
|
-
X\_GEOIP\_CITY\_NAME if not found set to an empty string
|
31
|
-
X\_GEOIP\_POSTAL\_CODE if not found set to an empty string
|
32
|
-
X\_GEOIP\_LATITUDE if not found won't be returned as I can't think of another good return value to signify "not found"
|
33
|
-
X\_GEOIP\_LONGITUDE if not found won't be returned as I can't think of another good return value to signify "not found"
|
34
|
-
'X\_GEOIP\_DMA\_CODE' The metropolitan code (this is for the USA, see http://code.google.com/apis/adwords/docs/appendix/metrocodes.html if you're interested), default 0 for not found.
|
35
|
-
X\_GEOIP\_AREA\_CODE if not found set to an empty string
|
36
|
-
X\_GEOIP\_TIMEZONE if not found set to an empty string
|
37
|
-
X\_GEOIP\_CONTINENT - The two-character continent code, if not found set to an empty string
|
38
|
-
|
39
|
-
|
40
|
-
You can use the included Mapping class to trigger lookup only for certain requests by specifying matching path prefix in options, eg:
|
41
|
-
use Rack::GeoIPCity::Mapping, :prefix => '/video\_tracking'
|
42
|
-
The above will lookup IP addresses only for requests matching /video\_tracking etc.
|
43
|
-
|
44
|
-
MIT License -
|
45
|
-
Originally by Karol Hosiawa ( http://twitter.com/hosiawak )
|
46
|
-
Converted to a gem by Thomas Maurer
|
47
|
-
This one by Iain Barnett
|