geoip_server 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.
Files changed (8) hide show
  1. data/.gems +2 -0
  2. data/README.markdown +31 -0
  3. data/Rakefile +46 -0
  4. data/VERSION +1 -0
  5. data/config.ru +6 -0
  6. data/lib/geoip_server.rb +73 -0
  7. data/test.rb +73 -0
  8. metadata +86 -0
data/.gems ADDED
@@ -0,0 +1,2 @@
1
+ sinatra
2
+ geoip
@@ -0,0 +1,31 @@
1
+ # GeoIP Server
2
+
3
+ This simple Rack server is useful as a self-hosted service for making lookups to the GeoIP database from MaxMind.com
4
+
5
+
6
+ ## Instant installation and deploy
7
+
8
+ * Clone this: `git clone git://github.com/JackDanger/geoip_server.git`
9
+ * Download the free GeoIP data files: `rake geoip:update_city_lite`
10
+ * Commit that data file to your clone: `git add vendor && git commit -m "adding data file"`
11
+ * Signup for an account at Heroku ([better details here](http://github.com/sinatra/heroku-sinatra-app))
12
+ * Create and name a new app where you want to host this
13
+ * push it to Heroku.com: `git push heroku master`
14
+
15
+
16
+ ## HowTo
17
+
18
+ Once the server is running you can make a GET request to the server and receive lookup results in JSON format.
19
+
20
+ ip = request.remote_ip
21
+ require 'open-uri'
22
+ data = JSON.decode(open("http://my-geoip-service-app.heroku.com/#{ip}").read)
23
+ render :text => "You're in: #{data[:city]}"
24
+
25
+ Or, straight from a terminal:
26
+
27
+ curl -X POST http://my-geoip-service-app.heroku.com/207.97.227.239
28
+
29
+ Patches welcome, forks celebrated.
30
+
31
+ Copyright (c) 2010 [Jack Danger Canty](http://jåck.com). Released under the MIT License.
@@ -0,0 +1,46 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "geoip_server"
5
+ gem.summary = %Q{Query the MaxMind GeoIP data records via a web service}
6
+ gem.description = %Q{Query the MaxMind GeoIP data records via a web service}
7
+ gem.email = "gitcommit@6brand.com"
8
+ gem.homepage = "http://github.com/JackDanger/geoip_server"
9
+ gem.authors = ["Jack Danger Canty"]
10
+ gem.add_development_dependency "shoulda", ">= 0"
11
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
12
+ end
13
+ Jeweler::GemcutterTasks.new
14
+ rescue LoadError
15
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
16
+ end
17
+
18
+
19
+
20
+ task :default => :test
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << '.'
25
+ test.pattern = 'test.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+
30
+
31
+
32
+ namespace :geoip do
33
+ desc "Update GeoIP City data file"
34
+ task :update_city_lite => :vendor do
35
+ %x{wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz && gzip -d GeoLiteCity.dat.gz && mv GeoLiteCity.dat ./vendor}
36
+ end
37
+
38
+ desc "Update GeoIP Country data file"
39
+ task :update_country_lite => :vendor do
40
+ %x{wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz && gzip -d GeoIP.dat.gz && mv GeoIP.dat ./vendor}
41
+ end
42
+
43
+ task :vendor do
44
+ %x{mkdir -p vendor}
45
+ end
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
@@ -0,0 +1,6 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib/geoip_server'))
2
+
3
+ ## There is no need to set directories here anymore;
4
+ ## Just run the application
5
+
6
+ run Sinatra::Application
@@ -0,0 +1,73 @@
1
+ ## Resources
2
+ gem 'sinatra', :version => '1.0'
3
+ require 'sinatra'
4
+ require 'geoip'
5
+ require 'json'
6
+
7
+ data_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'vendor', 'GeoLiteCity.dat'))
8
+
9
+ ## Application
10
+
11
+ get '/' do
12
+ %Q{
13
+ <html><title>Detect a computer's location by IP address</title>
14
+ <body style='line-height: 1.8em; font-family: Archer, Museo, Helvetica, Georgia; font-size 25px; text-align: center; padding-top: 20%;'>
15
+ Lookup a location by IP address. Example:
16
+ <pre style='font-family: Iconsolata, monospace;background-color:#EEE'>curl http://#{request.host}/207.97.227.239</pre>
17
+ <br />
18
+ <form action=/ method=GET onsubmit='if(\"\"==this.ip.value)return false;else{this.action=\"/\"+this.ip.value}'>
19
+ <input type=text name='ip' value='#{request.env['HTTP_X_REAL_IP']}' />
20
+ <input type=submit value='Lookup!' />
21
+ </form>
22
+ <div>None of this would be possible without <a href='http://www.maxmind.com/app/geolitecity'>MaxMind</a></div>
23
+ </body></html>
24
+ }
25
+ end
26
+
27
+ get '/:ip' do
28
+ pass unless params[:ip] =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
29
+
30
+ data = GeoIP.new(data_file).city(params[:ip])
31
+
32
+ content_type 'application/json'
33
+ headers['Cache-Control'] = "public; max-age=#{365*24*60*60}"
34
+
35
+ return "{}" unless data
36
+
37
+ encode(data).to_json
38
+
39
+ end
40
+
41
+ def encode data
42
+ {
43
+ # * The host or IP address string as requested
44
+ :ip => data.shift,
45
+ # * The IP address string after looking up the host
46
+ :ip_lookup => data.shift,
47
+ # * The GeoIP country-ID as an integer
48
+ # :country_id => data.shift,
49
+ # * The ISO3166-1 two-character country code
50
+ :country_code => data.shift,
51
+ # * The ISO3166-2 three-character country code
52
+ :country_code_long => data.shift,
53
+ # * The ISO3166 English-language name of the country
54
+ :country => data.shift,
55
+ # * The two-character continent code
56
+ :continent => data.shift,
57
+ # * The region name
58
+ :region => data.shift,
59
+ # * The city name
60
+ :city => data.shift,
61
+ # * The postal code
62
+ :postal_code => data.shift,
63
+ # * The latitude
64
+ :lat => data.shift,
65
+ # * The longitude
66
+ :lng => data.shift,
67
+ # * The USA dma_code and area_code, if available (REV1 City database)
68
+ :dma_code => data.shift,
69
+ :area_code => data.shift,
70
+ # Timezone, if available
71
+ :timezone => data.shift
72
+ }
73
+ end
data/test.rb ADDED
@@ -0,0 +1,73 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'shoulda'
6
+ require 'rack/test'
7
+ require File.expand_path(File.join(File.dirname(__FILE__), 'lib/geoip_server'))
8
+
9
+ class GeoipServerTest < Test::Unit::TestCase
10
+ include Rack::Test::Methods
11
+
12
+ def app
13
+ Sinatra::Application
14
+ end
15
+
16
+ context "on GET to /" do
17
+ setup {
18
+ get '/'
19
+ }
20
+ should "return ok" do
21
+ assert last_response.ok?
22
+ end
23
+ should "have some kind of welcome" do
24
+ assert last_response.body =~ /curl/
25
+ end
26
+ end
27
+
28
+ context "on GET to /:ip" do
29
+ setup {
30
+ get '/67.161.92.71'
31
+ }
32
+ should "return ok" do
33
+ assert last_response.ok?
34
+ end
35
+ should "return json content-type" do
36
+ assert_equal 'application/json', last_response.headers['Content-Type']
37
+ end
38
+ end
39
+
40
+ context "converting array" do
41
+ setup {
42
+ array = [
43
+ "67.161.92.71",
44
+ "67.161.92.71",
45
+ "US",
46
+ "USA",
47
+ "United States",
48
+ "NA",
49
+ "WA",
50
+ "Seattle",
51
+ "98117",
52
+ 47.6847,
53
+ -122.3848,
54
+ 819,
55
+ 206,
56
+ "America/Los_Angeles"
57
+ ]
58
+ @hash = encode(array)
59
+ }
60
+ should "find city" do
61
+ assert_equal 'Seattle', @hash[:city]
62
+ end
63
+ should "find country" do
64
+ assert_equal 'United States', @hash[:country]
65
+ end
66
+ should "find lat" do
67
+ assert_equal 47.6847, @hash[:lat]
68
+ end
69
+ should "find lng" do
70
+ assert_equal -122.3848, @hash[:lng]
71
+ end
72
+ end
73
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geoip_server
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Jack Danger Canty
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-27 00:00:00 -08:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ description: Query the MaxMind GeoIP data records via a web service
36
+ email: gitcommit@6brand.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.markdown
43
+ files:
44
+ - .gems
45
+ - README.markdown
46
+ - Rakefile
47
+ - VERSION
48
+ - config.ru
49
+ - lib/geoip_server.rb
50
+ - test.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/JackDanger/geoip_server
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ hash: 3
66
+ segments:
67
+ - 0
68
+ version: "0"
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ hash: 3
75
+ segments:
76
+ - 0
77
+ version: "0"
78
+ requirements: []
79
+
80
+ rubyforge_project:
81
+ rubygems_version: 1.3.7
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Query the MaxMind GeoIP data records via a web service
85
+ test_files: []
86
+