-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhandle_ip.go
126 lines (106 loc) · 2.7 KB
/
handle_ip.go
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"encoding/json"
"fmt"
"log"
"net"
"net/http"
"strings"
"gopkg.in/yaml.v3"
)
type geoip struct {
Country string `json:"country,omitempty" yaml:"country,omitempty"`
CountryName string `json:"country_name,omitempty" yaml:"country_name,omitempty"`
City string `json:"city,omitempty" yaml:"city,omitempty"`
Lat float64 `json:"lat,omitempty" yaml:"lat,omitempty"`
Lon float64 `json:"lon,omitempty" yaml:"lon,omitempty"`
}
type asn struct {
Number uint `json:"number,omitempty" yaml:"number,omitempty"`
Organization string `json:"org,omitempty" yaml:"org,omitempty"`
}
type response struct {
IP string `json:"ip"`
UserAgent string `json:"user_agent,omitempty" yaml:"user_agent,omitempty"`
ASN *asn `json:"asn,omitempty" yaml:"asn,omitempty"`
GeoIP *geoip `json:"geoip,omitempty" yaml:"geoip,omitempty"`
}
func (s *server) handleIP() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
ip := r.PathValue("ip")
format := "yaml"
if strings.HasSuffix(ip, ".json") {
format = "json"
ip = strings.TrimSuffix(ip, ".json")
}
// todo: check with regex
lang := "en"
if r.URL.Query().Get("lang") != "" {
lang = r.URL.Query().Get("lang")
}
resp := &response{
IP: ip,
UserAgent: r.UserAgent(),
}
nip := net.ParseIP(ip)
resp.ASN = s.getASN(nip)
resp.GeoIP = s.getCity(nip, lang)
switch {
case format == "json", r.Header.Get("Accept") == "application/json":
b, err := json.MarshalIndent(resp, "", " ")
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, string(b))
case format == "yaml":
b, err := yaml.Marshal(resp)
if err != nil {
log.Println(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, string(b))
}
}
}
func (s *server) getASN(ip net.IP) *asn {
if ip == nil {
return nil
}
if s.dbASN == nil {
return nil
}
a, err := s.dbASN.ASN(ip)
if err != nil {
log.Println(err)
return nil
}
return &asn{
Number: a.AutonomousSystemNumber,
Organization: a.AutonomousSystemOrganization,
}
}
func (s *server) getCity(ip net.IP, lang string) *geoip {
if ip == nil {
return nil
}
if s.dbCity == nil {
return nil
}
city, err := s.dbCity.City(ip)
if err != nil {
log.Println(err)
return nil
}
return &geoip{
Country: city.Country.IsoCode,
CountryName: city.Country.Names[lang],
City: city.City.Names[lang],
Lat: city.Location.Latitude,
Lon: city.Location.Longitude,
}
}