-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
maxmind.clj
66 lines (58 loc) · 1.85 KB
/
maxmind.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
(ns geocoder.maxmind
(:import [com.maxmind.geoip2 DatabaseReader$Builder]
[com.maxmind.geoip2.exception AddressNotFoundException]
[java.net InetAddress])
(:require [clojure.string :refer [lower-case]]
[clojure.java.io :as io]
[clojure.string :as str]))
(def default-path
(str (System/getenv "HOME") "/.maxmind/GeoLite2-City.mmdb"))
(defn db
"Make a Maxmind GeoIP database."
[& [path]]
(let [path (io/file (or path default-path))]
(when (.exists path)
(.build (DatabaseReader$Builder. path)))))
(defn city
"Returns the city of `address`."
[result]
(some-> (.getCity result) (.getName)))
(defn country
"Returns the country of `result`."
[result]
(let [country (.getCountry result)]
{:name (.getName country)
:iso-3166-1-alpha-2 (some-> (.getIsoCode country) str/lower-case)}))
(defn location
"Returns the location of `address`."
[result]
(when-let [location (.getLocation result)]
{:lng (double (.getLongitude location))
:lat (double (.getLatitude location)) }))
(defn region-id
"Returns the region id of `address`."
[address]
(. address region))
(defn geocode-ip-address
"Geocode an internet address using one of Maxmind's GeoIP
databases."
[db ip-address]
(try
(let [ip-address (InetAddress/getByName ip-address)]
(let [result (.city db ip-address)]
{:country (country result)
:city (city result)
:location (location result)
;; :region-id (region-id result)
}))
(catch AddressNotFoundException e
nil)))
(defn wrap-maxmind
"Wrap the Maxmind middleware around a Ring handler."
[handler db-path]
(let [db (db db-path)]
(fn [request]
(if db
(let [address (geocode-ip-address db (:remote-addr request))]
(handler (assoc request :maxmind address)))
(handler request)))))