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.
@@ -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
- *.tmproj
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/
@@ -0,0 +1,11 @@
1
+ # CH CH CH CHANGES! #
2
+
3
+ ## v1.0.0 ##
4
+
5
+ * Updated RSpec and specs ever so slightly because of it.
6
+ * Updated for semver, it's been same API for aaaages.
7
+ * Little bit of love for the formatting.
8
+
9
+ ## v0.0.1 ##
10
+
11
+ * Initial release.
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
@@ -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
@@ -0,0 +1,6 @@
1
+ require 'yard'
2
+
3
+ YARD::Rake::YardocTask.new do |t|
4
+ t.files = ['lib/**/*.rb', 'app/*.rb', 'models/*.rb', 'spec/**/*.rb']
5
+ t.options = ['-odocs/'] # optional
6
+ end
@@ -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
@@ -0,0 +1,15 @@
1
+ - stuff_here ||= "Nothing doing"
2
+ !!!
3
+ %head
4
+ %title
5
+ Rack GeoIPCity Example
6
+ %body
7
+ %h1
8
+ Rack GeoIPCity Example
9
+
10
+ %p= Time.now
11
+
12
+ %h2
13
+ Geo Info
14
+ %p
15
+ = stuff_here
@@ -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
- @db = GeoIP.new(options[:db])
10
- @app = app
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
- res = @db.city(env['REMOTE_ADDR'])
30
-
31
- unless res.nil? # won't bork on local or bad ip's
32
- hash = {}
33
- hash['X_GEOIP_COUNTRY_CODE'] = res.country_code2 unless res.country_code2.nil?
34
- hash['X_GEOIP_COUNTRY_CODE3'] = res.country_code3 unless res.country_code3.nil?
35
- hash['X_GEOIP_COUNTRY'] = res.country_name unless res.country_name.nil?
36
- hash['X_GEOIP_CONTINENT'] = res.continent_code unless res.continent_code.nil?
37
- hash['X_GEOIP_REGION_NAME'] = res.region_name unless res.region_name.nil?
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
@@ -1,5 +1,5 @@
1
1
  module Rack
2
- module GeoIPCity
3
- VERSION = "0.0.1"
2
+ class GeoIPCity
3
+ VERSION = "1.0.0"
4
4
  end
5
5
  end
@@ -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
@@ -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.1
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: 2011-06-24 00:00:00.000000000Z
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: &2152901760 !ruby/object:Gem::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: *2152901760
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
- - README
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: 1.8.5
84
+ rubygems_version: 2.0.14
62
85
  signing_key:
63
- specification_version: 3
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