mm_geoip 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/mm_geoip ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'mm_geoip'
4
+
5
+ begin
6
+ if ip = ARGV[0]
7
+ MMGeoip.db_path = ARGV[1] if ARGV[1]
8
+
9
+ puts "Using database: #{MMGeoip.db_path}"
10
+
11
+ geoip = MMGeoip.new :ip => ip
12
+
13
+ (MMGeoip::FIELDS + [:region_name]).each do |field|
14
+ puts "#{field}: #{geoip.send field}"
15
+ end
16
+
17
+ else
18
+ puts "You should try passing an IP as argument: mm_geoip 134.34.3.2"
19
+ end
20
+ rescue MMGeoip::NoDatabaseFile => e
21
+ puts %Q{
22
+ MMGeoip could't find your geodb database file.
23
+ #{e.class}: #{e.message}
24
+
25
+ When runing this tool you have three possibilities to define the database location.
26
+
27
+ * Either you can put one into the gem so mm_geoip finds it automatically:
28
+ ln -s /your/database.dat `pwd`
29
+
30
+ * Or you set an environment variable:
31
+ MMGeoipDatabase=/your/database.dat mm_geoip 134.34.3.2
32
+
33
+ * Or you pass the location as a second argument:
34
+ mm_geoip 134.34.3.2 /your/database.dat
35
+
36
+ Download:
37
+ curl http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz | gunzip > GeoLiteCity.dat
38
+
39
+ }
40
+
41
+ end
@@ -1,3 +1,3 @@
1
1
  class MMGeoip
2
- VERSION = '0.0.4'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/mm_geoip.rb CHANGED
@@ -4,6 +4,7 @@ $LOAD_PATH << File.dirname(File.expand_path __FILE__)
4
4
 
5
5
  class MMGeoip; end
6
6
 
7
+ require 'mm_geoip/version'
7
8
  require 'mm_geoip/region'
8
9
 
9
10
  class MMGeoip
@@ -13,14 +14,19 @@ class MMGeoip
13
14
  attr_reader :lookup
14
15
 
15
16
  class NoIpGiven < StandardError; end
17
+ class NoDatabaseFile < StandardError; end
16
18
 
17
19
  def initialize(env)
18
- @env = env # may be a Rack @env or any hash containing initial data
19
- @env[:ip] ||= @env["HTTP_X_REAL_IP"] || @env["HTTP_X_FORWARDED_FOR"] || @env["REMOTE_ADDR"]
20
+ # May be a Rack @env or any hash containing initial data. Or just an IP.
21
+ @env = env.is_a?(Hash) ? env.dup : {:ip => env}
22
+ @ip = @env[:ip] || @env["HTTP_X_REAL_IP"] || @env["HTTP_X_FORWARDED_FOR"] || @env["REMOTE_ADDR"]
20
23
 
21
- raise NoIpGiven.new unless @env[:ip]
22
-
23
- @geodb = GeoIP.new self.class.db_path
24
+ raise NoIpGiven.new("No IP in env hash") unless @ip
25
+ raise NoDatabaseFile.new("No database file: #{self.class.db_path}") unless File.exists? self.class.db_path
26
+ end
27
+
28
+ def geodb
29
+ @geodb ||= GeoIP.new self.class.db_path
24
30
  end
25
31
 
26
32
  FIELDS.each do |field|
@@ -56,7 +62,7 @@ class MMGeoip
56
62
  def lookup
57
63
  return @lookup if @lookup
58
64
 
59
- looked_up_fields = @geodb.city @env[:ip]
65
+ looked_up_fields = geodb.city @ip
60
66
 
61
67
  return @lookup = {} unless looked_up_fields
62
68
 
@@ -69,7 +75,7 @@ class MMGeoip
69
75
  File.join(File.dirname(File.expand_path(__FILE__)), '../data')
70
76
  end
71
77
  def self.db_path
72
- @db_path || File.join(data_path, 'GeoLiteCity.dat')
78
+ @db_path || ENV['MMGeoipDatabase'] || File.join(data_path, 'GeoLiteCity.dat')
73
79
  end
