Skip to content

Commit

Permalink
Added support for IP2Location Web Service
Browse files Browse the repository at this point in the history
  • Loading branch information
ip2location committed Nov 24, 2021
1 parent ed8030e commit 32906f4
Show file tree
Hide file tree
Showing 3 changed files with 358 additions and 19 deletions.
59 changes: 42 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
IP2Location Erlang Module
=========================
# IP2Location Erlang Module

This Erlang module provides a fast lookup of country, region, city, latitude, longitude, ZIP code, time zone, ISP, domain name, connection type, IDD code, area code, weather station code, station name, mcc, mnc, mobile brand, elevation, usage type, address type and IAB category from IP address by using IP2Location database. This module uses a file based database available at IP2Location.com. This database simply contains IP blocks as keys, and other information such as country, region, city, latitude, longitude, ZIP code, time zone, ISP, domain name, connection type, IDD code, area code, weather station code, station name, mcc, mnc, mobile brand, elevation, usage type, address type and IAB category as values. It supports both IP address in IPv4 and IPv6.

Expand All @@ -17,36 +16,62 @@ The database will be updated in monthly basis for the greater accuracy. Free LIT

The paid databases are available at https://www.ip2location.com under Premium subscription package.

As an alternative, this geolocation module can also call the IP2Location Web Service. This requires an API key. If you don't have an existing API key, you can subscribe for one at the below:

Compilation
=======
https://www.ip2location.com/web-service/ip2location

## Compilation

```
erlc ip2location.erl
erlc test.erl
```

Example
=======
## QUERY USING THE BIN FILE

```erlang
test:testme().
```
## Dependencies

Dependencies
============
This module requires IP2Location BIN data file to function. You may download the BIN data file at
* IP2Location LITE BIN Data (Free): https://lite.ip2location.com
* IP2Location Commercial BIN Data (Comprehensive): https://www.ip2location.com

The complete database is available at https://www.ip2location.com under subscription package.

## IPv4 BIN vs IPv6 BIN

IPv4 BIN vs IPv6 BIN
======================
Use the IPv4 BIN file if you just need to query IPv4 addresses.

Use the IPv6 BIN file if you need to query BOTH IPv4 and IPv6 addresses.


Copyright
=========
## Methods

Below are the methods supported in this module.

|Method Name|Description|
|---|---|
|new|Initialize with the BIN file.|
|query|Returns the geolocation information in an object.|
|close|Closes BIN file and resets metadata.|

## Usage

```erlang
test:testme().
```

## QUERY USING THE IP2LOCATION WEB SERVICE

Copyright (C) 2021 by IP2Location.com, support@ip2location.com
## Methods
Below are the methods supported in this module.

|Method Name|Description|
|---|---|
|openws| 3 input parameters:<ol><li>IP2Location API Key.</li><li>Package (WS1 - WS25)</li></li><li>Use HTTPS or HTTP</li></ol> |
|lookup|Query IP address. This method returns an object containing the geolocation info. <ul><li>country_code</li><li>country_name</li><li>region_name</li><li>city_name</li><li>latitude</li><li>longitude</li><li>zip_code</li><li>time_zone</li><li>isp</li><li>domain</li><li>net_speed</li><li>idd_code</li><li>area_code</li><li>weather_station_code</li><li>weather_station_name</li><li>mcc</li><li>mnc</li><li>mobile_brand</li><li>elevation</li><li>usage_type</li><li>address_type</li><li>category</li><li>continent<ul><li>name</li><li>code</li><li>hemisphere</li><li>translations</li></ul></li><li>country<ul><li>name</li><li>alpha3_code</li><li>numeric_code</li><li>demonym</li><li>flag</li><li>capital</li><li>total_area</li><li>population</li><li>currency<ul><li>code</li><li>name</li><li>symbol</li></ul></li><li>language<ul><li>code</li><li>name</li></ul></li><li>idd_code</li><li>tld</li><li>is_eu</li><li>translations</li></ul></li><li>region<ul><li>name</li><li>code</li><li>translations</li></ul></li><li>city<ul><li>name</li><li>translations</li></ul></li><li>geotargeting<ul><li>metro</li></ul></li><li>country_groupings</li><li>time_zone_info<ul><li>olson</li><li>current_time</li><li>gmt_offset</li><li>is_dst</li><li>sunrise</li><li>sunset</li></ul></li><ul>|
|getcredit|This method returns the web service credit balance in an object.|

## Usage

