Skip to content

Commit 32906f4

Browse files
Added support for IP2Location Web Service
1 parent ed8030e commit 32906f4

3 files changed

Lines changed: 358 additions & 19 deletions

File tree

README.md

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
IP2Location Erlang Module
2-
=========================
1+
# IP2Location Erlang Module
32

43
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.
54

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

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

19+
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:
2020

21-
Compilation
22-
=======
21+
https://www.ip2location.com/web-service/ip2location
22+
23+
## Compilation
2324

2425
```
2526
erlc ip2location.erl
2627
erlc test.erl
2728
```
2829

29-
Example
30-
=======
30+
## QUERY USING THE BIN FILE
3131

32-
```erlang
33-
test:testme().
34-
```
32+
## Dependencies
3533

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

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

39+
## IPv4 BIN vs IPv6 BIN
4140

42-
IPv4 BIN vs IPv6 BIN
43-
======================
4441
Use the IPv4 BIN file if you just need to query IPv4 addresses.
4542

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

4845

49-
Copyright
50-
=========
46+
## Methods
47+
48+
Below are the methods supported in this module.
49+
50+
|Method Name|Description|
51+
|---|---|
52+
|new|Initialize with the BIN file.|
53+
|query|Returns the geolocation information in an object.|
54+
|close|Closes BIN file and resets metadata.|
55+
56+
## Usage
57+
58+
```erlang
59+
test:testme().
60+
```
61+
62+
## QUERY USING THE IP2LOCATION WEB SERVICE
5163

52-
Copyright (C) 2021 by IP2Location.com, support@ip2location.com
64+
## Methods
65+
Below are the methods supported in this module.
66+
67+
|Method Name|Description|
68+
|---|---|
69+
|openws| 3 input parameters:<ol><li>IP2Location API Key.</li><li>Package (WS1 - WS25)</li></li><li>Use HTTPS or HTTP</li></ol> |
70+
|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>|
71+
|getcredit|This method returns the web service credit balance in an object.|
72+
73+
## Usage
74+
75+
```erlang
76+
test:testme2().
77+
```

ip2location.erl

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-module(ip2location).
2-
-export([apiversion/0, getapiversion/0, new/1, query/1, close/0]).
2+
-export([apiversion/0, getapiversion/0, new/1, query/1, close/0, openws/3, lookup/3, getcredit/0]).
33
-record(ip2locationrecord, {
44
country_short = "-",
55
country_long = "-",
@@ -27,7 +27,7 @@
2727
-define(IF(Cond), (case (Cond) of true -> (0); false -> (1) end)).
2828

2929
apiversion() ->
30-
"8.3.0".
30+
"8.4.0".
3131

3232
getapiversion() ->
3333
io:format("API Version: ~p~n", [apiversion()]).
@@ -382,3 +382,136 @@ close() ->
382382
_ ->
383383
ets:delete(mymeta)
384384
end.
385+
386+
closews() ->
387+
case ets:info(myws) of
388+
undefined ->
389+
ok;
390+
_ ->
391+
ets:delete(myws),
392+
ok
393+
end.
394+
395+
configurews(APIKey, APIPackage, UseSSL) ->
396+
_ = closews(),
397+
398+
case ets:info(myws) of
399+
undefined ->
400+
ets:new(myws, [set, named_table]),
401+
ets:insert(myws, {apikey, APIKey}),
402+
ets:insert(myws, {apipackage, APIPackage}),
403+
ets:insert(myws, {usessl, UseSSL}),
404+
ok;
405+
_ ->
406+
ok
407+
end.
408+
409+
checkparams(APIKey, APIPackage) ->
410+
RegExp = "^[\\dA-Z]{10}$",
411+
RegExp2 = "^WS\\d+$",
412+
case re:run(APIKey, RegExp) of
413+
{match, _} ->
414+
case re:run(APIPackage, RegExp2) of
415+
nomatch ->
416+
io:format("Invalid package name.~n", []),
417+
halt();
418+
{match, _} ->
419+
ok % do nothing
420+
end;
421+
nomatch ->
422+
io:format("Invalid API key.~n", []),
423+
halt()
424+
end.
425+
426+
openws(APIKey, APIPackage, UseSSL) ->
427+
case checkparams(APIKey, APIPackage) of
428+
ok ->
429+
case UseSSL of
430+
false ->
431+
configurews(APIKey, APIPackage, UseSSL);
432+
_ ->
433+
configurews(APIKey, APIPackage, true)
434+
end;
435+
_ ->
436+
-1 % should have been halted in checkparams
437+
end.
438+
439+
lookup(IPAddress, AddOn, Lang) ->
440+
ssl:start(),
441+
inets:start(),
442+
443+
case ets:info(myws) of
444+
undefined ->
445+
io:format("Run openws first.~n", []),
446+
halt();
447+
_ ->
448+
case ets:lookup(myws, apikey) of
449+
[] ->
450+
io:format("Run openws first.~n", []),
451+
halt();
452+
[{_, APIKey}] ->
453+
case ets:lookup(myws, apipackage) of
454+
[] ->
455+
io:format("Run openws first.~n", []),
456+
halt();
457+
[{_, APIPackage}] ->
458+
case ets:lookup(myws, usessl) of
459+
[] ->
460+
io:format("Run openws first.~n", []),
461+
halt();
462+
[{_, UseSSL}] ->
463+
case UseSSL of
464+
true ->
465+
Protocol = "https";
466+
_ ->
467+
Protocol = "http"
468+
end,
469+
MyParams = uri_string:compose_query([{"key", APIKey}, {"package", APIPackage}, {"ip", IPAddress}, {"addon", AddOn}, {"lang", Lang}]),
470+
471+
case httpc:request(get, {Protocol ++ "://api.ip2location.com/v2/?" ++ MyParams, []}, [{ssl, [{versions, ['tlsv1.2']}]}, {autoredirect, false}], []) of
472+
{ok, {{_, 200, _}, _, Body}} ->
473+
jiffy:decode(unicode:characters_to_binary(Body,unicode,utf8),[return_maps]);
474+
{error, Reason} ->
475+
{error, Reason}
476+
end
477+
end
478+
end
479+
end
480+
end.
481+
482+
getcredit() ->
483+
ssl:start(),
484+
inets:start(),
485+
486+
case ets:info(myws) of
487+
undefined ->
488+
io:format("Run openws first.~n", []),
489+
halt();
490+
_ ->
491+
case ets:lookup(myws, apikey) of
492+
[] ->
493+
io:format("Run openws first.~n", []),
494+
halt();
495+
[{_, APIKey}] ->
496+
case ets:lookup(myws, usessl) of
497+
[] ->
498+
io:format("Run openws first.~n", []),
499+
halt();
500+
[{_, UseSSL}] ->
501+
case UseSSL of
502+
true ->
503+
Protocol = "https";
504+
_ ->
505+
Protocol = "http"
506+
end,
507+
MyParams = uri_string:compose_query([{"key", APIKey}, {"check", "true"}]),
508+
509+
case httpc:request(get, {Protocol ++ "://api.ip2location.com/v2/?" ++ MyParams, []}, [{ssl, [{versions, ['tlsv1.2']}]}, {autoredirect, false}], []) of
510+
{ok, {{_, 200, _}, _, Body}} ->
511+
jiffy:decode(unicode:characters_to_binary(Body,unicode,utf8),[return_maps]);
512+
{error, Reason} ->
513+
{error, Reason}
514+
end
515+
end
516+
end
517+
end.

0 commit comments

Comments
 (0)