pax_global_header00006660000000000000000000000064136005245460014517gustar00rootroot0000000000000052 comment=ae8b169eb05b73c205edf569a6e4b0dc42c139fb geoip2-golang-1.4.0/000077500000000000000000000000001360052454600141535ustar00rootroot00000000000000geoip2-golang-1.4.0/.gitignore000066400000000000000000000000251360052454600161400ustar00rootroot00000000000000.vscode *.out *.test geoip2-golang-1.4.0/.gitmodules000066400000000000000000000001331360052454600163250ustar00rootroot00000000000000[submodule "test-data"] path = test-data url = https://github.com/maxmind/MaxMind-DB.git geoip2-golang-1.4.0/.golangci.toml000066400000000000000000000006651360052454600167200ustar00rootroot00000000000000[run] deadline = "10m" tests = true [linters] disable-all = true enable = [ "deadcode", "depguard", "errcheck", "goconst", "gocyclo", "gocritic", "gofmt", "golint", "gosec", "gosimple", "ineffassign", "maligned", "misspell", "nakedret", "staticcheck", "structcheck", "typecheck", "unconvert", "unparam", "varcheck", "vet", "vetshadow", ] geoip2-golang-1.4.0/.travis.yml000066400000000000000000000015501360052454600162650ustar00rootroot00000000000000language: go go: - 1.9.x - 1.10.x - 1.11.x - 1.12.x - 1.13.x - tip os: - linux - linux-ppc64le - osx - windows matrix: allow_failures: - go: tip install: - go get -v -t ./... before_script: - | if [[ $TRAVIS_GO_VERSION == '1.13.x' && $TRAVIS_OS_NAME == 'linux' && $(arch) != 'ppc64le' ]]; then curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin fi script: - | if [ $(arch) == "ppc64le" ]; then go test -cpu 1,4 -v else go test -race -cpu 1,4 -v fi - | if [ $(arch) == "ppc64le" ]; then go test -v -tags appengine else go test -race -v -tags appengine fi - | if [[ $TRAVIS_GO_VERSION == '1.13.x' && $TRAVIS_OS_NAME == 'linux' && $(arch) != 'ppc64le' ]]; then golangci-lint run fi sudo: false geoip2-golang-1.4.0/LICENSE000066400000000000000000000014041360052454600151570ustar00rootroot00000000000000ISC License Copyright (c) 2015, Gregory J. Oschwald Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. geoip2-golang-1.4.0/README.md000066400000000000000000000047561360052454600154460ustar00rootroot00000000000000# GeoIP2 Reader for Go # [![Build Status](https://travis-ci.org/oschwald/geoip2-golang.png?branch=master)](https://travis-ci.org/oschwald/geoip2-golang) [![GoDoc](https://godoc.org/github.com/oschwald/geoip2-golang?status.png)](https://godoc.org/github.com/oschwald/geoip2-golang) This library reads MaxMind [GeoLite2](http://dev.maxmind.com/geoip/geoip2/geolite2/) and [GeoIP2](http://www.maxmind.com/en/geolocation_landing) databases. This library is built using [the Go maxminddb reader](https://github.com/oschwald/maxminddb-golang). All data for the database record is decoded using this library. If you only need several fields, you may get superior performance by using maxminddb's `Lookup` directly with a result struct that only contains the required fields. (See [example_test.go](https://github.com/oschwald/maxminddb-golang/blob/master/example_test.go) in the maxminddb repository for an example of this.) ## Installation ## ``` go get github.com/oschwald/geoip2-golang ``` ## Usage ## [See GoDoc](http://godoc.org/github.com/oschwald/geoip2-golang) for documentation and examples. ## Example ## ```go package main import ( "fmt" "github.com/oschwald/geoip2-golang" "log" "net" ) func main() { db, err := geoip2.Open("GeoIP2-City.mmdb") if err != nil { log.Fatal(err) } defer db.Close() // If you are using strings that may be invalid, check that ip is not nil ip := net.ParseIP("81.2.69.142") record, err := db.City(ip) if err != nil { log.Fatal(err) } fmt.Printf("Portuguese (BR) city name: %v\n", record.City.Names["pt-BR"]) if len(record.Subdivisions) > 0 { fmt.Printf("English subdivision name: %v\n", record.Subdivisions[0].Names["en"]) } fmt.Printf("Russian country name: %v\n", record.Country.Names["ru"]) fmt.Printf("ISO country code: %v\n", record.Country.IsoCode) fmt.Printf("Time zone: %v\n", record.Location.TimeZone) fmt.Printf("Coordinates: %v, %v\n", record.Location.Latitude, record.Location.Longitude) // Output: // Portuguese (BR) city name: Londres // English subdivision name: England // Russian country name: Великобритания // ISO country code: GB // Time zone: Europe/London // Coordinates: 51.5142, -0.0931 } ``` ## Testing ## Make sure you checked out test data submodule: ``` git submodule init git submodule update ``` Execute test suite: ``` go test ``` ## Contributing ## Contributions welcome! Please fork the repository and open a pull request with your changes. ## License ## This is free software, licensed under the ISC license. geoip2-golang-1.4.0/example_test.go000066400000000000000000000021771360052454600172030ustar00rootroot00000000000000package geoip2 import ( "fmt" "log" "net" ) // Example provides a basic example of using the API. Use of the Country // method is analogous to that of the City method. func Example() { db, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb") if err != nil { log.Fatal(err) } defer db.Close() // If you are using strings that may be invalid, check that ip is not nil ip := net.ParseIP("81.2.69.142") record, err := db.City(ip) if err != nil { log.Fatal(err) } fmt.Printf("Portuguese (BR) city name: %v\n", record.City.Names["pt-BR"]) fmt.Printf("English subdivision name: %v\n", record.Subdivisions[0].Names["en"]) fmt.Printf("Russian country name: %v\n", record.Country.Names["ru"]) fmt.Printf("ISO country code: %v\n", record.Country.IsoCode) fmt.Printf("Time zone: %v\n", record.Location.TimeZone) fmt.Printf("Coordinates: %v, %v\n", record.Location.Latitude, record.Location.Longitude) // Output: // Portuguese (BR) city name: Londres // English subdivision name: England // Russian country name: Великобритания // ISO country code: GB // Time zone: Europe/London // Coordinates: 51.5142, -0.0931 } geoip2-golang-1.4.0/go.mod000066400000000000000000000002171360052454600152610ustar00rootroot00000000000000module github.com/oschwald/geoip2-golang go 1.9 require ( github.com/oschwald/maxminddb-golang v1.6.0 github.com/stretchr/testify v1.4.0 ) geoip2-golang-1.4.0/go.sum000066400000000000000000000025261360052454600153130ustar00rootroot00000000000000github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/oschwald/maxminddb-golang v1.6.0 h1:KAJSjdHQ8Kv45nFIbtoLGrGWqHFajOIm7skTyz/+Dls= github.com/oschwald/maxminddb-golang v1.6.0/go.mod h1:DUJFucBg2cvqx42YmDa/+xHvb0elJtOm3o4aFQ/nb/w= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= golang.org/x/sys v0.0.0-20191224085550-c709ea063b76 h1:Dho5nD6R3PcW2SH1or8vS0dszDaXRxIw55lBX7XiE5g= golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/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 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= geoip2-golang-1.4.0/reader.go000066400000000000000000000352111360052454600157460ustar00rootroot00000000000000// Package geoip2 provides an easy-to-use API for the MaxMind GeoIP2 and // GeoLite2 databases; this package does not support GeoIP Legacy databases. // // The structs provided by this package match the internal structure of // the data in the MaxMind databases. // // See github.com/oschwald/maxminddb-golang for more advanced used cases. package geoip2 import ( "fmt" "net" "github.com/oschwald/maxminddb-golang" ) // The Enterprise struct corresponds to the data in the GeoIP2 Enterprise // database. type Enterprise struct { City struct { Confidence uint8 `maxminddb:"confidence"` GeoNameID uint `maxminddb:"geoname_id"` Names map[string]string `maxminddb:"names"` } `maxminddb:"city"` Continent struct { Code string `maxminddb:"code"` GeoNameID uint `maxminddb:"geoname_id"` Names map[string]string `maxminddb:"names"` } `maxminddb:"continent"` Country struct { GeoNameID uint `maxminddb:"geoname_id"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` Confidence uint8 `maxminddb:"confidence"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` } `maxminddb:"country"` Location struct { AccuracyRadius uint16 `maxminddb:"accuracy_radius"` Latitude float64 `maxminddb:"latitude"` Longitude float64 `maxminddb:"longitude"` MetroCode uint `maxminddb:"metro_code"` TimeZone string `maxminddb:"time_zone"` } `maxminddb:"location"` Postal struct { Code string `maxminddb:"code"` Confidence uint8 `maxminddb:"confidence"` } `maxminddb:"postal"` RegisteredCountry struct { GeoNameID uint `maxminddb:"geoname_id"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` Confidence uint8 `maxminddb:"confidence"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` } `maxminddb:"registered_country"` RepresentedCountry struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` Type string `maxminddb:"type"` } `maxminddb:"represented_country"` Subdivisions []struct { Confidence uint8 `maxminddb:"confidence"` GeoNameID uint `maxminddb:"geoname_id"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` } `maxminddb:"subdivisions"` Traits struct { AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"` AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"` ConnectionType string `maxminddb:"connection_type"` Domain string `maxminddb:"domain"` IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"` IsLegitimateProxy bool `maxminddb:"is_legitimate_proxy"` IsSatelliteProvider bool `maxminddb:"is_satellite_provider"` ISP string `maxminddb:"isp"` Organization string `maxminddb:"organization"` UserType string `maxminddb:"user_type"` } `maxminddb:"traits"` } // The City struct corresponds to the data in the GeoIP2/GeoLite2 City // databases. type City struct { City struct { GeoNameID uint `maxminddb:"geoname_id"` Names map[string]string `maxminddb:"names"` } `maxminddb:"city"` Continent struct { Code string `maxminddb:"code"` GeoNameID uint `maxminddb:"geoname_id"` Names map[string]string `maxminddb:"names"` } `maxminddb:"continent"` Country struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` } `maxminddb:"country"` Location struct { AccuracyRadius uint16 `maxminddb:"accuracy_radius"` Latitude float64 `maxminddb:"latitude"` Longitude float64 `maxminddb:"longitude"` MetroCode uint `maxminddb:"metro_code"` TimeZone string `maxminddb:"time_zone"` } `maxminddb:"location"` Postal struct { Code string `maxminddb:"code"` } `maxminddb:"postal"` RegisteredCountry struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` } `maxminddb:"registered_country"` RepresentedCountry struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` Type string `maxminddb:"type"` } `maxminddb:"represented_country"` Subdivisions []struct { GeoNameID uint `maxminddb:"geoname_id"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` } `maxminddb:"subdivisions"` Traits struct { IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"` IsSatelliteProvider bool `maxminddb:"is_satellite_provider"` } `maxminddb:"traits"` } // The Country struct corresponds to the data in the GeoIP2/GeoLite2 // Country databases. type Country struct { Continent struct { Code string `maxminddb:"code"` GeoNameID uint `maxminddb:"geoname_id"` Names map[string]string `maxminddb:"names"` } `maxminddb:"continent"` Country struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` } `maxminddb:"country"` RegisteredCountry struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` } `maxminddb:"registered_country"` RepresentedCountry struct { GeoNameID uint `maxminddb:"geoname_id"` IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` IsoCode string `maxminddb:"iso_code"` Names map[string]string `maxminddb:"names"` Type string `maxminddb:"type"` } `maxminddb:"represented_country"` Traits struct { IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"` IsSatelliteProvider bool `maxminddb:"is_satellite_provider"` } `maxminddb:"traits"` } // The AnonymousIP struct corresponds to the data in the GeoIP2 // Anonymous IP database. type AnonymousIP struct { IsAnonymous bool `maxminddb:"is_anonymous"` IsAnonymousVPN bool `maxminddb:"is_anonymous_vpn"` IsHostingProvider bool `maxminddb:"is_hosting_provider"` IsPublicProxy bool `maxminddb:"is_public_proxy"` IsTorExitNode bool `maxminddb:"is_tor_exit_node"` } // The ASN struct corresponds to the data in the GeoLite2 ASN database. type ASN struct { AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"` AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"` } // The ConnectionType struct corresponds to the data in the GeoIP2 // Connection-Type database. type ConnectionType struct { ConnectionType string `maxminddb:"connection_type"` } // The Domain struct corresponds to the data in the GeoIP2 Domain database. type Domain struct { Domain string `maxminddb:"domain"` } // The ISP struct corresponds to the data in the GeoIP2 ISP database. type ISP struct { AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"` AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"` ISP string `maxminddb:"isp"` Organization string `maxminddb:"organization"` } type databaseType int const ( isAnonymousIP = 1 << iota isASN isCity isConnectionType isCountry isDomain isEnterprise isISP ) // Reader holds the maxminddb.Reader struct. It can be created using the // Open and FromBytes functions. type Reader struct { mmdbReader *maxminddb.Reader databaseType databaseType } // InvalidMethodError is returned when a lookup method is called on a // database that it does not support. For instance, calling the ISP method // on a City database. type InvalidMethodError struct { Method string DatabaseType string } func (e InvalidMethodError) Error() string { return fmt.Sprintf(`geoip2: the %s method does not support the %s database`, e.Method, e.DatabaseType) } // UnknownDatabaseTypeError is returned when an unknown database type is // opened. type UnknownDatabaseTypeError struct { DatabaseType string } func (e UnknownDatabaseTypeError) Error() string { return fmt.Sprintf(`geoip2: reader does not support the "%s" database type`, e.DatabaseType) } // Open takes a string path to a file and returns a Reader struct or an error. // The database file is opened using a memory map. Use the Close method on the // Reader object to return the resources to the system. func Open(file string) (*Reader, error) { reader, err := maxminddb.Open(file) if err != nil { return nil, err } dbType, err := getDBType(reader) return &Reader{reader, dbType}, err } // FromBytes takes a byte slice corresponding to a GeoIP2/GeoLite2 database // file and returns a Reader struct or an error. Note that the byte slice is // use directly; any modification of it after opening the database will result // in errors while reading from the database. func FromBytes(bytes []byte) (*Reader, error) { reader, err := maxminddb.FromBytes(bytes) if err != nil { return nil, err } dbType, err := getDBType(reader) return &Reader{reader, dbType}, err } func getDBType(reader *maxminddb.Reader) (databaseType, error) { switch reader.Metadata.DatabaseType { case "GeoIP2-Anonymous-IP": return isAnonymousIP, nil case "GeoLite2-ASN": return isASN, nil // We allow City lookups on Country for back compat case "DBIP-City-Lite", "DBIP-City", "DBIP-Country-Lite", "DBIP-Country", "GeoLite2-City", "GeoIP2-City", "GeoIP2-City-Africa", "GeoIP2-City-Asia-Pacific", "GeoIP2-City-Europe", "GeoIP2-City-North-America", "GeoIP2-City-South-America", "GeoIP2-Precision-City", "GeoLite2-Country", "GeoIP2-Country": return isCity | isCountry, nil case "GeoIP2-Connection-Type": return isConnectionType, nil case "GeoIP2-Domain": return isDomain, nil case "DBIP-Location-ISP (compat=Enterprise)", "GeoIP2-Enterprise": return isEnterprise | isCity | isCountry, nil case "GeoIP2-ISP", "GeoIP2-Precision-ISP": return isISP | isASN, nil default: return 0, UnknownDatabaseTypeError{reader.Metadata.DatabaseType} } } // Enterprise takes an IP address as a net.IP struct and returns an Enterprise // struct and/or an error. This is intended to be used with the GeoIP2 // Enterprise database. func (r *Reader) Enterprise(ipAddress net.IP) (*Enterprise, error) { if isEnterprise&r.databaseType == 0 { return nil, InvalidMethodError{"Enterprise", r.Metadata().DatabaseType} } var enterprise Enterprise err := r.mmdbReader.Lookup(ipAddress, &enterprise) return &enterprise, err } // City takes an IP address as a net.IP struct and returns a City struct // and/or an error. Although this can be used with other databases, this // method generally should be used with the GeoIP2 or GeoLite2 City databases. func (r *Reader) City(ipAddress net.IP) (*City, error) { if isCity&r.databaseType == 0 { return nil, InvalidMethodError{"City", r.Metadata().DatabaseType} } var city City err := r.mmdbReader.Lookup(ipAddress, &city) return &city, err } // Country takes an IP address as a net.IP struct and returns a Country struct // and/or an error. Although this can be used with other databases, this // method generally should be used with the GeoIP2 or GeoLite2 Country // databases. func (r *Reader) Country(ipAddress net.IP) (*Country, error) { if isCountry&r.databaseType == 0 { return nil, InvalidMethodError{"Country", r.Metadata().DatabaseType} } var country Country err := r.mmdbReader.Lookup(ipAddress, &country) return &country, err } // AnonymousIP takes an IP address as a net.IP struct and returns a // AnonymousIP struct and/or an error. func (r *Reader) AnonymousIP(ipAddress net.IP) (*AnonymousIP, error) { if isAnonymousIP&r.databaseType == 0 { return nil, InvalidMethodError{"AnonymousIP", r.Metadata().DatabaseType} } var anonIP AnonymousIP err := r.mmdbReader.Lookup(ipAddress, &anonIP) return &anonIP, err } // ASN takes an IP address as a net.IP struct and returns a ASN struct and/or // an error func (r *Reader) ASN(ipAddress net.IP) (*ASN, error) { if isASN&r.databaseType == 0 { return nil, InvalidMethodError{"ASN", r.Metadata().DatabaseType} } var val ASN err := r.mmdbReader.Lookup(ipAddress, &val) return &val, err } // ConnectionType takes an IP address as a net.IP struct and returns a // ConnectionType struct and/or an error func (r *Reader) ConnectionType(ipAddress net.IP) (*ConnectionType, error) { if isConnectionType&r.databaseType == 0 { return nil, InvalidMethodError{"ConnectionType", r.Metadata().DatabaseType} } var val ConnectionType err := r.mmdbReader.Lookup(ipAddress, &val) return &val, err } // Domain takes an IP address as a net.IP struct and returns a // Domain struct and/or an error func (r *Reader) Domain(ipAddress net.IP) (*Domain, error) { if isDomain&r.databaseType == 0 { return nil, InvalidMethodError{"Domain", r.Metadata().DatabaseType} } var val Domain err := r.mmdbReader.Lookup(ipAddress, &val) return &val, err } // ISP takes an IP address as a net.IP struct and returns a ISP struct and/or // an error func (r *Reader) ISP(ipAddress net.IP) (*ISP, error) { if isISP&r.databaseType == 0 { return nil, InvalidMethodError{"ISP", r.Metadata().DatabaseType} } var val ISP err := r.mmdbReader.Lookup(ipAddress, &val) return &val, err } // Metadata takes no arguments and returns a struct containing metadata about // the MaxMind database in use by the Reader. func (r *Reader) Metadata() maxminddb.Metadata { return r.mmdbReader.Metadata } // Close unmaps the database file from virtual memory and returns the // resources to the system. func (r *Reader) Close() error { return r.mmdbReader.Close() } geoip2-golang-1.4.0/reader_test.go000066400000000000000000000151631360052454600170110ustar00rootroot00000000000000package geoip2 import ( "math/rand" "net" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestReader(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.City(net.ParseIP("81.2.69.160")) assert.Nil(t, err) m := reader.Metadata() assert.Equal(t, uint(2), m.BinaryFormatMajorVersion) assert.Equal(t, uint(0), m.BinaryFormatMinorVersion) assert.NotZero(t, m.BuildEpoch) assert.Equal(t, "GeoIP2-City", m.DatabaseType) assert.Equal(t, map[string]string{ "en": "GeoIP2 City Test Database (fake GeoIP2 data, for example purposes only)", "zh": "小型数据库", }, m.Description, ) assert.Equal(t, uint(6), m.IPVersion) assert.Equal(t, []string{"en", "zh"}, m.Languages) assert.NotZero(t, m.NodeCount) assert.Equal(t, uint(28), m.RecordSize) assert.Equal(t, uint(2643743), record.City.GeoNameID) assert.Equal(t, map[string]string{ "de": "London", "en": "London", "es": "Londres", "fr": "Londres", "ja": "ロンドン", "pt-BR": "Londres", "ru": "Лондон", }, record.City.Names, ) assert.Equal(t, uint(6255148), record.Continent.GeoNameID) assert.Equal(t, "EU", record.Continent.Code) assert.Equal(t, map[string]string{ "de": "Europa", "en": "Europe", "es": "Europa", "fr": "Europe", "ja": "ヨーロッパ", "pt-BR": "Europa", "ru": "Европа", "zh-CN": "欧洲", }, record.Continent.Names, ) assert.Equal(t, uint(2635167), record.Country.GeoNameID) assert.True(t, record.Country.IsInEuropeanUnion) assert.Equal(t, "GB", record.Country.IsoCode) assert.Equal(t, map[string]string{ "de": "Vereinigtes Königreich", "en": "United Kingdom", "es": "Reino Unido", "fr": "Royaume-Uni", "ja": "イギリス", "pt-BR": "Reino Unido", "ru": "Великобритания", "zh-CN": "英国", }, record.Country.Names, ) assert.Equal(t, uint16(100), record.Location.AccuracyRadius) assert.Equal(t, 51.5142, record.Location.Latitude) assert.Equal(t, -0.0931, record.Location.Longitude) assert.Equal(t, "Europe/London", record.Location.TimeZone) assert.Equal(t, uint(6269131), record.Subdivisions[0].GeoNameID) assert.Equal(t, "ENG", record.Subdivisions[0].IsoCode) assert.Equal(t, map[string]string{ "en": "England", "pt-BR": "Inglaterra", "fr": "Angleterre", "es": "Inglaterra", }, record.Subdivisions[0].Names, ) assert.Equal(t, uint(6252001), record.RegisteredCountry.GeoNameID) assert.False(t, record.RegisteredCountry.IsInEuropeanUnion) assert.Equal(t, "US", record.RegisteredCountry.IsoCode) assert.Equal(t, map[string]string{ "de": "USA", "en": "United States", "es": "Estados Unidos", "fr": "États-Unis", "ja": "アメリカ合衆国", "pt-BR": "Estados Unidos", "ru": "США", "zh-CN": "美国", }, record.RegisteredCountry.Names, ) assert.False(t, record.RepresentedCountry.IsInEuropeanUnion) } func TestMetroCode(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-City-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.City(net.ParseIP("216.160.83.56")) assert.Nil(t, err) assert.Equal(t, uint(819), record.Location.MetroCode) } func TestAnonymousIP(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-Anonymous-IP-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.AnonymousIP(net.ParseIP("1.2.0.0")) assert.Nil(t, err) assert.Equal(t, true, record.IsAnonymous) assert.Equal(t, true, record.IsAnonymousVPN) assert.Equal(t, false, record.IsHostingProvider) assert.Equal(t, false, record.IsPublicProxy) assert.Equal(t, false, record.IsTorExitNode) } func TestASN(t *testing.T) { reader, err := Open("test-data/test-data/GeoLite2-ASN-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.ASN(net.ParseIP("1.128.0.0")) assert.Nil(t, err) assert.Equal(t, uint(1221), record.AutonomousSystemNumber) assert.Equal(t, "Telstra Pty Ltd", record.AutonomousSystemOrganization) } func TestConnectionType(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-Connection-Type-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.ConnectionType(net.ParseIP("1.0.1.0")) assert.Nil(t, err) assert.Equal(t, "Cable/DSL", record.ConnectionType) } func TestCountry(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-Country-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.Country(net.ParseIP("81.2.69.160")) assert.Nil(t, err) assert.True(t, record.Country.IsInEuropeanUnion) assert.False(t, record.RegisteredCountry.IsInEuropeanUnion) assert.False(t, record.RepresentedCountry.IsInEuropeanUnion) } func TestDomain(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-Domain-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.Domain(net.ParseIP("1.2.0.0")) assert.Nil(t, err) assert.Equal(t, "maxmind.com", record.Domain) } func TestEnterprise(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-Enterprise-Test.mmdb") require.Nil(t, err) defer reader.Close() record, err := reader.Enterprise(net.ParseIP("74.209.24.0")) require.Nil(t, err) assert.Equal(t, uint8(11), record.City.Confidence) assert.Equal(t, uint(14671), record.Traits.AutonomousSystemNumber) assert.Equal(t, "FairPoint Communications", record.Traits.AutonomousSystemOrganization) assert.Equal(t, "Cable/DSL", record.Traits.ConnectionType) assert.Equal(t, "frpt.net", record.Traits.Domain) } func TestISP(t *testing.T) { reader, err := Open("test-data/test-data/GeoIP2-ISP-Test.mmdb") assert.Nil(t, err) defer reader.Close() record, err := reader.ISP(net.ParseIP("1.128.0.0")) assert.Nil(t, err) assert.Equal(t, uint(1221), record.AutonomousSystemNumber) assert.Equal(t, "Telstra Pty Ltd", record.AutonomousSystemOrganization) assert.Equal(t, "Telstra Internet", record.ISP) assert.Equal(t, "Telstra Internet", record.Organization) } // This ensures the compiler does not optimize away the function call var cityResult *City func BenchmarkMaxMindDB(b *testing.B) { db, err := Open("GeoLite2-City.mmdb") if err != nil { b.Fatal(err) } defer db.Close() r := rand.New(rand.NewSource(0)) var city *City for i := 0; i < b.N; i++ { ip := randomIPv4Address(r) city, err = db.City(ip) if err != nil { b.Fatal(err) } } cityResult = city } func randomIPv4Address(r *rand.Rand) net.IP { num := r.Uint32() return []byte{byte(num >> 24), byte(num >> 16), byte(num >> 8), byte(num)} } geoip2-golang-1.4.0/test-data/000077500000000000000000000000001360052454600160415ustar00rootroot00000000000000