uses WinInet;
// here i define a record to hold information
type
ApiResults = record
Status: UTF8String;
Country: UTF8String;
CountryCode: UTF8String;
RegionState: UTF8String;
RegionName: UTF8String;
City: UTF8String;
Zip: UTF8String;
Latitude: UTF8String;
Longitude: UTF8String;
CityTimeZone: UTF8String;
ISP: UTF8String;
Organization: UTF8String;
NumberName: UTF8String;
DNS: UTF8String;
MobileConnection: UTF8String;
ProxyConnection: UTF8String;
QueryIP: UTF8String;
ErrorMessage: UTF8String;
end;
// this is an api function call to perform GET, optimized to handle ASCII or UNICODE data
function GetUrlContentData(const Url: string): UTF8String;
var
NetHandle: HINTERNET;
UrlHandle: HINTERNET;
Buffer: array[0..1023] of byte;
BytesRead: dWord;
StrBuffer: UTF8String;
begin
Result := '';
NetHandle := InternetOpen('Delphi 2009', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
if Assigned(NetHandle) then
try
UrlHandle := InternetOpenUrl(NetHandle, PChar(Url), nil, 0, INTERNET_FLAG_RELOAD, 0);
if Assigned(UrlHandle) then
try
repeat
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
SetString(StrBuffer, PAnsiChar(@Buffer[0]), BytesRead);
Result := Result + StrBuffer;
until BytesRead = 0;
finally
InternetCloseHandle(UrlHandle);
end
else
raise Exception.CreateFmt('Cannot open URL %s', [Url]);
finally
InternetCloseHandle(NetHandle);
end
else
raise Exception.Create('Unable to initialize Wininet');
end;
// in here the main work is done, input will be splitted up to prior defined fields of record
function GetUrlContent(const Url: string): ApiResults;
var
tmp: UTF8String;
sl: TStrings;
begin
// api offers XML and other stuff, but LINE needs no anything, just a stringlist :)
// by manual calling desired fields you get more informations, so i add them all in here
tmp := GetUrlContentData(Url+'?fields=status,country,countryCode,region,regionName,city,zip,lat,lon,timezone,isp,org,as,reverse,mobile,proxy,query,message');
// the field "reverse" aka DNS-resolver consumes most of inet time, you may add option on/off for this feature
try
sl := TStringList.Create;
sl.Text := tmp;
// by reading api i figured out how results could be
// first received line will be "status", so i add it to its proper record field
Result.Status := sl[0];
// now i compare if "status" contain "fail" to set up later received lines correct
// feel free to use it as template
if Pos('fail', LowerCase(Result.Status)) > 0 then
begin
Result.ErrorMessage := sl[1];
Result.QueryIP := sl[2];
end
else
begin
Result.Country := sl[1];
Result.CountryCode := sl[2];
Result.RegionState := sl[3];
Result.RegionName := sl[4];
Result.City := sl[5];
Result.Zip := sl[6];
Result.Latitude := sl[7];
Result.Longitude := sl[8];
Result.CityTimeZone := sl[9];
Result.ISP := sl[10];
Result.Organization := sl[11];
Result.NumberName := sl[12];
// the field "reverse" aka DNS-resolver consumes most of inet time, you may add option on/off for this feature
Result.DNS := sl[13];
Result.MobileConnection := sl[14];
Result.ProxyConnection := sl[15];
Result.QueryIP := sl[16];
end;
finally
sl.Free;
tmp := '';
end;
end;
// here comes what GUI perform
procedure TForm1.Button1Click(Sender: TObject);
var
// in here all results are local stored
ThisLines: ApiResults;
begin
// after reading api, i choosed smallest method to perform the GET and qualify results, the LINE variant
// replace the second 'ip-api.com' with target IP/Domain, this is just example
ThisLines := GetUrlContent('http://ip-api.com/line/' + 'ip-api.com');
// Memo1 is a Delphi Control to draw text
Memo1.Lines.Add('Status: '+ThisLines.Status);
// determine what record type we have, "fail" or "success"
if Pos('fail', LowerCase(ThisLines.Status)) > 0 then
begin
Memo1.Lines.Add('ErrorMessage: '+ThisLines.ErrorMessage);
Memo1.Lines.Add('QueryIP: '+ThisLines.QueryIP);
end
else
begin
Memo1.Lines.Add('Country: '+ThisLines.Country);
Memo1.Lines.Add('CountryCode: '+ThisLines.CountryCode);
Memo1.Lines.Add('RegionState: '+ThisLines.RegionState);
Memo1.Lines.Add('RegionName: '+ThisLines.RegionName);
Memo1.Lines.Add('City: '+ThisLines.City);
Memo1.Lines.Add('Zip: '+ThisLines.Zip);
Memo1.Lines.Add('Latitude: '+ThisLines.Latitude);
Memo1.Lines.Add('Longitude: '+ThisLines.Longitude);
Memo1.Lines.Add('CityTimeZone: '+ThisLines.CityTimeZone);
Memo1.Lines.Add('ISP: '+ThisLines.ISP);
Memo1.Lines.Add('Organization: '+ThisLines.Organization);
Memo1.Lines.Add('NumberName: '+ThisLines.NumberName);
Memo1.Lines.Add('DNS: '+ThisLines.DNS);
Memo1.Lines.Add('MobileConnection: '+ThisLines.MobileConnection);
Memo1.Lines.Add('ProxyConnection: '+ThisLines.ProxyConnection);
Memo1.Lines.Add('QueryIP: '+ThisLines.QueryIP);
end;
end;