Initial version.
This commit is contained in:
commit
3b61cc8d82
|
@ -0,0 +1,5 @@
|
|||
module git.eve.moe/jackyyf/navigator
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/ipipdotnet/ipdb-go v1.2.0
|
|
@ -0,0 +1,2 @@
|
|||
github.com/ipipdotnet/ipdb-go v1.2.0 h1:Afa0qx/SgRevzIK8Qg1TevuD5M28kFLWbzPvU+GQJ08=
|
||||
github.com/ipipdotnet/ipdb-go v1.2.0/go.mod h1:6SFLNyXDBF6q99FQvbOZJQCc2rdPrB1V5DSy4S83RSw=
|
|
@ -0,0 +1,141 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
_ "net/http/pprof"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/ipipdotnet/ipdb-go"
|
||||
)
|
||||
|
||||
var (
|
||||
requiredFields = []string{
|
||||
"country_name",
|
||||
"region_name",
|
||||
"city_name",
|
||||
"isp_domain",
|
||||
"country_code",
|
||||
"continent_code",
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
errIPv4Only = "Navigator works for IPv4 only :)"
|
||||
)
|
||||
|
||||
type errorMessage struct {
|
||||
Error string `json:error`
|
||||
}
|
||||
|
||||
func responseWithError(resp http.ResponseWriter, statusCode int, message string) {
|
||||
resp.Header().Set("Content-Type", "text/plain")
|
||||
resp.WriteHeader(statusCode)
|
||||
resp.Write([]byte("error: " + message))
|
||||
}
|
||||
|
||||
func responseWithJsonError(resp http.ResponseWriter, statusCode int, message string) {
|
||||
resp.Header().Set("Content-Type", "application/json")
|
||||
body, err := json.Marshal(&errorMessage{
|
||||
Error: message,
|
||||
})
|
||||
resp.Header().Set("Content-Length", strconv.Itoa(len(body)))
|
||||
if err != nil {
|
||||
// This should never happen
|
||||
panic("json marshal failed, check code")
|
||||
}
|
||||
resp.WriteHeader(statusCode)
|
||||
resp.Write(body)
|
||||
}
|
||||
|
||||
func buildLocation(info *ipdb.CityInfo) string {
|
||||
ret := ""
|
||||
if info.CountryName != "" {
|
||||
ret += info.CountryName + " "
|
||||
}
|
||||
if info.RegionName != "" {
|
||||
ret += info.RegionName + " "
|
||||
}
|
||||
if info.CityName != "" {
|
||||
ret += info.CityName + " "
|
||||
}
|
||||
return strings.TrimSpace(ret)
|
||||
}
|
||||
|
||||
func main() {
|
||||
ipipdb := flag.String("ipdb-database", "ipip.db", "path to ipip database")
|
||||
flag.Parse()
|
||||
|
||||
db, err := ipdb.NewCity(*ipipdb)
|
||||
if err != nil {
|
||||
log.Fatalln("Unable to open ipdb:", err.Error())
|
||||
}
|
||||
if !db.IsIPv4() {
|
||||
log.Fatalln("This IPIP.net database has no IPv4 information!")
|
||||
}
|
||||
{
|
||||
fields := db.Fields()
|
||||
for _, requiredField := range requiredFields {
|
||||
ok := false
|
||||
for _, field := range fields {
|
||||
if field == requiredField {
|
||||
ok = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !ok {
|
||||
log.Fatalln("This IPIP.net database has no required field", requiredField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
http.HandleFunc("/healthz", func(resp http.ResponseWriter, req *http.Request) {
|
||||
resp.WriteHeader(200)
|
||||
resp.Write([]byte("ok"))
|
||||
})
|
||||
|
||||
http.HandleFunc("/info", func(resp http.ResponseWriter, req *http.Request) {
|
||||
host, _, err := net.SplitHostPort(req.RemoteAddr)
|
||||
if err != nil {
|
||||
responseWithError(resp, http.StatusPreconditionFailed, errIPv4Only)
|
||||
return
|
||||
}
|
||||
if net.ParseIP(host).To4() == nil {
|
||||
responseWithError(resp, http.StatusPreconditionFailed, errIPv4Only)
|
||||
return
|
||||
}
|
||||
|
||||
info_cn, err := db.FindInfo(host, "CN")
|
||||
if err != nil {
|
||||
fmt.Fprintf(resp, "IP %s not found in the database.", host)
|
||||
return
|
||||
}
|
||||
info_en, err := db.FindInfo(host, "EN")
|
||||
if err != nil {
|
||||
fmt.Fprintf(resp, "IP %s not found in the database.", host)
|
||||
return
|
||||
}
|
||||
resp.Header().Set("Content-Type", "text/plain")
|
||||
resp.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(resp, "您的IP:", host)
|
||||
fmt.Fprintln(resp, "数据库中IP所属位置:", buildLocation(info_cn))
|
||||
if info_cn.IspDomain != "" {
|
||||
fmt.Fprintln(resp, "数据库中IP所属运营商:", info_cn.IspDomain)
|
||||
}
|
||||
// TODO(jackyyf): add mapping info here
|
||||
|
||||
fmt.Fprintln(resp, "Your IP:", host)
|
||||
fmt.Fprintln(resp, "Location for your IP according our database:", buildLocation(info_en))
|
||||
if info_en.IspDomain != "" {
|
||||
fmt.Fprintln(resp, "ISP for your IP according our database:", info_en.IspDomain)
|
||||
}
|
||||
// TODO(jackyyf): add mapping info here
|
||||
|
||||
})
|
||||
http.ListenAndServe("0.0.0.0:8086", nil)
|
||||
}
|
Loading…
Reference in New Issue