Subject: [Info-WASD] Geolocation Utility
From: [email-masked]
To: [email-masked]
Date: Wed, 21 May 2025 14:17:08 +0930

Geolocation allows an IP address to be located in geography (country, region,
city), Internet Provider (ISP), and various other data that may be made
available by the hosting service ... with 'good-enough' accuracy.

  https://en.wikipedia.org/wiki/Internet_geolocation

WASD provided a geolocation utility with its 2022 package and then improved
further on that in the 2025 package.  It is intended to provide optional,
supplementary information where IP addresses are displayed.  It is not
integrated into the server or considered a 'supported' feature of WASD for
these reasons;

1) it uses a free, rate-limited geolocation service
2) that is; free for non-commercial uses
3) this could changed or be withdrawn at any point
4) being rate-limited imposes some constraints

Versions of WASD utilities providing optional geolocation data for IP
addresses include HTTPDMON and QDLOGSTATS.  The recently discussed INTRUspect
application also provides optional geolocation

  https://wasd.vsm.com.au/info-WASD/2025/0003

In addition, the GEOLOCATION utility itself provides data either as a textual
string or into DCL symbols.

  https://wasd.vsm.com.au/wasd_root/src/utils/geolocate.c

The GEOLOCATE utility can operate in two modes:

1) DCL symbol
   ~~~~~~~~~~

Where the IP address is supplied to the executable as a parameter/argument
the utility creates DCL symbols representing the data returned by the
service.  The symbols can then be used to further process and/or display that
data.  The example code shows a simple script to demonstrate this action.

  https://wasd.vsm.com.au/wasd_root/src/utils/geolocate.com
  https://wasd.vsm.com.au/cgi-bin/geolocate.com

2) geolocation string
   ~~~~~~~~~~~~~~~~~~

When not supplied as a parameter/argument the IP address is derived from the
CGI variable QUERY_STRING (facilitating explicit supply) or REMOTE_ADDR
(client address) and outputs a 'text/plain' HTTP response with a string
providing geolocation data in one of two formats.

  'IP address' 'country' / 'region' / 'city'
  'resolved domain name' ('IP address') 'country' / 'region' / 'city'

As geolocation lookup introduces latency, the RTT of the query and response,
this can make pages seemingly slow to load, particularly if rate-limiting has
become active.  A solution for this is to make the lookup asynchronous using
JavaScript.  This way the page is rendered as loaded, with the lookup 
completing the page transparently (usually) tens of milliseconds later.

The JavaScript snippet can be as simply invoked

  <head>
  8< snip 8<
  <script src="./geolocate.js"></script>
  </head>

asynchronously responding into an HTML DOM element identified as 

  <div id="wasdGeoLocate"></div>

  https://wasd.vsm.com.au/wasd_root/src/utils/geolocate.js

DECUServe uses this to provide a 'we know where you live' message.

  https://decuserve.org

As there is still some latency during geolocation lookup, the DECUServe
example, using Server Side Includes (SSI) code, pre-fills the host name and
address until lookup completes, overwriting the displayed pre-fill.  This
reduces the effect of an initially empty section of page suddenly being
populated.  Less jarring to the viewer.

  <div class="you" id="wasdGeoLocate">
  <b>You:</b>  <!--#echo var={remote_host} --> (<!--#echo var={remote_addr} -->) ...
  </div>

Caching Data
~~~~~~~~~~~~
The issue with a rate-limited service is that it cannot indiscriminately be
used without running the risk being either restricted for a period or banned
completely.  From the https://ip-api.com FAQ

 "How many requests can I do?

  Our endpoints are limited to 45 HTTP requests per minute from an IP
  address. If you go over this limit your requests will be throttled
  (HTTP 429) until your rate limit window is reset.

  If you need unlimited queries, please see our pro service."

One solution is to cache IP addresses and responses thereby potentially
reducing the number of lookups for repeated IP addresses.  The GEOLOCATE
utility has such a cache built-in.  It also implements the rate-limit
responses from the provider, introducing explicit waits as required.  The
HTTPDMON and QDLOGSTATS utilities do just this.  Another mechanism is, when
possible, to invoke the GEOLOCATE utility as a CGIplus script.  The resident
CGIplus maintains the cache.  The DECUServe example JavaScript above uses an
invocation URL of

  var url = '/cgiplus-bin/geolocate.exe';

Seems to work in practice.

And of course, if a commercial concern or high-rate site, there is always

  https://members.ip-api.com/#pricing

Using Geolocation Utilities
~~~~~~~~~~~~~~~~~~~~~~~~~~~
To make the geolocation HTTPMON and/or QDLOGSTATS the default just

  $ COPY WASD_EXE:HTTPDMON_GEOLOCATE.EXE WASD_EXE:HTTPDMON.EXE
  $ COPY WASD_EXE:QDLOGSTATS_GEOLOCATE.EXE WASD_EXE:QDLOGSTATS.EXE
  $ INSTALL REPLACE CGI-BIN:[000000]QDLOGSTATS.EXE

This item is one of a collection at
https://wasd.vsm.com.au/other/#occasional