From da516d7a50ba78d59d366c1b35cf0883d1ddf68b Mon Sep 17 00:00:00 2001 From: bplubell Date: Mon, 15 Sep 2025 08:07:54 -0700 Subject: [PATCH 1/2] Add referer header to Nominatim requests Per the [Nominatim usage policy][1], all requests should have an identifying Referer or User-Agent header (quoted below). Using the host name, as we already do for Mapbox requests, should be sufficient to satisfy the requirement while avoiding the need for additional settings. > Provide a valid HTTP Referer or User-Agent identifying the > application (stock User-Agents as set by http libraries will not do). [1]: https://operations.osmfoundation.org/policies/nominatim/ --- src/services/GeoService.php | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/services/GeoService.php b/src/services/GeoService.php index c83ad64..aace988 100644 --- a/src/services/GeoService.php +++ b/src/services/GeoService.php @@ -796,7 +796,15 @@ private static function _latLngFromAddress_Nominatim ($address, $country): ?arra $url .= '&country=' . rawurlencode($country); } - $data = (string) static::_client()->get($url)->getBody(); + $referer = Craft::$app->getRequest()->getIsConsoleRequest() + ? Craft::getAlias('@web') + : Craft::$app->urlManager->getHostInfo(); + + $data = (string) static::_client()->get($url, [ + 'headers' => [ + 'referer' => $referer + ] + ])->getBody(); $data = Json::decodeIfJson($data); if (!is_array($data) || empty($data)) @@ -883,7 +891,15 @@ private static function _addressFromLatLng_Nominatim ($lat, $lng): ?array $url .= '&accept-language=' . Craft::$app->locale->getLanguageID(); $url .= '&lat=' . rawurlencode($lat) . '&lon=' . rawurldecode($lng); - $data = (string) static::_client()->get($url)->getBody(); + $referer = Craft::$app->getRequest()->getIsConsoleRequest() + ? Craft::getAlias('@web') + : Craft::$app->urlManager->getHostInfo(); + + $data = (string) static::_client()->get($url, [ + 'headers' => [ + 'referer' => $referer + ] + ])->getBody(); $data = Json::decodeIfJson($data); if (!is_array($data) || empty($data) || array_key_exists('error', $data)) From a48b80dc13f28168b386e7be0bea61987a2be8e9 Mon Sep 17 00:00:00 2001 From: bplubell Date: Wed, 17 Sep 2025 14:38:37 -0700 Subject: [PATCH 2/2] Add app identifier to User-Agent for Nominatim requests An openstreetmap.org system administrator recommended we include an app identifier in the User-Agent header. My inference is that they block based on the User-Agent. However, I did not want to use only the app identifier so I found the form that Craft uses and copied that, appending the app identifier. --- src/services/GeoService.php | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/services/GeoService.php b/src/services/GeoService.php index aace988..60b4c43 100644 --- a/src/services/GeoService.php +++ b/src/services/GeoService.php @@ -21,6 +21,7 @@ use GuzzleHttp\Client; use Mapkit\JWT; use Exception; +use function GuzzleHttp\default_user_agent; /** * Class GeoService @@ -763,13 +764,9 @@ private static function _latLngFromAddress_Mapbox ($token, $address, $country): $url = str_replace('.json', rawurlencode(', ' . $country) . '.json', $url); } - $referer = Craft::$app->getRequest()->getIsConsoleRequest() - ? Craft::getAlias('@web') - : Craft::$app->urlManager->getHostInfo(); - $data = (string) static::_client()->get($url, [ 'headers' => [ - 'referer' => $referer, + 'referer' => static::_referer(), ] ])->getBody(); $data = Json::decodeIfJson($data); @@ -796,13 +793,10 @@ private static function _latLngFromAddress_Nominatim ($address, $country): ?arra $url .= '&country=' . rawurlencode($country); } - $referer = Craft::$app->getRequest()->getIsConsoleRequest() - ? Craft::getAlias('@web') - : Craft::$app->urlManager->getHostInfo(); - $data = (string) static::_client()->get($url, [ 'headers' => [ - 'referer' => $referer + 'referer' => static::_referer(), + 'user-agent' => static::_userAgent(), ] ])->getBody(); $data = Json::decodeIfJson($data); @@ -891,13 +885,10 @@ private static function _addressFromLatLng_Nominatim ($lat, $lng): ?array $url .= '&accept-language=' . Craft::$app->locale->getLanguageID(); $url .= '&lat=' . rawurlencode($lat) . '&lon=' . rawurldecode($lng); - $referer = Craft::$app->getRequest()->getIsConsoleRequest() - ? Craft::getAlias('@web') - : Craft::$app->urlManager->getHostInfo(); - $data = (string) static::_client()->get($url, [ 'headers' => [ - 'referer' => $referer + 'referer' => static::_referer(), + 'user-agent' => static::_userAgent(), ] ])->getBody(); $data = Json::decodeIfJson($data); @@ -930,6 +921,21 @@ private static function _client () return $client; } + private static function _referer () + { + return Craft::$app->getRequest()->getIsConsoleRequest() + ? Craft::getAlias('@web') + : Craft::$app->urlManager->getHostInfo(); + } + + private static function _userAgent () + { + // User agent form based on Craft::createGuzzleClient + return 'Craft/' . Craft::$app->getVersion() + . ' ' . default_user_agent() + . ' ' . static::_referer(); + } + private static function _validateCountryCode (string $code): bool { return in_array(strtoupper($code), array_keys(static::$countries));