```erlang
test:testme2().
```
137 changes: 135 additions & 2 deletions ip2location.erl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
-module(ip2location).
-export([apiversion/0, getapiversion/0, new/1, query/1, close/0]).
-export([apiversion/0, getapiversion/0, new/1, query/1, close/0, openws/3, lookup/3, getcredit/0]).
-record(ip2locationrecord, {
country_short = "-",
country_long = "-",
Expand Down Expand Up @@ -27,7 +27,7 @@
-define(IF(Cond), (case (Cond) of true -> (0); false -> (1) end)).

apiversion() ->
"8.3.0".
"8.4.0".

getapiversion() ->
io:format("API Version: ~p~n", [apiversion()]).
Expand Down Expand Up @@ -382,3 +382,136 @@ close() ->
_ ->
ets:delete(mymeta)
end.

closews() ->
case ets:info(myws) of
undefined ->
ok;
_ ->
ets:delete(myws),
ok
end.

configurews(APIKey, APIPackage, UseSSL) ->
_ = closews(),

case ets:info(myws) of
undefined ->
ets:new(myws, [set, named_table]),
ets:insert(myws, {apikey, APIKey}),
ets:insert(myws, {apipackage, APIPackage}),
ets:insert(myws, {usessl, UseSSL}),
ok;
_ ->
ok
end.

checkparams(APIKey, APIPackage) ->
RegExp = "^[\\dA-Z]{10}$",
RegExp2 = "^WS\\d+$",
case re:run(APIKey, RegExp) of
{match, _} ->
case re:run(APIPackage, RegExp2) of
nomatch ->
io:format("Invalid package name.~n", []),
halt();
{match, _} ->
ok % do nothing
end;
nomatch ->
io:format("Invalid API key.~n", []),
halt()
end.

openws(APIKey, APIPackage, UseSSL) ->
case checkparams(APIKey, APIPackage) of
ok ->
case UseSSL of
false ->
configurews(APIKey, APIPackage, UseSSL);
_ ->
configurews(APIKey, APIPackage, true)
end;
_ ->
-1 % should have been halted in checkparams
end.

lookup(IPAddress, AddOn, Lang) ->
ssl:start(),
inets:start(),

case ets:info(myws) of
undefined ->
io:format("Run openws first.~n", []),
halt();
_ ->
case ets:lookup(myws, apikey) of
[] ->
io:format("Run openws first.~n", []),
halt();
[{_, APIKey}] ->
case ets:lookup(myws, apipackage) of
[] ->
io:format("Run openws first.~n", []),
halt();
[{_, APIPackage}] ->
case ets:lookup(myws, usessl) of
[] ->
io:format("Run openws first.~n", []),
halt();
[{_, UseSSL}] ->
case UseSSL of
true ->
Protocol = "https";
_ ->
Protocol = "http"
end,
MyParams = uri_string:compose_query([{"key", APIKey}, {"package", APIPackage}, {"ip", IPAddress}, {"addon", AddOn}, {"lang", Lang}]),

case httpc:request(get, {Protocol ++ "://api.ip2location.com/v2/?" ++ MyParams, []}, [{ssl, [{versions, ['tlsv1.2']}]}, {autoredirect, false}], []) of
{ok, {{_, 200, _}, _, Body}} ->
jiffy:decode(unicode:characters_to_binary(Body,unicode,utf8),[return_maps]);
{error, Reason} ->
{error, Reason}
end
end
end
end
end.

getcredit() ->
ssl:start(),
inets:start(),

case ets:info(myws) of
undefined ->
io:format("Run openws first.~n", []),
halt();
_ ->
case ets:lookup(myws, apikey) of
[] ->
io:format("Run openws first.~n", []),
halt();
[{_, APIKey}] ->
case ets:lookup(myws, usessl) of
[] ->
io:format("Run openws first.~n", []),
halt();
[{_, UseSSL}] ->
case UseSSL of
true ->
Protocol = "https";
_ ->
Protocol = "http"
end,
MyParams = uri_string:compose_query([{"key", APIKey}, {"check", "true"}]),

case httpc:request(get, {Protocol ++ "://api.ip2location.com/v2/?" ++ MyParams, []}, [{ssl, [{versions, ['tlsv1.2']}]}, {autoredirect, false}], []) of
{ok, {{_, 200, _}, _, Body}} ->
jiffy:decode(unicode:characters_to_binary(Body,unicode,utf8),[return_maps]);
{error, Reason} ->
{error, Reason}
end
end
end
end.
Loading

0 comments on commit 32906f4

Please sign in to comment.