74
80
  def self.db_path=(path)
75
81
  @db_path = path
@@ -1,3 +1,5 @@
1
+ require 'mm_geoip.rb'
2
+
1
3
  module Rack
2
4
  class MMGeoip
3
5
  def initialize(app)
@@ -5,8 +7,8 @@ module Rack
5
7
  end
6
8
 
7
9
  def call(env)
8
- env['GEOIP'] = ::MMGeoip.new env
9
- @app.call(env)
10
+ @app.call env.dup.merge('GEOIP' => ::MMGeoip.new(env))
10
11
  end
11
12
  end
12
13
  end
14
+
@@ -0,0 +1,15 @@
1
+ require 'rack/mm_geoip.rb'
2
+
3
+ module Sinatra
4
+ module MMGeoip
5
+
6
+ # Just a convinience method to access the mm_geoip proxy
7
+ # object in Sinatra routes and views.
8
+ def geoip
9
+ request.env['GEOIP']
10
+ end
11
+
12
+ end
13
+
14
+ helpers MMGeoip
15
+ end
@@ -0,0 +1,20 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'spec_helper')
2
+
3
+ describe MMGeoip::Regions do
4
+ describe "#parse" do
5
+ it "works" do
6
+ MMGeoip::Regions.parse[:CA]['NS'].should == 'Nova Scotia' # CA,NS,"Nova Scotia"
7
+ MMGeoip::Regions.parse[:US]['AL'].should == 'Alabama' # US,AL,"Alabama"
8
+ MMGeoip::Regions.parse[:DE]['01'].should == 'Baden-Wurttemberg' # DE,02,"Bayern"
9
+ MMGeoip::Regions.parse[:DE]['02'].should == 'Bayern' # DE,01,"Baden-Wurttemberg"
10
+ end
11
+ end
12
+ describe "#[]" do
13
+ it "works" do
14
+ MMGeoip::Regions[:CA]['NS'].should == 'Nova Scotia' # CA,NS,"Nova Scotia"
15
+ MMGeoip::Regions[:US]['AL'].should == 'Alabama' # US,AL,"Alabama"
16
+ MMGeoip::Regions[:DE]['01'].should == 'Baden-Wurttemberg' # DE,02,"Bayern"
17
+ MMGeoip::Regions[:DE]['02'].should == 'Bayern' # DE,01,"Baden-Wurttemberg"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,105 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'spec_helper')
2
+
3
+ describe MMGeoip do
4
+ describe "the whole stack" do
5
+ before(:each) do
6
+ @env = {:ip => '134.34.3.2'}
7
+ end
8
+ it "should be fast" do
9
+ # Succeeds with a margin of about 10% on my MBP core2duo 2.4GHz.
10
+ # On slower computers this will fail.
11
+ Benchmark.measure{
12
+ 1000.times{mm_geoip = MMGeoip.new @env ; mm_geoip.city} # with lookup
13
+ }.total.should < 0.6
14
+ end
15
+ it "be lazy, i.e. 3 times faster without lookup" do
16
+ with_lookup = Benchmark.measure{
17
+ 1000.times{mm_geoip = MMGeoip.new @env ; mm_geoip.city} # with lookup
18
+ }.total
19
+
20
+ no_lookup = Benchmark.measure{
21
+ 1000.times{mm_geoip = MMGeoip.new @env} # no lookup
22
+ }.total
23
+
24
+ (no_lookup*3).should < with_lookup
25
+ end
26
+ end
27
+
28
+ describe "#initialize" do
29
+ it "works with the IP as :ip field" do
30
+ MMGeoip.new '134.34.3.2'
31
+ end
32
+ it "works with just the IP" do
33
+ MMGeoip.new :ip => '134.34.3.2'
34
+ end
35
+ it "works with the IP as 'REMOTE_ADDR' field" do
36
+ MMGeoip.new 'REMOTE_ADDR' => '134.34.3.2'
37
+ end
38
+ it "works with the IP as 'HTTP_X_REAL_IP' field" do
39
+ MMGeoip.new 'HTTP_X_REAL_IP' => '134.34.3.2'
40
+ end
41
+ it "works with the IP as 'HTTP_X_FORWARDED_FOR' field" do
42
+ MMGeoip.new 'HTTP_X_FORWARDED_FOR' => '134.34.3.2'
43
+ end
44
+ it "raises, if not :ip or 'REMOTE_ADDR' is given" do
45
+ lambda{ MMGeoip.new :whatelse => 'something' }.should raise_error(MMGeoip::NoIpGiven)
46
+ end
47
+ it "puts the parameter into the env instance variable" do
48
+ env = {:ip => '134.34.3.2'}
49
+ mm_geoip = MMGeoip.new env
50
+ mm_geoip.instance_variable_get('@env').should == env
51
+ end
52
+ it "does not alter the env hash" do
53
+ env = {'REMOTE_ADDR' => '134.34.3.2'}
54
+ env_before = env.dup
55
+ mm_geoip = MMGeoip.new env
56
+ env.should == env_before
57
+ end
58
+ end
59
+
60
+ describe "#geoip" do
61
+ it "sets up a geoidb object" do
62
+ mm_geoip = MMGeoip.new(:ip => '134.34.3.2')
63
+ mm_geoip.geodb.should == mm_geoip.instance_variable_get('@geodb')
64
+ mm_geoip.geodb.should be_a(GeoIP)
65
+ end
66
+ end
67
+
68
+ describe "the getters" do
69
+ it "works" do
70
+ mm_geoip = MMGeoip.new :ip => '134.34.3.2'
71
+ mm_geoip.ip.should == '134.34.3.2'
72
+
73
+ mm_geoip.hostname.should == '134.34.3.2'
74
+ mm_geoip.ip.should == '134.34.3.2'
75
+ mm_geoip.country_code.should == 'DE'
76
+ mm_geoip.country_code3.should == 'DEU'
77
+ mm_geoip.country_name.should == 'Germany'
78
+ mm_geoip.country_continent.should == 'EU'
79
+ mm_geoip.region.should == '01'
80
+ mm_geoip.city.should == 'Konstanz'
81
+ mm_geoip.postal_code.should == ''
82
+ mm_geoip.lat.should == 47.66669999999999
83
+ mm_geoip.lng.should == 9.183300000000003
84
+ mm_geoip.dma_code.should == nil
85
+ mm_geoip.area_code.should == nil
86
+ mm_geoip.timezone.should == 'Europe/Berlin'
87
+ mm_geoip.region_name.should == 'Baden-Wurttemberg'
88
+ end
89
+ it "works with localhost, too" do
90
+ mm_geoip = MMGeoip.new :ip => '127.0.0.1'
91
+ mm_geoip.ip.should == '127.0.0.1'
92
+
93
+ mm_geoip.hostname.should be_nil
94
+ mm_geoip.region_name.should be_nil
95
+ end
96
+ end
97
+
98
+ describe "#get_from_env" do
99
+ it "tries the env fields" do
100
+ MMGeoip.new(:ip => '134.34.3.2', :hostname => 'hostname').hostname.should == 'hostname'
101
+ MMGeoip.new(:ip => '134.34.3.2', 'GEOIP_HOSTNAME' => 'geoip hostname').hostname.should == 'geoip hostname'
102
+ MMGeoip.new(:ip => '134.34.3.2', 'X_GEOIP_HOSTNAME' => 'x geoip hostname').hostname.should == 'x geoip hostname'
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,11 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../spec_helper')
2
+
3
+ describe Rack::MMGeoip do
4
+ describe '#call' do
5
+ it "adds a MMGeoip object to the env hash" do
6
+ app = proc{|env| env}
7
+ rack_geoip = Rack::MMGeoip.new app
8
+ rack_geoip.call({:ip => '134.34.3.2'})['GEOIP'].should be_a(MMGeoip)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
1
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../spec_helper')
2
+
3
+ require 'rack/test'
4
+
5
+ class SinatraMMGeoipApp < Sinatra::Base
6
+ use Rack::MMGeoip
7
+ helpers Sinatra::MMGeoip
8
+
9
+ get '/' do
10
+ geoip.city
11
+ end
12
+
13
+ end
14
+
15
+ describe Sinatra::MMGeoip do
16
+ include Rack::Test::Methods
17
+
18
+ def app
19
+ SinatraMMGeoipApp
20
+ end
21
+
22
+ describe "a test app which just puts the city into the body" do
23
+ describe "with a remote address in the env hash" do
24
+ it "returns the city as response" do
25
+ get '/', {}, {'REMOTE_ADDR' => '134.34.3.2'}
26
+ puts last_response.body
27
+ last_response.should be_ok
28
+ last_response.body.should == 'Konstanz'
29
+ end
30
+ end
31
+ describe "without a remote address in the env hash" do
32
+ it "returns an emty response" do
33
+ get '/'
34
+ last_response.should be_ok
35
+ last_response.body.should == ''
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH << File.join(File.dirname(File.expand_path __FILE__), '../lib')
2
+
3
+ require 'benchmark'
4
+
5
+ require 'mm_geoip'
6
+ require 'rack/mm_geoip'
7
+ require 'sinatra/base'
8
+ require 'sinatra/mm_geoip'
9
+
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mm_geoip
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.4
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Niko Dittmann
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-06 00:00:00 Z
13
+ date: 2011-06-13 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: geoip
@@ -23,10 +23,65 @@ dependencies:
23
23
  version: "0"
