mirror of
https://github.com/mpolden/echoip.git
synced 2025-05-11 00:16:31 +02:00
Patch for ISO and Map display (#45)
This commit is contained in:
parent
9f839c5f36
commit
c195bae4fb
@ -32,6 +32,9 @@ Country and city lookup:
|
|||||||
$ http ifconfig.co/country
|
$ http ifconfig.co/country
|
||||||
Elbonia
|
Elbonia
|
||||||
|
|
||||||
|
$ http ifconfig.co/country-iso
|
||||||
|
EB
|
||||||
|
|
||||||
$ http ifconfig.co/city
|
$ http ifconfig.co/city
|
||||||
Bornyasherk
|
Bornyasherk
|
||||||
```
|
```
|
||||||
@ -43,6 +46,7 @@ $ http --json ifconfig.co
|
|||||||
{
|
{
|
||||||
"city": "Bornyasherk",
|
"city": "Bornyasherk",
|
||||||
"country": "Elbonia",
|
"country": "Elbonia",
|
||||||
|
"country_iso": "EB",
|
||||||
"ip": "127.0.0.1",
|
"ip": "127.0.0.1",
|
||||||
"ip_decimal": 2130706433
|
"ip_decimal": 2130706433
|
||||||
}
|
}
|
||||||
|
36
api/api.go
36
api/api.go
@ -31,11 +31,12 @@ type API struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
type Response struct {
|
||||||
IP net.IP `json:"ip"`
|
IP net.IP `json:"ip"`
|
||||||
IPDecimal *big.Int `json:"ip_decimal"`
|
IPDecimal *big.Int `json:"ip_decimal"`
|
||||||
Country string `json:"country,omitempty"`
|
Country string `json:"country,omitempty"`
|
||||||
City string `json:"city,omitempty"`
|
CountryISO string `json:"country_iso,omitempty"`
|
||||||
Hostname string `json:"hostname,omitempty"`
|
City string `json:"city,omitempty"`
|
||||||
|
Hostname string `json:"hostname,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PortResponse struct {
|
type PortResponse struct {
|
||||||
@ -84,6 +85,10 @@ func (a *API) newResponse(r *http.Request) (Response, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Debug(err)
|
a.log.Debug(err)
|
||||||
}
|
}
|
||||||
|
countryISO, err := a.oracle.LookupCountryISO(ip)
|
||||||
|
if err != nil {
|
||||||
|
a.log.Debug(err)
|
||||||
|
}
|
||||||
city, err := a.oracle.LookupCity(ip)
|
city, err := a.oracle.LookupCity(ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
a.log.Debug(err)
|
a.log.Debug(err)
|
||||||
@ -93,11 +98,12 @@ func (a *API) newResponse(r *http.Request) (Response, error) {
|
|||||||
a.log.Debug(err)
|
a.log.Debug(err)
|
||||||
}
|
}
|
||||||
return Response{
|
return Response{
|
||||||
IP: ip,
|
IP: ip,
|
||||||
IPDecimal: ipDecimal,
|
IPDecimal: ipDecimal,
|
||||||
Country: country,
|
Country: country,
|
||||||
City: city,
|
CountryISO: countryISO,
|
||||||
Hostname: strings.Join(hostnames, " "),
|
City: city,
|
||||||
|
Hostname: strings.Join(hostnames, " "),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +146,15 @@ func (a *API) CLICountryHandler(w http.ResponseWriter, r *http.Request) *appErro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *API) CLICountryISOHandler(w http.ResponseWriter, r *http.Request) *appError {
|
||||||
|
response, err := a.newResponse(r)
|
||||||
|
if err != nil {
|
||||||
|
return internalServerError(err)
|
||||||
|
}
|
||||||
|
fmt.Fprintln(w, response.CountryISO)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *API) CLICityHandler(w http.ResponseWriter, r *http.Request) *appError {
|
func (a *API) CLICityHandler(w http.ResponseWriter, r *http.Request) *appError {
|
||||||
response, err := a.newResponse(r)
|
response, err := a.newResponse(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -250,6 +265,7 @@ func (a *API) Router() http.Handler {
|
|||||||
r.Handle("/", appHandler(a.CLIHandler)).Methods("GET").Headers("Accept", textMediaType)
|
r.Handle("/", appHandler(a.CLIHandler)).Methods("GET").Headers("Accept", textMediaType)
|
||||||
r.Handle("/ip", appHandler(a.CLIHandler)).Methods("GET")
|
r.Handle("/ip", appHandler(a.CLIHandler)).Methods("GET")
|
||||||
r.Handle("/country", appHandler(a.CLICountryHandler)).Methods("GET")
|
r.Handle("/country", appHandler(a.CLICountryHandler)).Methods("GET")
|
||||||
|
r.Handle("/country-iso", appHandler(a.CLICountryISOHandler)).Methods("GET")
|
||||||
r.Handle("/city", appHandler(a.CLICityHandler)).Methods("GET")
|
r.Handle("/city", appHandler(a.CLICityHandler)).Methods("GET")
|
||||||
|
|
||||||
// Browser
|
// Browser
|
||||||
|
@ -12,14 +12,15 @@ import (
|
|||||||
|
|
||||||
type mockOracle struct{}
|
type mockOracle struct{}
|
||||||
|
|
||||||
func (r *mockOracle) LookupAddr(net.IP) ([]string, error) { return []string{"localhost"}, nil }
|
func (r *mockOracle) LookupAddr(net.IP) ([]string, error) { return []string{"localhost"}, nil }
|
||||||
func (r *mockOracle) LookupCountry(net.IP) (string, error) { return "Elbonia", nil }
|
func (r *mockOracle) LookupCountry(net.IP) (string, error) { return "Elbonia", nil }
|
||||||
func (r *mockOracle) LookupCity(net.IP) (string, error) { return "Bornyasherk", nil }
|
func (r *mockOracle) LookupCountryISO(net.IP) (string, error) { return "EB", nil }
|
||||||
func (r *mockOracle) LookupPort(net.IP, uint64) error { return nil }
|
func (r *mockOracle) LookupCity(net.IP) (string, error) { return "Bornyasherk", nil }
|
||||||
func (r *mockOracle) IsLookupAddrEnabled() bool { return true }
|
func (r *mockOracle) LookupPort(net.IP, uint64) error { return nil }
|
||||||
func (r *mockOracle) IsLookupCountryEnabled() bool { return true }
|
func (r *mockOracle) IsLookupAddrEnabled() bool { return true }
|
||||||
func (r *mockOracle) IsLookupCityEnabled() bool { return true }
|
func (r *mockOracle) IsLookupCountryEnabled() bool { return true }
|
||||||
func (r *mockOracle) IsLookupPortEnabled() bool { return true }
|
func (r *mockOracle) IsLookupCityEnabled() bool { return true }
|
||||||
|
func (r *mockOracle) IsLookupPortEnabled() bool { return true }
|
||||||
|
|
||||||
func newTestAPI() *API {
|
func newTestAPI() *API {
|
||||||
return &API{oracle: &mockOracle{}}
|
return &API{oracle: &mockOracle{}}
|
||||||
@ -61,6 +62,7 @@ func TestCLIHandlers(t *testing.T) {
|
|||||||
{s.URL, "127.0.0.1\n", 200, "foo/bar", textMediaType},
|
{s.URL, "127.0.0.1\n", 200, "foo/bar", textMediaType},
|
||||||
{s.URL + "/ip", "127.0.0.1\n", 200, "", ""},
|
{s.URL + "/ip", "127.0.0.1\n", 200, "", ""},
|
||||||
{s.URL + "/country", "Elbonia\n", 200, "", ""},
|
{s.URL + "/country", "Elbonia\n", 200, "", ""},
|
||||||
|
{s.URL + "/country-iso", "EB\n", 200, "", ""},
|
||||||
{s.URL + "/city", "Bornyasherk\n", 200, "", ""},
|
{s.URL + "/city", "Bornyasherk\n", 200, "", ""},
|
||||||
{s.URL + "/foo", "404 page not found", 404, "", ""},
|
{s.URL + "/foo", "404 page not found", 404, "", ""},
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ func TestJSONHandlers(t *testing.T) {
|
|||||||
out string
|
out string
|
||||||
status int
|
status int
|
||||||
}{
|
}{
|
||||||
{s.URL, `{"ip":"127.0.0.1","ip_decimal":2130706433,"country":"Elbonia","city":"Bornyasherk","hostname":"localhost"}`, 200},
|
{s.URL, `{"ip":"127.0.0.1","ip_decimal":2130706433,"country":"Elbonia","country_iso":"EB","city":"Bornyasherk","hostname":"localhost"}`, 200},
|
||||||
{s.URL + "/port/foo", `{"error":"404 page not found"}`, 404},
|
{s.URL + "/port/foo", `{"error":"404 page not found"}`, 404},
|
||||||
{s.URL + "/port/0", `{"error":"Invalid port: 0"}`, 400},
|
{s.URL + "/port/0", `{"error":"Invalid port: 0"}`, 400},
|
||||||
{s.URL + "/port/65356", `{"error":"Invalid port: 65356"}`, 400},
|
{s.URL + "/port/65356", `{"error":"Invalid port: 65356"}`, 400},
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
type Oracle interface {
|
type Oracle interface {
|
||||||
LookupAddr(net.IP) ([]string, error)
|
LookupAddr(net.IP) ([]string, error)
|
||||||
LookupCountry(net.IP) (string, error)
|
LookupCountry(net.IP) (string, error)
|
||||||
|
LookupCountryISO(net.IP) (string, error)
|
||||||
LookupCity(net.IP) (string, error)
|
LookupCity(net.IP) (string, error)
|
||||||
LookupPort(net.IP, uint64) error
|
LookupPort(net.IP, uint64) error
|
||||||
IsLookupAddrEnabled() bool
|
IsLookupAddrEnabled() bool
|
||||||
@ -23,6 +24,7 @@ type Oracle interface {
|
|||||||
type DefaultOracle struct {
|
type DefaultOracle struct {
|
||||||
lookupAddr func(net.IP) ([]string, error)
|
lookupAddr func(net.IP) ([]string, error)
|
||||||
lookupCountry func(net.IP) (string, error)
|
lookupCountry func(net.IP) (string, error)
|
||||||
|
lookupCountryISO func(net.IP) (string, error)
|
||||||
lookupCity func(net.IP) (string, error)
|
lookupCity func(net.IP) (string, error)
|
||||||
lookupPort func(net.IP, uint64) error
|
lookupPort func(net.IP, uint64) error
|
||||||
lookupAddrEnabled bool
|
lookupAddrEnabled bool
|
||||||
@ -33,10 +35,11 @@ type DefaultOracle struct {
|
|||||||
|
|
||||||
func NewOracle() *DefaultOracle {
|
func NewOracle() *DefaultOracle {
|
||||||
return &DefaultOracle{
|
return &DefaultOracle{
|
||||||
lookupAddr: func(net.IP) ([]string, error) { return nil, nil },
|
lookupAddr: func(net.IP) ([]string, error) { return nil, nil },
|
||||||
lookupCountry: func(net.IP) (string, error) { return "", nil },
|
lookupCountry: func(net.IP) (string, error) { return "", nil },
|
||||||
lookupCity: func(net.IP) (string, error) { return "", nil },
|
lookupCountryISO: func(net.IP) (string, error) { return "", nil },
|
||||||
lookupPort: func(net.IP, uint64) error { return nil },
|
lookupCity: func(net.IP) (string, error) { return "", nil },
|
||||||
|
lookupPort: func(net.IP, uint64) error { return nil },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,6 +51,10 @@ func (r *DefaultOracle) LookupCountry(ip net.IP) (string, error) {
|
|||||||
return r.lookupCountry(ip)
|
return r.lookupCountry(ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *DefaultOracle) LookupCountryISO(ip net.IP) (string, error) {
|
||||||
|
return r.lookupCountryISO(ip)
|
||||||
|
}
|
||||||
|
|
||||||
func (r *DefaultOracle) LookupCity(ip net.IP) (string, error) {
|
func (r *DefaultOracle) LookupCity(ip net.IP) (string, error) {
|
||||||
return r.lookupCity(ip)
|
return r.lookupCity(ip)
|
||||||
}
|
}
|
||||||
@ -69,6 +76,9 @@ func (r *DefaultOracle) EnableLookupCountry(filepath string) error {
|
|||||||
r.lookupCountry = func(ip net.IP) (string, error) {
|
r.lookupCountry = func(ip net.IP) (string, error) {
|
||||||
return lookupCountry(db, ip)
|
return lookupCountry(db, ip)
|
||||||
}
|
}
|
||||||
|
r.lookupCountryISO = func(ip net.IP) (string, error) {
|
||||||
|
return lookupCountryISO(db, ip)
|
||||||
|
}
|
||||||
r.lookupCountryEnabled = true
|
r.lookupCountryEnabled = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -127,6 +137,20 @@ func lookupCountry(db *geoip2.Reader, ip net.IP) (string, error) {
|
|||||||
return "Unknown", fmt.Errorf("could not determine country for IP: %s", ip)
|
return "Unknown", fmt.Errorf("could not determine country for IP: %s", ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func lookupCountryISO(db *geoip2.Reader, ip net.IP) (string, error) {
|
||||||
|
record, err := db.City(ip)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if record.Country.IsoCode != "" {
|
||||||
|
return record.Country.IsoCode, nil
|
||||||
|
}
|
||||||
|
if record.RegisteredCountry.IsoCode != "" {
|
||||||
|
return record.RegisteredCountry.IsoCode, nil
|
||||||
|
}
|
||||||
|
return "Unknown", fmt.Errorf("could not determine country ISO Code for IP: %s", ip)
|
||||||
|
}
|
||||||
|
|
||||||
func lookupCity(db *geoip2.Reader, ip net.IP) (string, error) {
|
func lookupCity(db *geoip2.Reader, ip net.IP) (string, error) {
|
||||||
record, err := db.City(ip)
|
record, err := db.City(ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
16
index.html
16
index.html
@ -63,6 +63,10 @@ $ bat -print=b {{ .Host }}/ip
|
|||||||
<pre>
|
<pre>
|
||||||
$ http {{ .Host }}/country
|
$ http {{ .Host }}/country
|
||||||
{{ .Country }}</pre>
|
{{ .Country }}</pre>
|
||||||
|
<h2>Short country code (ISO 3166-1 alpha-2) lookup:</h2>
|
||||||
|
<pre>
|
||||||
|
$ http {{ .Host }}/country-iso
|
||||||
|
{{ .CountryISO }}</pre>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ if .IsLookupCityEnabled }}
|
{{ if .IsLookupCityEnabled }}
|
||||||
<h2>City lookup:</h2>
|
<h2>City lookup:</h2>
|
||||||
@ -76,8 +80,9 @@ $ http {{ .Host }}/city
|
|||||||
<pre>
|
<pre>
|
||||||
$ http {{ .Host }}/json
|
$ http {{ .Host }}/json
|
||||||
{ {{ if .IsLookupCityEnabled }}
|
{ {{ if .IsLookupCityEnabled }}
|
||||||
"city": "{{ .City }}",{{ end }}{{ if .IsLookupCountryEnabled }}
|
"city": "{{ .City }}",
|
||||||
"country": "{{ .Country }}",{{ end }}{{ if .IsLookupAddrEnabled }}
|
"country": "{{ .Country }}",
|
||||||
|
"country_iso": "{{ .CountryISO }}",{{ end }}{{ if .IsLookupAddrEnabled }}
|
||||||
"hostname": "{{ .Hostname }}",{{ end }}
|
"hostname": "{{ .Hostname }}",{{ end }}
|
||||||
"ip": "{{ .IP }}",
|
"ip": "{{ .IP }}",
|
||||||
"ip_decimal": {{ .IPDecimal }}
|
"ip_decimal": {{ .IPDecimal }}
|
||||||
@ -100,6 +105,13 @@ $ http {{ .Host }}/port/8080
|
|||||||
}</pre>
|
}</pre>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
</div>
|
</div>
|
||||||
|
{{ if .IsLookupCountryEnabled }}{{ if ne .Country "Unknown"}}{{ if .IsLookupCityEnabled }}{{ if ne .City "Unknown"}}
|
||||||
|
<div class="pure-u-1 pure-u-md-1-1">
|
||||||
|
<h2>Map</h2>
|
||||||
|
<p><img src="https://maps.googleapis.com/maps/api/staticmap?size=600x200&scale=2&markers=color%3Aorange%7Clabel%3AS%7c{{ .City }},{{ .Country }}" width="600" height="200"/>
|
||||||
|
</p>
|
||||||
|
{{ end }}{{ end }}{{ end }}{{ end }}
|
||||||
|
</div>
|
||||||
<div class="pure-u-1 pure-u-md-1-1">
|
<div class="pure-u-1 pure-u-md-1-1">
|
||||||
<h2>FAQ</h2>
|
<h2>FAQ</h2>
|
||||||
<h3>How do I force IPv4 or IPv6 lookup?</h3>
|
<h3>How do I force IPv4 or IPv6 lookup?</h3>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user