adding test to include a response with all these new fields

This commit is contained in:
Dmitriy Shelikhov 2020-04-29 22:46:10 +07:00
parent ae769e61f9
commit 0c509605fa
4 changed files with 181 additions and 24 deletions

View File

@ -34,21 +34,21 @@ type Server struct {
type Response struct {
IP net.IP `json:"ip"`
IPDecimal *big.Int `json:"ip_decimal"`
Country string `json:"country,omitempty"`
CountryISO string `json:"country_iso,omitempty"`
CountryEU *bool `json:"country_eu,omitempty"`
RegionName string `json:"region_name,omitempty"`
RegionCode string `json:"region_code,omitempty"`
Country string `json:"country,omitempty"`
CountryEU *bool `json:"country_eu,omitempty"`
CountryISO string `json:"country_iso,omitempty"`
MetroCode uint `json:"metro_code,omitempty"`
PostalCode string `json:"zip_code,omitempty"`
City string `json:"city,omitempty"`
Hostname string `json:"hostname,omitempty"`
Latitude float64 `json:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty"`
Timezone string `json:"time_zone,omitempty"`
ASN string `json:"asn,omitempty"`
ASNOrg string `json:"asn_org,omitempty"`
Hostname string `json:"hostname,omitempty"`
UserAgent *useragent.UserAgent `json:"user_agent,omitempty"`
PostalCode string `json:"zip_code,omitempty"`
Timezone string `json:"time_zone,omitempty"`
MetroCode uint `json:"metro_code,omitempty"`
}
type PortResponse struct {
@ -127,18 +127,18 @@ func (s *Server) newResponse(r *http.Request) (Response, error) {
Country: country.Name,
CountryISO: country.ISO,
CountryEU: country.IsEU,
City: city.Name,
Hostname: hostname,
Latitude: city.Latitude,
Longitude: city.Longitude,
ASN: autonomousSystemNumber,
ASNOrg: asn.AutonomousSystemOrganization,
UserAgent: userAgent,
PostalCode: city.PostalCode,
Timezone: city.Timezone,
MetroCode: city.MetroCode,
RegionName: city.RegionName,
RegionCode: city.RegionCode,
MetroCode: city.MetroCode,
PostalCode: city.PostalCode,
City: city.Name,
Latitude: city.Latitude,
Longitude: city.Longitude,
Timezone: city.Timezone,
ASN: autonomousSystemNumber,
ASNOrg: asn.AutonomousSystemOrganization,
Hostname: hostname,
UserAgent: userAgent,
}
s.cache.Set(ip, response)
return *response, nil

View File

@ -21,7 +21,7 @@ func (t *testDb) Country(net.IP) (geo.Country, error) {
}
func (t *testDb) City(net.IP) (geo.City, error) {
return geo.City{Name: "Bornyasherk", Latitude: 63.416667, Longitude: 10.416667}, nil
return geo.City{Name: "Bornyasherk", RegionName: "North Elbonia", RegionCode: "1234", MetroCode: 1234, PostalCode: "1234", Latitude: 63.416667, Longitude: 10.416667, Timezone: "Europe/Bornyasherk"}, nil
}
func (t *testDb) ASN(net.IP) (geo.ASN, error) {
@ -134,7 +134,7 @@ func TestJSONHandlers(t *testing.T) {
out string
status int
}{
{s.URL, `{"ip":"127.0.0.1","ip_decimal":2130706433,"country":"Elbonia","country_eu":false,"country_iso":"EB","city":"Bornyasherk","hostname":"localhost","latitude":63.416667,"longitude":10.416667,"asn":"AS59795","asn_org":"Hosting4Real","user_agent":{"product":"curl","version":"7.2.6.0","raw_value":"curl/7.2.6.0"}}`, 200},
{s.URL, `{"ip":"127.0.0.1","ip_decimal":2130706433,"country":"Elbonia","country_iso":"EB","country_eu":false,"region_name":"North Elbonia","region_code":"1234","metro_code":1234,"zip_code":"1234","city":"Bornyasherk","latitude":63.416667,"longitude":10.416667,"time_zone":"Europe/Bornyasherk","asn":"AS59795","asn_org":"Hosting4Real","hostname":"localhost","user_agent":{"product":"curl","version":"7.2.6.0","raw_value":"curl/7.2.6.0"}}`, 200},
{s.URL + "/port/foo", `{"error":"invalid port: foo"}`, 400},
{s.URL + "/port/0", `{"error":"invalid port: 0"}`, 400},
{s.URL + "/port/65537", `{"error":"invalid port: 65537"}`, 400},

View File

@ -106,29 +106,30 @@ func (g *geoip) City(ip net.IP) (City, error) {
if c, exists := record.City.Names["en"]; exists {
city.Name = c
}
if len(record.Subdivisions)>0 {
if len(record.Subdivisions) > 0 {
if c, exists := record.Subdivisions[0].Names["en"]; exists {
city.RegionName = c
}
if record.Subdivisions[0].IsoCode != "" {
city.RegionCode = record.Subdivisions[0].IsoCode
}
}
}
if !math.IsNaN(record.Location.Latitude) {
city.Latitude = record.Location.Latitude
}
if !math.IsNaN(record.Location.Longitude) {
city.Longitude = record.Location.Longitude
}
if record.Location.TimeZone != "" {
city.Timezone = record.Location.TimeZone
}
if record.Location.MetroCode > 0 && record.Country.IsoCode == "US" {
city.MetroCode = record.Location.MetroCode
}
if record.Postal.Code != "" {
city.PostalCode = record.Postal.Code
}
if record.Location.TimeZone != "" {
city.Timezone = record.Location.TimeZone
}
return city, nil
}

156
iputil/geo/geo/geo.go Normal file
View File

@ -0,0 +1,156 @@
package geo
import (
"math"
"net"
geoip2 "github.com/oschwald/geoip2-golang"
)
type Reader interface {
Country(net.IP) (Country, error)
City(net.IP) (City, error)
ASN(net.IP) (ASN, error)
IsEmpty() bool
}
type Country struct {
Name string
ISO string
IsEU *bool
}
type City struct {
Name string
Latitude float64
Longitude float64
PostalCode string
Timezone string
MetroCode uint
RegionName string
RegionCode string
}
type ASN struct {
AutonomousSystemNumber uint
AutonomousSystemOrganization string
}
type geoip struct {
country *geoip2.Reader
city *geoip2.Reader
asn *geoip2.Reader
}
func Open(countryDB, cityDB string, asnDB string) (Reader, error) {
var country, city, asn *geoip2.Reader
if countryDB != "" {
r, err := geoip2.Open(countryDB)
if err != nil {
return nil, err
}
country = r
}
if cityDB != "" {
r, err := geoip2.Open(cityDB)
if err != nil {
return nil, err
}
city = r
}
if asnDB != "" {
r, err := geoip2.Open(asnDB)
if err != nil {
return nil, err
}
asn = r
}
return &geoip{country: country, city: city, asn: asn}, nil
}
func (g *geoip) Country(ip net.IP) (Country, error) {
country := Country{}
if g.country == nil {
return country, nil
}
record, err := g.country.Country(ip)
if err != nil {
return country, err
}
if c, exists := record.Country.Names["en"]; exists {
country.Name = c
}
if c, exists := record.RegisteredCountry.Names["en"]; exists && country.Name == "" {
country.Name = c
}
if record.Country.IsoCode != "" {
country.ISO = record.Country.IsoCode
}
if record.RegisteredCountry.IsoCode != "" && country.ISO == "" {
country.ISO = record.RegisteredCountry.IsoCode
}
isEU := record.Country.IsInEuropeanUnion || record.RegisteredCountry.IsInEuropeanUnion
country.IsEU = &isEU
return country, nil
}
func (g *geoip) City(ip net.IP) (City, error) {
city := City{}
if g.city == nil {
return city, nil
}
record, err := g.city.City(ip)
if err != nil {
return city, err
}
if c, exists := record.City.Names["en"]; exists {
city.Name = c
}
if len(record.Subdivisions) > 0 {
if c, exists := record.Subdivisions[0].Names["en"]; exists {
city.RegionName = c
}
if record.Subdivisions[0].IsoCode != "" {
city.RegionCode = record.Subdivisions[0].IsoCode
}
}
if !math.IsNaN(record.Location.Latitude) {
city.Latitude = record.Location.Latitude
}
if !math.IsNaN(record.Location.Longitude) {
city.Longitude = record.Location.Longitude
}
if record.Location.MetroCode > 0 && record.Country.IsoCode == "US" {
city.MetroCode = record.Location.MetroCode
}
if record.Postal.Code != "" {
city.PostalCode = record.Postal.Code
}
if record.Location.TimeZone != "" {
city.Timezone = record.Location.TimeZone
}
return city, nil
}
func (g *geoip) ASN(ip net.IP) (ASN, error) {
asn := ASN{}
if g.asn == nil {
return asn, nil
}
record, err := g.asn.ASN(ip)
if err != nil {
return asn, err
}
if record.AutonomousSystemNumber > 0 {
asn.AutonomousSystemNumber = record.AutonomousSystemNumber
}
if record.AutonomousSystemOrganization != "" {
asn.AutonomousSystemOrganization = record.AutonomousSystemOrganization
}
return asn, nil
}
func (g *geoip) IsEmpty() bool {
return g.country == nil && g.city == nil
}