geoip_server 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gems +2 -0
- data/README.markdown +31 -0
- data/Rakefile +46 -0
- data/VERSION +1 -0
- data/config.ru +6 -0
- data/lib/geoip_server.rb +73 -0
- data/test.rb +73 -0
- metadata +86 -0
data/.gems
ADDED
data/README.markdown
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|
data/config.ru
ADDED
data/lib/geoip_server.rb
ADDED
@@ -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
|
+
|