├── AUTHORS ├── CONTRIBUTORS ├── TODO ├── go.mod ├── systemd └── telize.service ├── go.sum ├── payload.go ├── LICENSE ├── structs.go ├── utils.go ├── telize.go ├── endpoints.go ├── ChangeLog ├── README.md └── country-code3.go /AUTHORS: -------------------------------------------------------------------------------- 1 | Telize is developed by: 2 | 3 | Frederic Cambus 4 | 5 | Site: https://www.cambus.net 6 | -------------------------------------------------------------------------------- /CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | The following people have contributed to Telize: 2 | 3 | - Jon Nalley 4 | - Yann Verry 5 | - Ludovic Robinot 6 | - Joris Vink 7 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | - Investigate doing city and asn lookups in a single goroutine 2 | - Investigate zero downtime reloads of the DBs. Use fsnotify in a goroutine? 3 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module telize 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.23.7 6 | 7 | require ( 8 | github.com/go-chi/chi/v5 v5.2.2 9 | github.com/oschwald/maxminddb-golang v1.13.1 10 | ) 11 | 12 | require golang.org/x/sys v0.21.0 // indirect 13 | -------------------------------------------------------------------------------- /systemd/telize.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=High performance IP Geolocation API 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=telize 8 | Restart=on-failure 9 | DynamicUser=yes 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/go-chi/chi/v5 v5.2.2 h1:CMwsvRVTbXVytCk1Wd72Zy1LAsAh9GxMmSNWLHCG618= 2 | github.com/go-chi/chi/v5 v5.2.2/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= 3 | github.com/oschwald/maxminddb-golang v1.13.1 h1:G3wwjdN9JmIK2o/ermkHM+98oX5fS+k5MbwsmL4MRQE= 4 | github.com/oschwald/maxminddb-golang v1.13.1/go.mod h1:K4pgV9N/GcK694KSTmVSDTODk4IsCNThNdTmnaBZ/F8= 5 | golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= 6 | golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 7 | -------------------------------------------------------------------------------- /payload.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Telize 4.0.0 3 | * Copyright (c) 2013-2025, Frederic Cambus 4 | * https://www.telize.com 5 | * 6 | * Created: 2013-08-15 7 | * Last Updated: 2022-06-23 8 | * 9 | * Telize is released under the BSD 2-Clause license. 10 | * See LICENSE file for details. 11 | * 12 | * SPDX-License-Identifier: BSD-2-Clause 13 | */ 14 | 15 | package main 16 | 17 | type payload struct { 18 | IP string `json:"ip"` 19 | Continent string `json:"continent_code,omitempty"` 20 | Country string `json:"country,omitempty"` 21 | CountryCode string `json:"country_code,omitempty"` 22 | CountryCode3 string `json:"country_code3,omitempty"` 23 | IsInEuropeanUnion bool `json:"is_in_european_union,omitempty"` 24 | Region string `json:"region,omitempty"` 25 | RegionCode string `json:"region_code,omitempty"` 26 | City string `json:"city,omitempty"` 27 | PostalCode string `json:"postal_code,omitempty"` 28 | Latitude float64 `json:"latitude,omitempty"` 29 | Longitude float64 `json:"longitude,omitempty"` 30 | TimeZone string `json:"timezone,omitempty"` 31 | Offset *int `json:"offset,omitempty"` 32 | ASN uint `json:"asn,omitempty"` 33 | Organization string `json:"organization,omitempty"` 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013-2025, Frederic Cambus 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 18 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /structs.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Telize 4.0.0 3 | * Copyright (c) 2013-2025, Frederic Cambus 4 | * https://www.telize.com 5 | * 6 | * Created: 2013-08-15 7 | * Last Updated: 2022-06-23 8 | * 9 | * Telize is released under the BSD 2-Clause license. 10 | * See LICENSE file for details. 11 | * 12 | * SPDX-License-Identifier: BSD-2-Clause 13 | */ 14 | 15 | package main 16 | 17 | type ASN struct { 18 | AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"` 19 | AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"` 20 | } 21 | 22 | type City struct { 23 | Continent struct { 24 | Code string `maxminddb:"code"` 25 | Names map[string]string `maxminddb:"names"` 26 | } `maxminddb:"continent"` 27 | Country struct { 28 | IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` 29 | IsoCode string `maxminddb:"iso_code"` 30 | Names map[string]string `maxminddb:"names"` 31 | } `maxminddb:"country"` 32 | Subdivisions []struct { 33 | IsoCode string `maxminddb:"iso_code"` 34 | Names map[string]string `maxminddb:"names"` 35 | } `maxminddb:"subdivisions"` 36 | City struct { 37 | Names map[string]string `maxminddb:"names"` 38 | } `maxminddb:"city"` 39 | Postal struct { 40 | Code string `maxminddb:"code"` 41 | } `maxminddb:"postal"` 42 | Location struct { 43 | Latitude float64 `maxminddb:"latitude"` 44 | Longitude float64 `maxminddb:"longitude"` 45 | TimeZone string `maxminddb:"time_zone"` 46 | } `maxminddb:"location"` 47 | } 48 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Telize 4.0.0 3 | * Copyright (c) 2013-2025, Frederic Cambus 4 | * https://www.telize.com 5 | * 6 | * Created: 2013-08-15 7 | * Last Updated: 2022-11-24 8 | * 9 | * Telize is released under the BSD 2-Clause license. 10 | * See LICENSE file for details. 11 | * 12 | * SPDX-License-Identifier: BSD-2-Clause 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "encoding/json" 19 | "io" 20 | "net" 21 | "net/http" 22 | "strings" 23 | ) 24 | 25 | // Return an HTTP Error along with a JSON-encoded error message 26 | func errorCode(w http.ResponseWriter, status int, code int, message string) { 27 | type Error struct { 28 | Code int `json:"code"` 29 | Message string `json:"message"` 30 | } 31 | 32 | w.Header().Set("Cache-Control", "no-cache") 33 | w.Header().Set("Content-Type", "application/json") 34 | 35 | if output, err := json.Marshal(Error{Code: code, Message: message}); err == nil { 36 | w.WriteHeader(status) 37 | io.WriteString(w, string(output)) 38 | } 39 | } 40 | 41 | func request_ip(r *http.Request) string { 42 | var ip string 43 | 44 | if xff := r.Header.Get("X-Forwarded-For"); xff != "" { 45 | ips := strings.Split(xff, ",") 46 | ip = ips[0] 47 | } 48 | 49 | if ip == "" { 50 | ip, _, _ = net.SplitHostPort(r.RemoteAddr) 51 | } 52 | 53 | return ip 54 | } 55 | 56 | // Generate JSON output 57 | func jsonify(w http.ResponseWriter, r *http.Request, payload *payload) { 58 | callback := r.URL.Query().Get("callback") 59 | 60 | w.Header().Set("Cache-Control", "no-cache") 61 | w.Header().Set("Content-Type", "application/json") 62 | w.Header().Set("Access-Control-Allow-Origin", "*") 63 | 64 | if json, err := json.Marshal(payload); err == nil { 65 | if callback != "" { 66 | io.WriteString(w, callback+"("+string(json)+");") 67 | } else { 68 | io.WriteString(w, string(json)) 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /telize.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Telize 4.0.0 3 | * Copyright (c) 2013-2025, Frederic Cambus 4 | * https://www.telize.com 5 | * 6 | * Created: 2013-08-15 7 | * Last Updated: 2023-11-28 8 | * 9 | * Telize is released under the BSD 2-Clause license. 10 | * See LICENSE file for details. 11 | * 12 | * SPDX-License-Identifier: BSD-2-Clause 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "flag" 19 | "fmt" 20 | "github.com/go-chi/chi/v5" 21 | "github.com/oschwald/maxminddb-golang" 22 | "log" 23 | "net/http" 24 | "os" 25 | ) 26 | 27 | var asn *maxminddb.Reader 28 | var city *maxminddb.Reader 29 | 30 | func main() { 31 | var err error 32 | 33 | host := flag.String("host", "127.0.0.1", "Set the server host") 34 | port := flag.String("port", "8080", "Set the server port") 35 | version := flag.Bool("version", false, "Display version") 36 | 37 | flag.Usage = func() { 38 | fmt.Println("\nUSAGE:") 39 | flag.PrintDefaults() 40 | } 41 | flag.Parse() 42 | 43 | if *version { 44 | fmt.Println("Telize 4.0.0") 45 | os.Exit(0) 46 | } 47 | 48 | asn, err = maxminddb.Open("/var/db/GeoIP/GeoLite2-ASN.mmdb") 49 | if err != nil { 50 | log.Fatal(err) 51 | } 52 | defer asn.Close() 53 | 54 | city, err = maxminddb.Open("/var/db/GeoIP/GeoLite2-City.mmdb") 55 | if err != nil { 56 | log.Fatal(err) 57 | } 58 | defer city.Close() 59 | 60 | address := *host + ":" + *port 61 | 62 | r := chi.NewRouter() 63 | r.Get("/ip", ip) 64 | r.Get("/jsonip", jsonip) 65 | r.Get("/geoip", location) 66 | r.Get("/geoip/", location) 67 | r.Get("/geoip/{ip}", location) 68 | r.Get("/location", location) 69 | r.Get("/location/", location) 70 | r.Get("/location/{ip}", location) 71 | 72 | r.Head("/ip", ip) 73 | r.Head("/jsonip", jsonip) 74 | r.Head("/geoip", location) 75 | r.Head("/geoip/", location) 76 | r.Head("/geoip/{ip}", location) 77 | r.Head("/location", location) 78 | r.Head("/location/", location) 79 | r.Head("/location/{ip}", location) 80 | 81 | fmt.Print("Listening on: http://", address+"\n") 82 | log.Fatal(http.ListenAndServe(address, r)) 83 | } 84 | -------------------------------------------------------------------------------- /endpoints.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Telize 4.0.0 3 | * Copyright (c) 2013-2025, Frederic Cambus 4 | * https://www.telize.com 5 | * 6 | * Created: 2013-08-15 7 | * Last Updated: 2022-11-24 8 | * 9 | * Telize is released under the BSD 2-Clause license. 10 | * See LICENSE file for details. 11 | * 12 | * SPDX-License-Identifier: BSD-2-Clause 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "github.com/go-chi/chi/v5" 19 | "io" 20 | "net" 21 | "net/http" 22 | "time" 23 | ) 24 | 25 | func ip(w http.ResponseWriter, r *http.Request) { 26 | ip := request_ip(r) 27 | 28 | w.Header().Set("Cache-Control", "no-cache") 29 | w.Header().Set("Content-Type", "text/plain") 30 | 31 | io.WriteString(w, ip) 32 | } 33 | 34 | func jsonip(w http.ResponseWriter, r *http.Request) { 35 | ip := request_ip(r) 36 | jsonip := payload{IP: ip} 37 | 38 | jsonify(w, r, &jsonip) 39 | } 40 | 41 | func location(w http.ResponseWriter, r *http.Request) { 42 | ip := chi.URLParam(r, "ip") 43 | 44 | if ip == "" { 45 | ip = request_ip(r) 46 | } 47 | 48 | address := net.ParseIP(ip) 49 | 50 | var asn_record ASN 51 | 52 | err := asn.Lookup(address, &asn_record) 53 | if err != nil { 54 | errorCode(w, 400, 401, "Input string is not a valid IP address") 55 | return 56 | } 57 | 58 | var record City 59 | 60 | err = city.Lookup(address, &record) 61 | if err != nil { 62 | errorCode(w, 400, 401, "Input string is not a valid IP address") 63 | return 64 | } 65 | 66 | location := payload{ 67 | IP: ip, 68 | Continent: record.Continent.Code, 69 | Country: record.Country.Names["en"], 70 | CountryCode: record.Country.IsoCode, 71 | CountryCode3: CountryCode3[record.Country.IsoCode], 72 | IsInEuropeanUnion: record.Country.IsInEuropeanUnion, 73 | City: record.City.Names["en"], 74 | PostalCode: record.Postal.Code, 75 | Latitude: record.Location.Latitude, 76 | Longitude: record.Location.Longitude, 77 | TimeZone: record.Location.TimeZone, 78 | ASN: asn_record.AutonomousSystemNumber, 79 | Organization: asn_record.AutonomousSystemOrganization, 80 | } 81 | 82 | if record.Subdivisions != nil { 83 | location.Region = record.Subdivisions[0].Names["en"] 84 | location.RegionCode = record.Subdivisions[0].IsoCode 85 | } 86 | 87 | if record.Location.TimeZone != "" { 88 | if tz, err := time.LoadLocation(record.Location.TimeZone); err == nil { 89 | _, offset := time.Now().In(tz).Zone() 90 | location.Offset = &offset 91 | } 92 | } 93 | 94 | jsonify(w, r, &location) 95 | } 96 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | Telize 3.1.1 (2022-04-27) 2 | 3 | - Define GEOIP2DB_CITY and GEOIP2DB_ASN macros to load MMDB databases 4 | - Account for Kore 4.2 changes in http_request structure 5 | - Account for Kore 4.2 changes in the routing configuration 6 | 7 | 8 | 9 | Telize 3.1.0 (2021-03-29) 10 | 11 | - Decrement COUNTRIES to account for "Netherlands Antilles" removal 12 | - Allow telize_getdata() to handle boolean values from MMDB databases 13 | - Add the 'is_in_european_union' field if it's present in the MMDB database 14 | 15 | 16 | 17 | Telize 3.0.1 (2021-01-01) 18 | 19 | - Add port number for endpoints examples, so they work with default settings 20 | - Add a 'Timezone offsets' section in the README 21 | - Remove entry for "Netherlands Antilles" in 'country_code' and 'country_code3' 22 | arrays 23 | - Add -Wextra and -pedantic to CFLAGS 24 | - Enable FORTIFY_SOURCE level 2 25 | - Check strndup() return value and error out if allocation fails 26 | 27 | 28 | 29 | Telize 3.0.0 (2020-09-07) 30 | 31 | - Telize has been rewritten in C using the Kore Web platform 32 | - Add a few entries in the 'country_code' to 'country_code3' map 33 | - Handle the 'X-Forwarded-For' HTTP header if present 34 | - When 'X-Forwarded-For' header is set, get the first IP of the list 35 | - Dynamically calculate timezone offsets and add data to the payload 36 | 37 | 38 | 39 | Telize 2.0.0 (2018-03-15) 40 | 41 | - Switch to using GeoIP2/GeoLite2 databases 42 | - The 'region_code' field is now in the ISO-3166-2 format for all countries 43 | - The 'organization' field now only contains organization name, Autonomous 44 | System Numbers are now provided as a separate 'asn' field in numeric value 45 | - Timezone offsets ('offset' field) are now generated as numeric values 46 | and in seconds 47 | - The 'area_code' and 'dma_code' are not provided anymore 48 | - Drop dependency on the Lua iconv module, GeoIP2/GeoLite2 databases are 49 | encoded as UTF-8 50 | - Drop timezone.conf, GeoIP2/GeoLite2 databases contain time zones for each 51 | location 52 | - Rename telize to telize.conf 53 | - Update timezones list 54 | - Add support for CORS in the 'jsonip' endpoint 55 | - Rename the 'geoip' endpoint to 'location' 56 | - Add Cache-Control header in the 'jsonip' endpoint as well 57 | 58 | 59 | 60 | Telize 1.07 (2016-11-22) 61 | 62 | - The timezone offset generator has been rewritten in Lua 63 | - Relicensed under the BSD 2-Clause license 64 | - Use Lua to set additional headers and drop dependency on the 65 | 'ngx_headers_more' module 66 | - Use Lua to echo IP address in the 'ip' endpoint and drop dependency on 67 | the 'ngx_echo' module 68 | - Use 'content_by_lua_block' directive instead of 'content_by_lua' 69 | - Various documentation updates 70 | 71 | 72 | 73 | Telize 1.06 (2016-02-04) 74 | 75 | - Prefixing all country codes with carets to prevent wrong matching 76 | 77 | 78 | 79 | Telize 1.05 (2016-01-05) 80 | 81 | - Regression fix: organization name was not correctly converted to UTF-8 82 | 83 | 84 | 85 | Telize 1.04 (2015-11-10) 86 | 87 | - Do not attempt to split GeoIP org field into ASN and ISP, return the raw 88 | organization string instead 89 | 90 | 91 | 92 | Telize 1.03 (2015-10-27) 93 | 94 | - Fix region and ISP name encoding (Thanks to Ludovic Robinot) 95 | - Removed legacy Debian automatic install script 96 | - Check for invalid IP addresses before attempting to validate arguments 97 | - Convert latitude and longitude to numeric values only after all arguments 98 | have been validated 99 | - The 'jsonip' endpoint do not use the internal 'jsonify' endpoint anymore 100 | - Various documentation updates 101 | - The 'localize' internal endpoint is not needed anymore, and Telize now 102 | requires Nginx 1.7.4+ 103 | - Splitting GeoIP organization string into ASN and ISP using Lua 104 | 105 | 106 | 107 | Telize 1.02 (2014-09-01) 108 | 109 | - Refactored Lua code (Thanks to Jon Nalley) 110 | - Adding support for Timezones offsets (Thanks to Yann Verry) 111 | - Default output charset is now UTF-8 (Thanks to Yann Verry) 112 | - Adding an automatic install script for Debian 113 | - Enable setting charsets for application/json MIME type 114 | - Adding Cache-Control headers (no-cache by default) 115 | - Enabling CORS by default 116 | 117 | 118 | 119 | Telize 1.01 (2013-10-11) 120 | 121 | - Adding support for Timezones 122 | - Adding support for GeoIP ASN database 123 | - Enforcing strictly defined URL endpoints 124 | - Prevent logging of internal redirects 125 | 126 | 127 | 128 | Telize 1.00 (2013-08-21) 129 | 130 | - Initial release 131 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | t e l i z e 3 | _______________________ 4 | ______\ /_______ 5 | \\ \\ ___ // / 6 | __ \ ____ \ __ / \ _____/\ / ____ 7 | ___/ \____/ _//____/ \___\___/___\__ /__/ _//____ 8 | \\__ ____ __/ __ __ ____ ____ __/ __/// 9 | / \_ |/ \_ / \/ /_/ |/ \_ 10 | \\\ ___/\___ /____/\_______/\ ___/\___ / 11 | <0(--- \__/ -h7- \______/ \ . \__/ ---- \______/ --(0> 12 | \ .\ /. . 13 | \ .\ // / 14 | \______\\ //______/ 15 | Y 16 | 17 | ## Description 18 | 19 | Telize is a REST API built in Go allowing to get a visitor IP address and 20 | to query location information from any IP address. It outputs JSON-encoded 21 | IP geolocation data, and supports both JSON and JSONP. 22 | 23 | Geolocation operations are performed using the MaxMind DB Reader for Go 24 | which caches the database in RAM. Therefore, Telize has very minimal 25 | overhead and should be blazing fast. 26 | 27 | ## Requirements 28 | 29 | Telize requires the following Go libraries: 30 | 31 | - chi: lightweight, idiomatic and composable router - https://github.com/go-chi/chi 32 | - maxminddb-golang: MaxMind DB Reader for Go - https://github.com/oschwald/maxminddb-golang 33 | 34 | ### GeoIP2 databases 35 | 36 | Telize requires the free [GeoLite2 databases][1] from MaxMind. 37 | 38 | Telize will look for the `GeoLite2 City` and `GeoLite2 ASN` databases in 39 | `/var/db/GeoIP` by default. 40 | 41 | ## Installation 42 | 43 | Build and install with the `go` tool, all dependencies will be automatically 44 | fetched and compiled: 45 | 46 | go build 47 | go install telize 48 | 49 | ## Usage 50 | 51 | By default, Telize will bind on localhost, port 8080. 52 | 53 | USAGE: 54 | -host string 55 | Set the server host (default "127.0.0.1") 56 | -port string 57 | Set the server port (default "8080") 58 | -version 59 | Display version 60 | 61 | ## Running Telize at boot time 62 | 63 | ### Systemd unit file 64 | 65 | Telize is bundled with a systemd unit file, see: `systemd/telize.service` 66 | 67 | Copy the `systemd/telize.service` file in `/etc/systemd/system` and the Telize 68 | binary in `/usr/local/sbin`. 69 | 70 | To launch the daemon at startup, run: 71 | 72 | systemctl enable telize 73 | 74 | ## Making Queries 75 | 76 | For complete API documentation and usage examples, please check the 77 | project site. 78 | 79 | Telize supports JSONP callbacks. 80 | 81 | ### Get IP address in Plain text format 82 | 83 | - Example: http://127.0.0.1:8080/ip 84 | 85 | ### Get IP address in JSON format 86 | 87 | - Example (JSON): http://127.0.0.1:8080/jsonip 88 | - Example (JSONP): http://127.0.0.1:8080/jsonip?callback=getip 89 | 90 | ### Get IP address location in JSON format 91 | 92 | Calling the API endpoint without any parameter will return the visitor 93 | IP address: 94 | 95 | - Example (JSON): http://127.0.0.1:8080/location 96 | - Example (JSONP): http://127.0.0.1:8080/location?callback=getlocation 97 | 98 | Appending an IP address as parameter will return location information for 99 | the given address: 100 | 101 | - Example (JSON): http://127.0.0.1:8080/location/46.19.37.108 102 | - Example (JSONP): http://127.0.0.1:8080/location/46.19.37.108?callback=getlocation 103 | 104 | ## Client Errors 105 | 106 | When incorrect user input is entered, the server returns an HTTP 400 Error 107 | (Bad Request), along with a JSON-encoded error message. 108 | 109 | - Code 401: Input string is not a valid IP address 110 | 111 | ## Telize and proxies 112 | 113 | Telize handles the 'X-Forwarded-For' HTTP header if present, and returns 114 | data for the first IP address of the list. 115 | 116 | ## CORS Support (Cross-origin resource sharing) 117 | 118 | Telize has CORS enabled by default with the following policy: 119 | 120 | Access-Control-Allow-Origin: * 121 | 122 | ## Timezone offsets 123 | 124 | Since version 3.0.0, Telize now dynamically calculates timezone offsets 125 | (UTC time offset) and adds data to the payload. 126 | 127 | ## License 128 | 129 | Telize is released under the BSD 2-Clause license. See `LICENSE` file 130 | for details. 131 | 132 | ## Author 133 | 134 | Telize is developed by Frederic Cambus. 135 | 136 | - Site: https://www.cambus.net 137 | 138 | ## Resources 139 | 140 | Project homepage: https://www.telize.com 141 | 142 | Latest tarball release: https://www.statdns.com/telize/telize-3.1.1.tar.gz 143 | 144 | GitHub: https://github.com/fcambus/telize 145 | 146 | [1]: https://dev.maxmind.com/geoip/geoip2/geolite2/ 147 | -------------------------------------------------------------------------------- /country-code3.go: -------------------------------------------------------------------------------- 1 | /* 2 | * Telize 4.0.0 3 | * Copyright (c) 2013-2025, Frederic Cambus 4 | * https://www.telize.com 5 | * 6 | * Created: 2013-08-15 7 | * Last Updated: 2022-01-18 8 | * 9 | * Telize is released under the BSD 2-Clause license. 10 | * See LICENSE file for details. 11 | * 12 | * SPDX-License-Identifier: BSD-2-Clause 13 | */ 14 | 15 | package main 16 | 17 | var CountryCode3 = map[string]string{ 18 | "AD": "AND", 19 | "AE": "ARE", 20 | "AF": "AFG", 21 | "AG": "ATG", 22 | "AI": "AIA", 23 | "AL": "ALB", 24 | "AM": "ARM", 25 | "AO": "AGO", 26 | "AQ": "ATA", 27 | "AR": "ARG", 28 | "AS": "ASM", 29 | "AT": "AUT", 30 | "AU": "AUS", 31 | "AW": "ABW", 32 | "AX": "ALA", 33 | "AZ": "AZE", 34 | "BA": "BIH", 35 | "BB": "BRB", 36 | "BD": "BGD", 37 | "BE": "BEL", 38 | "BF": "BFA", 39 | "BG": "BGR", 40 | "BH": "BHR", 41 | "BI": "BDI", 42 | "BJ": "BEN", 43 | "BL": "BLM", 44 | "BM": "BMU", 45 | "BN": "BRN", 46 | "BO": "BOL", 47 | "BQ": "BES", 48 | "BR": "BRA", 49 | "BS": "BHS", 50 | "BT": "BTN", 51 | "BV": "BVT", 52 | "BW": "BWA", 53 | "BY": "BLR", 54 | "BZ": "BLZ", 55 | "CA": "CAN", 56 | "CC": "CCK", 57 | "CD": "COD", 58 | "CF": "CAF", 59 | "CG": "COG", 60 | "CH": "CHE", 61 | "CI": "CIV", 62 | "CK": "COK", 63 | "CL": "CHL", 64 | "CM": "CMR", 65 | "CN": "CHN", 66 | "CO": "COL", 67 | "CR": "CRI", 68 | "CU": "CUB", 69 | "CV": "CPV", 70 | "CW": "CUW", 71 | "CX": "CXR", 72 | "CY": "CYP", 73 | "CZ": "CZE", 74 | "DE": "DEU", 75 | "DJ": "DJI", 76 | "DK": "DNK", 77 | "DM": "DMA", 78 | "DO": "DOM", 79 | "DZ": "DZA", 80 | "EC": "ECU", 81 | "EE": "EST", 82 | "EG": "EGY", 83 | "EH": "ESH", 84 | "ER": "ERI", 85 | "ES": "ESP", 86 | "ET": "ETH", 87 | "FI": "FIN", 88 | "FJ": "FJI", 89 | "FK": "FLK", 90 | "FM": "FSM", 91 | "FO": "FRO", 92 | "FR": "FRA", 93 | "GA": "GAB", 94 | "GB": "GBR", 95 | "GD": "GRD", 96 | "GE": "GEO", 97 | "GF": "GUF", 98 | "GG": "GGY", 99 | "GH": "GHA", 100 | "GI": "GIB", 101 | "GL": "GRL", 102 | "GM": "GMB", 103 | "GN": "GIN", 104 | "GP": "GLP", 105 | "GQ": "GNQ", 106 | "GR": "GRC", 107 | "GS": "SGS", 108 | "GT": "GTM", 109 | "GU": "GUM", 110 | "GW": "GNB", 111 | "GY": "GUY", 112 | "HK": "HKG", 113 | "HM": "HMD", 114 | "HN": "HND", 115 | "HR": "HRV", 116 | "HT": "HTI", 117 | "HU": "HUN", 118 | "ID": "IDN", 119 | "IE": "IRL", 120 | "IL": "ISR", 121 | "IM": "IMN", 122 | "IN": "IND", 123 | "IO": "IOT", 124 | "IQ": "IRQ", 125 | "IR": "IRN", 126 | "IS": "ISL", 127 | "IT": "ITA", 128 | "JE": "JEY", 129 | "JM": "JAM", 130 | "JO": "JOR", 131 | "JP": "JPN", 132 | "KE": "KEN", 133 | "KG": "KGZ", 134 | "KH": "KHM", 135 | "KI": "KIR", 136 | "KM": "COM", 137 | "KN": "KNA", 138 | "KP": "PRK", 139 | "KR": "KOR", 140 | "KW": "KWT", 141 | "KY": "CYM", 142 | "KZ": "KAZ", 143 | "LA": "LAO", 144 | "LB": "LBN", 145 | "LC": "LCA", 146 | "LI": "LIE", 147 | "LK": "LKA", 148 | "LR": "LBR", 149 | "LS": "LSO", 150 | "LT": "LTU", 151 | "LU": "LUX", 152 | "LV": "LVA", 153 | "LY": "LBY", 154 | "MA": "MAR", 155 | "MC": "MCO", 156 | "MD": "MDA", 157 | "ME": "MNE", 158 | "MF": "MAF", 159 | "MG": "MDG", 160 | "MH": "MHL", 161 | "MK": "MKD", 162 | "ML": "MLI", 163 | "MM": "MMR", 164 | "MN": "MNG", 165 | "MO": "MAC", 166 | "MP": "MNP", 167 | "MQ": "MTQ", 168 | "MR": "MRT", 169 | "MS": "MSR", 170 | "MT": "MLT", 171 | "MU": "MUS", 172 | "MV": "MDV", 173 | "MW": "MWI", 174 | "MX": "MEX", 175 | "MY": "MYS", 176 | "MZ": "MOZ", 177 | "NA": "NAM", 178 | "NC": "NCL", 179 | "NE": "NER", 180 | "NF": "NFK", 181 | "NG": "NGA", 182 | "NI": "NIC", 183 | "NL": "NLD", 184 | "NO": "NOR", 185 | "NP": "NPL", 186 | "NR": "NRU", 187 | "NU": "NIU", 188 | "NZ": "NZL", 189 | "OM": "OMN", 190 | "PA": "PAN", 191 | "PE": "PER", 192 | "PF": "PYF", 193 | "PG": "PNG", 194 | "PH": "PHL", 195 | "PK": "PAK", 196 | "PL": "POL", 197 | "PM": "SPM", 198 | "PN": "PCN", 199 | "PR": "PRI", 200 | "PS": "PSE", 201 | "PT": "PRT", 202 | "PW": "PLW", 203 | "PY": "PRY", 204 | "QA": "QAT", 205 | "RE": "REU", 206 | "RO": "ROU", 207 | "RS": "SRB", 208 | "RU": "RUS", 209 | "RW": "RWA", 210 | "SA": "SAU", 211 | "SB": "SLB", 212 | "SC": "SYC", 213 | "SD": "SDN", 214 | "SE": "SWE", 215 | "SG": "SGP", 216 | "SH": "SHN", 217 | "SI": "SVN", 218 | "SJ": "SJM", 219 | "SK": "SVK", 220 | "SL": "SLE", 221 | "SM": "SMR", 222 | "SN": "SEN", 223 | "SO": "SOM", 224 | "SR": "SUR", 225 | "SS": "SSD", 226 | "ST": "STP", 227 | "SV": "SLV", 228 | "SX": "SXM", 229 | "SY": "SYR", 230 | "SZ": "SWZ", 231 | "TC": "TCA", 232 | "TD": "TCD", 233 | "TF": "ATF", 234 | "TG": "TGO", 235 | "TH": "THA", 236 | "TJ": "TJK", 237 | "TK": "TKL", 238 | "TL": "TLS", 239 | "TM": "TKM", 240 | "TN": "TUN", 241 | "TO": "TON", 242 | "TR": "TUR", 243 | "TT": "TTO", 244 | "TV": "TUV", 245 | "TW": "TWN", 246 | "TZ": "TZA", 247 | "UA": "UKR", 248 | "UG": "UGA", 249 | "UM": "UMI", 250 | "US": "USA", 251 | "UY": "URY", 252 | "UZ": "UZB", 253 | "VA": "VAT", 254 | "VC": "VCT", 255 | "VE": "VEN", 256 | "VG": "VGB", 257 | "VI": "VIR", 258 | "VN": "VNM", 259 | "VU": "VUT", 260 | "WF": "WLF", 261 | "WS": "WSM", 262 | "YE": "YEM", 263 | "YT": "MYT", 264 | "ZA": "ZAF", 265 | "ZM": "ZMB", 266 | "ZW": "ZWE", 267 | } 268 | --------------------------------------------------------------------------------