24
24
  type: :runtime
25
25
  version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: rake
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :development
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: bundler
39
+ prerelease: false
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: sinatra
50
+ prerelease: false
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :development
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: rack-test
61
+ prerelease: false
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :development
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: rspec
72
+ prerelease: false
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id006
26
81
  description: A proxy object around the geoip gem for lazy lookup. Includes a Rack middleware.
27
82
  email: mail+git@niko-dittmann.com
28
- executables: []
29
-
83
+ executables:
84
+ - mm_geoip
30
85
  extensions: []
31
86
 
32
87
  extra_rdoc_files: []
@@ -35,13 +90,19 @@ files:
35
90
  - lib/mm_geoip/region.rb
36
91
  - lib/mm_geoip/version.rb
37
92
  - lib/mm_geoip.rb
38
- - lib/rack_mm_geoip.rb
93
+ - lib/rack/mm_geoip.rb
94
+ - lib/sinatra/mm_geoip.rb
39
95
  - data/fips_and_3166_2.txt
40
- - data/GeoLiteCity.dat
96
+ - bin/mm_geoip
97
+ - spec/mm_geoip_region_spec.rb
98
+ - spec/mm_geoip_spec.rb
99
+ - spec/rack/mm_geoip_spec.rb
100
+ - spec/sinatra/mm_geoip_spec.rb
101
+ - spec/spec_helper.rb
41
102
  homepage: http://github.com/niko/mm_geoip
42
103
  licenses: []
43
104
 
44
- post_install_message:
105
+ post_install_message: "Try your new mm_geoip installation: type mm_geoip 134.34.3.2 [RETURN] in the command line."
45
106
  rdoc_options: []
46
107
 
47
108
  require_paths:
@@ -65,5 +126,9 @@ rubygems_version: 1.7.2
65
126
  signing_key:
66
127
  specification_version: 3
67
128
  summary: A proxy object around the geoip gem for lazy lookup. Includes a Rack middleware.
68
- test_files: []
69
-
129
+ test_files:
130
+ - spec/mm_geoip_region_spec.rb
131
+ - spec/mm_geoip_spec.rb
132
+ - spec/rack/mm_geoip_spec.rb
133
+ - spec/sinatra/mm_geoip_spec.rb
134
+ - spec/spec_helper.rb
data/data/GeoLiteCity.dat DELETED
Binary file