What is my IP address?

by Oct 20, 2017

There are many situation when it would handy to know the IP address of a device where our app is running. Maybe you want to identify who is running your app? By IP address it is also possible to calculate the approximate location of a device. If you connect to Internet through a router, there are big chances that it implements "Network Address Translation" (NAT), to make it harder for remote machines to establish a direct connection to a machine within a local network.

Recently I have come across a very simple and useful REST API that makes it possible to get the IP address and the geographical location of a client that invokes it. In this way we could find out under which IP address the Internet "sees" us.

If you send an HTTP GET request to http://ip-api.com/json, you will receive a JSON document with information about your IP address, longitude and latitude, country, city, zip code, ISP provider name, timezone and region.

In order to make this service easily accessible in code I have put together a little Delphi "TMyIP" class that provides one class function "GetInfo" that takes "TIPInfo" record "out" parameter and returns a boolean value that indicates if the parameter contains valid information. The actual HTTP GET request is made using the native "THTTPClient" class from "System.Net.HttpClient" unit. The JSON processing is done using "TJSONTextReader" class.

Below is the full source code of the "uMyIP" unit that contains the "TMyIP" class.


unit uMyIP;

interface

type
  TIPInfo = record
    status: stringstringstringstringstringstringstringstringstringstringstringstringendclass
  public
    class function GetInfo(out info: TIPInfo): boolean;
  endimplementation

uses
  System.SysUtils,
  System.Classes,
  System.JSON.Readers,
  System.JSON.Types,
  System.Net.HttpClient;

const
  IP_API_JSON_URL = 'http://ip-api.com/json';

{ TMyIP }

class function TMyIP.GetInfo(out info: TIPInfo): boolean;
var c: THTTPClient; json: stringbegin
  Result := False;
  c := THTTPClient.Create;
  try
    try
      resp := c.Get(IP_API_JSON_URL);
      json := resp.ContentAsString;
    except
      exit;
    endfinally
    c.Free;
  endtry
    jtr := TJsonTextReader.Create(sr);
    try
      while jtr.Read do
      begin
        if jtr.TokenType = TJsonToken.PropertyName then
        begin
          if jtr.Value.ToString = 'status' then
          begin
            jtr.Read;
            info.status := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'as' then
          begin
            jtr.Read;
            info.aAs := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'city' then
          begin
            jtr.Read;
            info.city := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'country' then
          begin
            jtr.Read;
            info.country := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'countyCode' then
          begin
            jtr.Read;
            info.countyCode := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'isp' then
          begin
            jtr.Read;
            info.isp := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'lat' then
          begin
            jtr.Read;
            info.lat := jtr.Value.AsExtended;
          end

          else if jtr.Value.ToString = 'lon' then
          begin
            jtr.Read;
            info.lon := jtr.Value.AsExtended;
          end

          else if jtr.Value.ToString = 'org' then
          begin
            jtr.Read;
            info.org := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'query' then
          begin
            jtr.Read;
            info.IPAddress := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'region' then
          begin
            jtr.Read;
            info.region := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'regionName' then
          begin
            jtr.Read;
            info.regionName := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'timezone' then
          begin
            jtr.Read;
            info.timezone := jtr.Value.AsString;
          end

          else if jtr.Value.ToString = 'zip' then
          begin
            jtr.Read;
            info.zip := jtr.Value.AsString;
          end

        endend
    finally
      jtr.Free;
    endfinally
    sr.Free;
  endendend.

Let's quickly test this class. Start Delphi and create a new "Multi-Device Application" project. Choose "Blank Application" template and save the main form as "uFormMyIP" and the whole project as "MyIP". You can optionally change the "Name" property of the form to "FormMyIP". Add a new unit to the project and save it as "uMyIP". Copy the above code, select the source code of the empty unit and paste the code to replace the entire content. Now add the new "uMyIP" unit to the uses clause of the form. Drop a button on the form and align it to "Top". Change its "Text" property to "Check IP". Drop "TListView" control onto the form, align it to "Client" and change its "Name" property to "lstvwInfo". Double-click on the button and add the following code to the "OnClick" event handler to invoke the "TMyIP.GetInfo" and display the data in the list view.


uses uMyIP;

procedure TFormMyIP.btnCheckIPClick(Sender: TObject);

  procedure AddItem(txt, det: string  var item: TListViewItem;
  begin
    item := lstvwInfo.Items.Add;
    item.Text := txt;
    item.Detail := det;
  endvar info: TIPInfo; item: TListViewItem;
begin
  if TMyIP.GetInfo(info) then
  begin
    lstvwInfo.BeginUpdate;
    try
      lstvwInfo.Items.Clear;
      AddItem(info.IPAddress, 'IP address');
      AddItem(info.city, 'City');
      AddItem(info.country, 'Country');
      AddItem(info.timezone, 'Timezone');
      AddItem(info.lat.ToString, 'Latitude');
      AddItem(info.lon.ToString, 'Longitude');
    finally
      lstvwInfo.EndUpdate;
    endend
  else
    ShowMessage('Failed');
end

Save all and run the project. When you click on the button you should see how the world sees You!

The complete source code of this simple demo can be downloaded from here. Enjoy!