rack-geoipcity 0.0.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|