some refactoring

This commit is contained in:
Ethan Knowlton 2023-10-04 14:19:05 -04:00
parent 410002ff47
commit 6c950e10d3
6 changed files with 184 additions and 99 deletions

2
go.sum
View File

@ -9,6 +9,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/qioalice/ipstack v1.0.1 h1:Ync2O+tR2AH9/TzTg4aeJxd9c1Xz2CeH1joECwnhvms=
github.com/qioalice/ipstack v1.0.1/go.mod h1:6eB9LdNCUdUoOsfDB8Pn2GpmD2I+f2k3yR30ceuf/rY=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -18,5 +19,6 @@ golang.org/x/sys v0.0.0-20210223212115-eede4237b368 h1:fDE3p0qf2V1co1vfj3/o87Ps8
golang.org/x/sys v0.0.0-20210223212115-eede4237b368/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -136,10 +136,9 @@
<th scope="row">Timezone</th>
<td>{{ .Timezone }}</td>
</tr>
{{ end }} {{ if .IsDayLightSavings }}
<tr>
<th scope="row">Is Daylight Savings?</th>
<td>{{ .IsDayLightSavings }}</td>
<td>{{ .TimezoneEtc.IsDaylightSavings }}</td>
</tr>
{{ end }} {{ if .ASN }}
<tr>
@ -176,35 +175,35 @@
{{ if .IPStackSecurityEnabled }}
<tr>
<th scope="row">Is Proxy?</th>
<td>{{ .IsProxy }}</td>
<td>{{ .Security.IsProxy }}</td>
</tr>
<tr>
<th scope="row">Is Crawler?</th>
<td>{{ .IsCrawler }}</td>
<td>{{ .Security.IsCrawler }}</td>
</tr>
{{ if .IsCrawler }}
{{ if .Security.IsCrawler }}
<tr>
<th scope="row">Crawler Name</th>
<td>{{ .CrawlerName }}</td>
<td>{{ .Security.CrawlerName }}</td>
</tr>
<tr>
<th scope="row">Crawler Type</th>
<td>{{ .CrawlerType }}</td>
<td>{{ .Security.CrawlerType }}</td>
</tr>
{{ end }}
<tr>
<th scope="row">Is Tor?</th>
<td>{{ .IsTor }}</td>
<td>{{ .Security.IsTor }}</td>
</tr>
<tr>
<th scope="row">Threat Level</th>
<td>{{ .ThreatLevel }}</td>
<td>{{ .Security.ThreatLevel }}</td>
</tr>
<tr>
<th scope="row">Threat Types</th>
<td>{{ .ThreatTypes }}</td>
<td>{{ .Security.ThreatTypes }}</td>
</tr>
{{ end }}

View File

