├── .gitignore ├── Makefile ├── Procfile ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | GeoLite2-City.mmdb 2 | node_modules/ 3 | .env 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: GeoLite2-City.mmdb node_modules 2 | 3 | clean: 4 | rm GeoLite2-City.mmdb 5 | rm -rf node_modules 6 | 7 | .PHONY: all clean 8 | 9 | GeoLite2-City.mmdb: 10 | curl -O http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz 11 | gunzip GeoLite2-City.mmdb.gz 12 | 13 | node_modules: package.json 14 | npm install 15 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: make && node index.js 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## node-geoip-web 2 | 3 | An Express server that returns location information using the GeoLite2 4 | database. 5 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var ip = require('ipv6'); 3 | var MaxMind = require('maxmind-db-reader'); 4 | var _ = require('lodash'); 5 | 6 | var db = new MaxMind('./GeoLite2-City.mmdb'); 7 | 8 | // Uses equirectangular approximation for speed 9 | function approximateDistance(lat1, lon1, lat2, lon2) { 10 | lat1 = lat1 * Math.PI / 180; 11 | lon1 = lon1 * Math.PI / 180; 12 | 13 | lat2 = lat2 * Math.PI / 180; 14 | lon2 = lon2 * Math.PI / 180; 15 | 16 | var R = 6371; 17 | 18 | var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2); 19 | var y = (lat2 - lat1); 20 | 21 | return Math.sqrt(x * x + y * y) * R; 22 | } 23 | 24 | function resultFromAddress(req, opt_address) { 25 | if (!opt_address) { 26 | opt_address = _.last(req.ips) || req.connection.remoteAddress; 27 | } 28 | 29 | var geoData = db.getGeoData(opt_address); 30 | 31 | if (!geoData || !geoData.location) { 32 | return { 33 | ip: opt_address, 34 | location: 'unknown' 35 | }; 36 | } 37 | 38 | var result = { 39 | ip: opt_address 40 | }; 41 | 42 | if (req.param('fields')) { 43 | var fields = req.param('fields').split(','); 44 | 45 | fields.forEach(function (field) { 46 | result[field] = geoData[field]; 47 | }); 48 | } else { 49 | result.country = geoData.country; 50 | result.location = geoData.location; 51 | } 52 | 53 | if (req.param('lat') && req.param('lon') && req.param('distance')) { 54 | var lat = parseFloat(req.param('lat'), 10); 55 | var lon = parseFloat(req.param('lon'), 10); 56 | 57 | var distance = parseInt(req.param('distance'), 10); 58 | 59 | result.distance = approximateDistance(geoData.location.latitude, 60 | geoData.location.longitude, lat, lon) < distance; 61 | } 62 | 63 | return result; 64 | } 65 | 66 | var app = express(); 67 | 68 | app.enable('trust proxy'); 69 | 70 | app.get('/', function (req, res) { 71 | res.jsonp(resultFromAddress(req)); 72 | }); 73 | 74 | app.get(/^\/(robots\.txt|favicon\.ico)$/, function (req, res) { 75 | res.send(404); 76 | }); 77 | 78 | app.get('/:address', function (req, res) { 79 | var v4 = new ip.v4.Address(req.param('address')); 80 | var v6 = new ip.v6.Address(req.param('address')); 81 | 82 | if (!v4.isValid() && !v6.isValid()) { 83 | return res.jsonp(500, { error: 'Invalid IP Address' }); 84 | } 85 | 86 | res.jsonp(resultFromAddress(req, req.param('address'))); 87 | }); 88 | 89 | app.listen(process.env.PORT || 3000); 90 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geoip-web", 3 | "version": "1.0.1", 4 | "description": "A very small server that answers queries via GeoLite2-City.", 5 | "author": "Beau Gunderson ", 6 | "main": "index.js", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/tfrce/node-geoip-web.git" 10 | }, 11 | "engines": { 12 | "node": "0.10.x" 13 | }, 14 | "dependencies": { 15 | "express": "~3.4.8", 16 | "lodash": "~2.4.1", 17 | "maxmind-db-reader": "~0.0.2", 18 | "ipv6": "~3.1.1" 19 | }, 20 | "license": "MIT" 21 | } 22 | --------------------------------------------------------------------------------