-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
server.go
134 lines (115 loc) · 3.58 KB
/
server.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
127
128
129
130
131
132
133
134
package main
import (
"fmt"
"net"
"net/http"
"strings"
"runtime/debug"
"github.com/go-chi/chi/v5"
"github.com/oschwald/geoip2-golang"
)
type GeoIPReader interface {
City(net.IP) (*geoip2.City, error)
ASN(net.IP) (*geoip2.ASN, error)
}
type Whois interface {
Query(string) (string, error)
}
type server struct {
router chi.Router
dbASN GeoIPReader
dbCity GeoIPReader
whois Whois
}
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.router.ServeHTTP(w, r)
}
func (s *server) routes() {
buildRevision, buildTime := buildInfo()
s.router.HandleFunc("/", s.handleIndex())
s.router.HandleFunc("/whois", s.handleWhois())
s.router.HandleFunc("/{ip:[0-9.]+}json", s.handleIP("json"))
s.router.HandleFunc("/{ip:[0-9.]+}", s.handleIP("yaml"))
s.router.HandleFunc("/{ip:[0-9.]+}/whois", s.handleIPWhois())
s.router.HandleFunc("/{ip:[0-9.]+}/{mask:[0-9]+}", s.handleMask())
s.router.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "/help")
w.WriteHeader(http.StatusFound)
})
s.router.HandleFunc("/info", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "/help")
w.WriteHeader(http.StatusFound)
})
s.router.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Location", "/help")
w.WriteHeader(http.StatusFound)
})
s.router.HandleFunc("/help", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, `ip.chuhlomin.com is a service for finding information about IP addresses.
It uses:
* GeoLite2 databases for ASN and GeoIP lookups,
* whois.iana.org for Whois queries.
Available endpoints:
/help - this page
/ - index page, redirects to /{ip}, where {ip} is your IP address
/{ip} - returns information about the IP address: ASN and GeoIP
/whois - redirects to /{ip}/whois if IP is known, otherwise returns 404
/{ip}/whois - returns the Whois information for the IP address
/{ip}/{mask} - displays the IP in binary format, visualizing the mask
Example usage:
curl -L https://ip.chuhlomin.com/
curl https://ip.chuhlomin.com/1.1.1.1
curl https://ip.chuhlomin.com/1.1.1.1/whois
curl https://ip.chuhlomin.com/192.168.0.0/24
Version: 1.0.0
Revision: %s
Build time: %s
Source code: https://github.com/chuhlomin/ip
Author: Konstantin Chukhlomin
License: MIT
---
Known alternatives:
https://ip.me
https://ifconfig.co
https://httpbin.org/ip
https://ipinfo.io
https://whatismyipaddress.com
`,
buildRevision, buildTime)
})
s.router.HandleFunc("/robots.txt", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/plain")
fmt.Fprintf(w, "User-agent: *\nDisallow: /\n")
})
s.router.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./favicon.ico")
})
s.router.HandleFunc("/og.png", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "./og.png")
})
s.router.NotFound(func(w http.ResponseWriter, r *http.Request) {
// check if the request path is a valid IP address
ip := net.ParseIP(strings.Trim(r.URL.Path[1:], " /"))
if ip == nil {
http.Error(w, "Not found", http.StatusNotFound)
return
}
// redirect to the IP address page
w.Header().Set("Location", "/"+ip.String())
w.WriteHeader(http.StatusFound)
})
}
func buildInfo() (revision, time string) {
if info, ok := debug.ReadBuildInfo(); ok {
for _, setting := range info.Settings {
switch setting.Key {
case "vcs.revision":
revision = setting.Value
case "vcs.time":
time = setting.Value
}
}
}
return
}