@ -163,7 +163,7 @@ func TestDisabledHandlers(t *testing.T) {
{s.URL + "/country", "404 page not found", 404},
{s.URL + "/country-iso", "404 page not found", 404},
{s.URL + "/city", "404 page not found", 404},
{s.URL + "/json", "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"IPStackSecurityEnabled\": false,\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433\n}", 200},
{s.URL + "/json", "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"IPStackSecurityEnabled\": false,\n \"timezone_etc\": {},\n \"security\": {\n \"is_proxy\": false,\n \"is_crawler\": false,\n \"is_tor\": false\n },\n \"currency\": {},\n \"location\": {\n \"country_flag\": {}\n },\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433\n}", 200},
}
for _, tt := range tests {
@ -189,7 +189,7 @@ func TestJSONHandlers(t *testing.T) {
out string
status int
}{
{s.URL, "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"IPStackSecurityEnabled\": false,\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433,\n \"country\": \"Elbonia\",\n \"country_iso\": \"EB\",\n \"country_eu\": false,\n \"region_name\": \"North Elbonia\",\n \"region_code\": \"1234\",\n \"metro_code\": 1234,\n \"zip_code\": \"1234\",\n \"city\": \"Bornyasherk\",\n \"latitude\": 63.416667,\n \"longitude\": 10.416667,\n \"time_zone\": \"Europe/Bornyasherk\",\n \"asn\": \"AS59795\",\n \"asn_org\": \"Hosting4Real\",\n \"hostname\": \"localhost\",\n \"user_agent\": {\n \"product\": \"curl\",\n \"version\": \"7.2.6.0\",\n \"raw_value\": \"curl/7.2.6.0\"\n }\n}", 200},
{s.URL, "{\n \"UsingGeoIP\": true,\n \"UsingIPStack\": false,\n \"IPStackSecurityEnabled\": false,\n \"timezone_etc\": {},\n \"security\": {\n \"is_proxy\": false,\n \"is_crawler\": false,\n \"is_tor\": false\n },\n \"currency\": {},\n \"location\": {\n \"country_flag\": {}\n },\n \"ip\": \"127.0.0.1\",\n \"ip_decimal\": 2130706433,\n \"country\": \"Elbonia\",\n \"country_iso\": \"EB\",\n \"country_eu\": false,\n \"region_name\": \"North Elbonia\",\n \"region_code\": \"1234\",\n \"metro_code\": 1234,\n \"zip_code\": \"1234\",\n \"city\": \"Bornyasherk\",\n \"latitude\": 63.416667,\n \"longitude\": 10.416667,\n \"timezone\": \"Europe/Bornyasherk\",\n \"asn\": \"AS59795\",\n \"asn_org\": \"Hosting4Real\",\n \"hostname\": \"localhost\",\n \"user_agent\": {\n \"product\": \"curl\",\n \"version\": \"7.2.6.0\",\n \"raw_value\": \"curl/7.2.6.0\"\n }\n}", 200},
{s.URL + "/port/foo", "{\n \"status\": 400,\n \"error\": \"invalid port: foo\"\n}", 400},
{s.URL + "/port/0", "{\n \"status\": 400,\n \"error\": \"invalid port: 0\"\n}", 400},
{s.URL + "/port/65537", "{\n \"status\": 400,\n \"error\": \"invalid port: 65537\"\n}", 400},

View File

@ -84,22 +84,24 @@ func (g *geoip) Parse(ip net.IP, hostname string) (parser.Response, error) {
UsingGeoIP: true,
UsingIPStack: false,
IPStackSecurityEnabled: false,
IP: ip,
IPDecimal: ipDecimal,
Country: country.Name,
CountryISO: country.ISO,
CountryEU: country.IsEU,
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,
/* kept for backward compatibility */
IP: ip,
IPDecimal: ipDecimal,
Country: country.Name,
CountryISO: country.ISO,
CountryEU: country.IsEU,
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,
}, nil
}

View File

@ -3,10 +3,11 @@ package ipstack
import (
"fmt"
"net"
"reflect"
"time"
"github.com/mpolden/echoip/iputil"
parser "github.com/mpolden/echoip/iputil/paser"
"github.com/qioalice/ipstack"
)
@ -17,6 +18,7 @@ type IPStack struct {
func (ips *IPStack) Parse(ip net.IP, hostname string) (parser.Response, error) {
res, err := ipstack.IP(ip.String())
ips.response = res
if err != nil {
return parser.Response{}, err
}
@ -26,52 +28,91 @@ func (ips *IPStack) Parse(ip net.IP, hostname string) (parser.Response, error) {
parserResponse := parser.Response{
UsingGeoIP: false,
UsingIPStack: true,
Latitude: float64(res.Latitide),
Longitude: float64(res.Longitude),
Hostname: hostname,
IP: ip,
IPDecimal: ipDecimal,
Country: res.CountryName,
CountryISO: res.CountryCode,
RegionName: res.RegionName,
RegionCode: res.RegionCode,
MetroCode: 0,
PostalCode: res.Zip,
City: res.City,
/* kept for backward compatibility */
Latitude: float64(res.Latitide),
Longitude: float64(res.Longitude),
Hostname: hostname,
IP: ip,
IPDecimal: ipDecimal,
Country: res.CountryName,
CountryISO: res.CountryCode,
RegionName: res.RegionName,
RegionCode: res.RegionCode,
MetroCode: 0,
PostalCode: res.Zip,
City: res.City,
}
if res.Timezone != nil {
parserResponse.Timezone = res.Timezone.ID
parserResponse.IsDayLightSavings = res.Timezone.IsDaylightSaving
}
if res.Security != nil {
parserResponse.IPStackSecurityEnabled = true
parserResponse.IsProxy = res.Security.IsProxy
parserResponse.IsCrawler = res.Security.IsCrawler
parserResponse.CrawlerName = res.Security.CrawlerName
parserResponse.CrawlerType = res.Security.CrawlerType
parserResponse.IsTor = res.Security.IsTOR
parserResponse.ThreatLevel = res.Security.ThreatLevel
if !reflect.ValueOf(&res.Security.ThreatTypes).IsNil() {
parserResponse.ThreatTypes = &res.Security.ThreatTypes
}
}
if res.Location != nil {
parserResponse.CountryEU = &res.Location.IsEU
}
if res.Connection != nil {
if res.Connection.ASN > 0 {
parserResponse.ASN = fmt.Sprintf("AS%d", res.Connection.ASN)
}
}
ips.ParseSecurityResponse(&parserResponse)
ips.ParseTimezoneResponse(&parserResponse)
ips.ParseLocationResponse(&parserResponse)
ips.ParseConnectionResponse(&parserResponse)
return parserResponse, nil
}
func (ips *IPStack) ParseSecurityResponse(parserResponse *parser.Response) {
if ips.response.Security != nil {
parserResponse.IPStackSecurityEnabled = true
parserResponse.Security = parser.Security{
IsProxy: ips.response.Security.IsProxy,
IsTor: ips.response.Security.IsTOR,
CrawlerName: ips.response.Security.CrawlerName,
CrawlerType: ips.response.Security.CrawlerType,
ThreatLevel: ips.response.Security.ThreatLevel,
ThreatTypes: ips.response.Security.ThreatTypes,
}
}
}
func (ips *IPStack) ParseTimezoneResponse(parserResponse *parser.Response) {
if ips.response.Timezone != nil {
parserResponse.TimezoneEtc = parser.Timezone{
ID: ips.response.Timezone.ID,
CurrentTime: ips.response.Timezone.CurrentTime.Format(time.RFC3339),
GmtOffset: ips.response.Timezone.GMTOffset,
Code: ips.response.Timezone.Code,
IsDaylightSavings: ips.response.Timezone.IsDaylightSaving,
}
/* kept for backward compatibility */
parserResponse.Timezone = ips.response.Timezone.ID
}
}
func (ips *IPStack) ParseLocationResponse(parserResponse *parser.Response) {
if ips.response.Location != nil {
var languages []parser.Language
for i := 0; i < len(ips.response.Location.Languages); i++ {
languages = append(languages, parser.Language{
Code: ips.response.Location.Languages[i].Code,
Name: ips.response.Location.Languages[i].Name,
Native: ips.response.Location.Languages[i].NativeName,
})
}
parserResponse.Location = parser.Location{
Languages: languages,
CountryFlag: parser.CountryFlag{
Flag: ips.response.Location.CountryFlagLink,
Emoji: ips.response.Location.CountryFlagEmoji,
EmojiUnicode: ips.response.Location.CountryFlagEmojiUnicode,
},
}
/* kept for backward compatibility */
parserResponse.CountryEU = &ips.response.Location.IsEU
}
}
func (ips *IPStack) ParseConnectionResponse(parserResponse *parser.Response) {
if ips.response.Connection != nil && ips.response.Connection.ASN > 0 {
/* kept for backward compatibility */
parserResponse.ASN = fmt.Sprintf("AS%d", ips.response.Connection.ASN)
}
}
func (ips *IPStack) IsEmpty() bool {
return false
}

View File

@ -12,34 +12,75 @@ type Parser interface {
IsEmpty() bool
}
type Response struct {
UsingGeoIP bool `json:"UsingGeoIP"`
UsingIPStack bool `json:"UsingIPStack"`
IPStackSecurityEnabled bool `json:"IPStackSecurityEnabled"`
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"`
MetroCode uint `json:"metro_code,omitempty"`
PostalCode string `json:"zip_code,omitempty"`
City string `json:"city,omitempty"`
Latitude float64 `json:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty"`
Timezone string `json:"time_zone,omitempty"`
IsDayLightSavings bool `json:"is_daylight_savings,omitempty"`
ASN string `json:"asn,omitempty"`
ASNOrg string `json:"asn_org,omitempty"`
Hostname string `json:"hostname,omitempty"`
UserAgent *useragent.UserAgent `json:"user_agent,omitempty"`
CurrencyCode string `json:"currency_code,omitempty"`
IsProxy bool `json:"is_proxy,omitempty"`
IsCrawler bool `json:"is_crawler,omitempty"`
CrawlerName string `json:"crawler_name,omitempty"`
CrawlerType string `json:"crawler_type,omitempty"`
IsTor bool `json:"is_tor,omitempty"`
ThreatLevel string `json:"threat_level,omitempty"`
ThreatTypes *interface{} `json:"threat_types,omitempty"`
type Currency struct {
Code string `json:"code,omitempty"`
Name string `json:"name,omitempty"`
Plural string `json:"plural,omitempty"`
Symbol string `json:"symbol,omitempty"`
SymbolNative string `json:"symbol_native,omitempty"`
}
type Security struct {
IsProxy bool `json:"is_proxy"`
IsCrawler bool `json:"is_crawler"`
CrawlerName string `json:"crawler_name,omitempty"`
CrawlerType string `json:"crawler_type,omitempty"`
IsTor bool `json:"is_tor"`
ThreatLevel string `json:"threat_level,omitempty"`
ThreatTypes interface{} `json:"threat_types,omitempty"`
}
type Timezone struct {
ID string `json:"id,omitempty"`
CurrentTime string `json:"current_time,omitempty"`
GmtOffset int `json:"gmt_offset,omitempty"`
Code string `json:"code,omitempty"`
IsDaylightSavings bool `json:"is_daylight_savings,omitempty"`
}
type Language struct {
Code string `json:"code,omitempty"`
Name string `json:"name,omitempty"`
Native string `json:"native,omitempty"`
}
type CountryFlag struct {
Flag string `json:"flag,omitempty"`
Emoji string `json:"emoji,omitempty"`
EmojiUnicode string `json:"emoji_unicode,omitempty"`
}
type Location struct {
Languages interface{} `json:"languages,omitempty"`
CountryFlag CountryFlag `json:"country_flag,omitempty"`
}
type Response struct {
UsingGeoIP bool `json:"UsingGeoIP"`
UsingIPStack bool `json:"UsingIPStack"`
IPStackSecurityEnabled bool `json:"IPStackSecurityEnabled"`
TimezoneEtc Timezone `json:"timezone_etc,omitempty"`
Security Security `json:"security,omitempty"`
Currency Currency `json:"currency,omitempty"`
Location Location `json:"location,omitempty"`
/* Kept to prevent breaking changes */
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"`
MetroCode uint `json:"metro_code,omitempty"`
PostalCode string `json:"zip_code,omitempty"`
City string `json:"city,omitempty"`
Latitude float64 `json:"latitude,omitempty"`
Longitude float64 `json:"longitude,omitempty"`
Timezone string `json:"timezone,omitempty"`
ASN string `json:"asn,omitempty"`
ASNOrg string `json:"asn_org,omitempty"`
Hostname string `json:"hostname,omitempty"`
UserAgent *useragent.UserAgent `json:"user_agent,omitempty"`
}