Skip to content

Commit f924123

Browse files
kodinkatcorsacca
andauthored
Include reference when validating mapbox key.
* Enhance Mapbox API error handling: Added checks for missing token, network errors, and specific HTTP response codes. Improved user feedback with detailed error messages and guidance for resolving access issues. * Refactor Mapbox API error handling: Removed unnecessary whitespace and improved code readability in the is_active_mapbox_key method. Enhanced user feedback by ensuring detailed error messages are consistently formatted. * Implement Referer header in Mapbox API requests: Added a method to generate request arguments with a Referer header to ensure URL restrictions are respected. Enhanced error handling for 403 responses by providing detailed guidance for resolving access issues related to URL restrictions. * Update another location where Mapbox is being used. --------- Co-authored-by: corsac <corsacca@gmail.com>
1 parent 20fe065 commit f924123

2 files changed

Lines changed: 169 additions & 20 deletions

File tree

dt-mapping/geocode-api/location-grid-geocoder.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -828,8 +828,22 @@ public function query_by_grid_id( $grid_id ) {
828828
public function mapbox_get_country_by_coordinates( $longitude, $latitude ) {
829829
$country_code = false;
830830
if ( get_option( 'dt_mapbox_api_key' ) ) {
831-
$url = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' . $longitude . ',' . $latitude . '.json?types=country&access_token=' . get_option( 'dt_mapbox_api_key' );
832-
$data_result = @file_get_contents( $url );
831+
$url = 'https://api.mapbox.com/geocoding/v5/mapbox.places/' . $longitude . ',' . $latitude . '.json?types=country&access_token=' . get_option( 'dt_mapbox_api_key' );
832+
833+
$server_url = home_url( '', 'https' );
834+
$server_url = rtrim( $server_url, '/' );
835+
$args = [
836+
'headers' => [
837+
'Referer' => $server_url
838+
]
839+
];
840+
$response = wp_remote_get( esc_url_raw( $url ), $args );
841+
842+
if ( is_wp_error( $response ) ) {
843+
return false;
844+
}
845+
846+
$data_result = wp_remote_retrieve_body( $response );
833847
if ( ! $data_result ) {
834848
return false;
835849
}

dt-mapping/geocode-api/mapbox-api.php

Lines changed: 153 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@ public static function update_key( $key ) {
4545
return update_option( 'dt_mapbox_api_key', $key, true );
4646
}
4747

48+
/**
49+
* Get request arguments with Referer header for Mapbox API calls
50+
* This ensures URL restrictions work correctly with server-side requests
51+
*
52+
* @return array Request arguments array with Referer header
53+
*/
54+
private static function get_mapbox_request_args() {
55+
// Get and normalize the server URL for Referer header
56+
$server_url = home_url( '', 'https' );
57+
// Remove trailing slash for consistency
58+
$server_url = rtrim( $server_url, '/' );
59+
60+
return [
61+
'headers' => [
62+
'Referer' => $server_url
63+
]
64+
];
65+
}
66+
4867
/**
4968
* Geocoder Scripts for Echo
5069
*/
@@ -77,7 +96,8 @@ public static function forward_lookup( $address, $country_code = null ) {
7796
}
7897

7998
/** @link https://codex.wordpress.org/Function_Reference/wp_remote_get */
80-
$response = wp_remote_get( esc_url_raw( $url ) );
99+
$args = self::get_mapbox_request_args();
100+
$response = wp_remote_get( esc_url_raw( $url ), $args );
81101
$data_result = wp_remote_retrieve_body( $response );
82102

83103
if ( ! $data_result ) {
@@ -138,9 +158,9 @@ public static function lookup( $search_string, $type = 'full', $country_code = n
138158
break;
139159
}
140160

141-
142161
/** @link https://codex.wordpress.org/Function_Reference/wp_remote_get */
143-
$response = wp_remote_get( esc_url_raw( $url ) );
162+
$args = self::get_mapbox_request_args();
163+
$response = wp_remote_get( esc_url_raw( $url ), $args );
144164
$data_result = wp_remote_retrieve_body( $response );
145165

146166
if ( ! $data_result ) {
@@ -150,8 +170,9 @@ public static function lookup( $search_string, $type = 'full', $country_code = n
150170
}
151171

152172
public static function reverse_lookup( $longitude, $latitude ) {
153-
$url = self::$mapbox_endpoint . $longitude . ',' . $latitude . '.json?access_token=' . self::get_key();
154-
$response = wp_remote_get( esc_url_raw( $url ) );
173+
$url = self::$mapbox_endpoint . $longitude . ',' . $latitude . '.json?access_token=' . self::get_key();
174+
$args = self::get_mapbox_request_args();
175+
$response = wp_remote_get( esc_url_raw( $url ), $args );
155176
$data_result = wp_remote_retrieve_body( $response );
156177

157178
if ( ! $data_result ) {
@@ -171,11 +192,19 @@ public static function reverse_lookup( $longitude, $latitude ) {
171192
public static function get_country_by_coordinates( $longitude, $latitude ) {
172193
$country_code = false;
173194
if ( self::get_key() ) {
174-
$url = self::$mapbox_endpoint . $longitude . ',' . $latitude . '.json?types=country&access_token=' . self::get_key();
175-
$data_result = @file_get_contents( $url );
195+
$url = self::$mapbox_endpoint . $longitude . ',' . $latitude . '.json?types=country&access_token=' . self::get_key();
196+
$args = self::get_mapbox_request_args();
197+
$response = wp_remote_get( esc_url_raw( $url ), $args );
198+
199+
if ( is_wp_error( $response ) ) {
200+
return false;
201+
}
202+
203+
$data_result = wp_remote_retrieve_body( $response );
176204
if ( ! $data_result ) {
177205
return false;
178206
}
207+
179208
$data = json_decode( $data_result, true );
180209

181210
if ( isset( $data['features'][0]['properties']['short_code'] ) ) {
@@ -396,21 +425,91 @@ public static function load_admin_header() {
396425

397426
public static function is_active_mapbox_key() : array {
398427
$key = self::get_key();
399-
$url = self::$mapbox_endpoint . 'Denver.json?access_token=' . $key;
400-
$response = wp_remote_get( esc_url_raw( $url ) );
401-
$data_result = json_decode( wp_remote_retrieve_body( $response ), true );
402428

403-
if ( isset( $data_result['features'] ) && ! empty( $data_result['features'] ) ) {
429+
if ( empty( $key ) ) {
404430
return [
405-
'success' => true,
406-
'message' => ''
431+
'success' => false,
432+
'message' => 'No Mapbox API token provided',
433+
'error_type' => 'missing_token'
407434
];
408-
} else {
435+
}
436+
437+
// Get normalized server URL for error reporting
438+
$server_url = home_url( '', 'https' );
439+
$server_url = rtrim( $server_url, '/' );
440+
$referer_url = $server_url;
441+
442+
$url = self::$mapbox_endpoint . 'Denver.json?access_token=' . $key;
443+
444+
// Set Referer header to match the site URL so Mapbox can validate URL restrictions
445+
$args = self::get_mapbox_request_args();
446+
$response = wp_remote_get( esc_url_raw( $url ), $args );
447+
448+
// Check for WordPress HTTP errors
449+
if ( is_wp_error( $response ) ) {
409450
return [
410451
'success' => false,
411-
'message' => ( isset( $data_result['message'] ) && ! empty( $data_result['message'] ) ) ? $data_result['message'] : ''
452+
'message' => 'Network error: ' . $response->get_error_message(),
453+
'error_type' => 'network_error'
412454
];
413455
}
456+
457+
// Get HTTP response code
458+
$http_code = wp_remote_retrieve_response_code( $response );
459+
$body = wp_remote_retrieve_body( $response );
460+
$data_result = json_decode( $body, true );
461+
462+
// Success case
463+
if ( $http_code === 200 && isset( $data_result['features'] ) && ! empty( $data_result['features'] ) ) {
464+
return [
465+
'success' => true,
466+
'message' => ''
467+
];
468+
}
469+
470+
// Error cases based on HTTP status code
471+
$error_message = isset( $data_result['message'] ) ? $data_result['message'] : 'Unknown error';
472+
473+
switch ( $http_code ) {
474+
case 401:
475+
return [
476+
'success' => false,
477+
'message' => 'Invalid or expired Mapbox access token. Please check your token.',
478+
'error_type' => 'unauthorized',
479+
'api_message' => $error_message
480+
];
481+
482+
case 403:
483+
// Build detailed error message for URL restriction issues
484+
$message = 'Mapbox token is valid but access is restricted. ';
485+
$message .= 'This may be due to URL restrictions on your token. ';
486+
$message .= 'The request was sent with Referer header: ' . $referer_url;
487+
488+
return [
489+
'success' => false,
490+
'message' => $message,
491+
'error_type' => 'forbidden',
492+
'api_message' => $error_message,
493+
'server_url' => $server_url,
494+
'referer_sent' => $referer_url
495+
];
496+
497+
case 429:
498+
return [
499+
'success' => false,
500+
'message' => 'Rate limit exceeded. Please try again later.',
501+
'error_type' => 'rate_limit',
502+
'api_message' => $error_message
503+
];
504+
505+
default:
506+
return [
507+
'success' => false,
508+
'message' => 'Could not verify Mapbox token. HTTP ' . $http_code . ': ' . $error_message,
509+
'error_type' => 'api_error',
510+
'api_message' => $error_message
511+
];
512+
}
414513
}
415514

416515
/**
@@ -441,8 +540,44 @@ public static function metabox_for_admin() {
441540
if ( empty( $key ) ) {
442541
$message = 'Please add a Mapbox API Token';
443542
} else {
444-
$message = 'Could not connect to the Mapbox API or could not verify the token';
445-
$message .= ! empty( $mapbox_key_active_state['message'] ) ? ' - ' . $mapbox_key_active_state['message'] : '';
543+
$message = $mapbox_key_active_state['message'];
544+
545+
// Add detailed information for 403 errors (URL restrictions)
546+
if ( isset( $mapbox_key_active_state['error_type'] ) && $mapbox_key_active_state['error_type'] === 'forbidden' ) {
547+
$message .= '<br><br><strong>Debugging Information:</strong>';
548+
$message .= '<br><strong>Site URL detected:</strong> <code>' . esc_html( $mapbox_key_active_state['server_url'] ?? 'N/A' ) . '</code>';
549+
550+
if ( isset( $mapbox_key_active_state['referer_sent'] ) ) {
551+
$message .= '<br><strong>Referer header sent:</strong> <code>' . esc_html( $mapbox_key_active_state['referer_sent'] ) . '</code>';
552+
}
553+
554+
$message .= '<br><br><strong>To fix this:</strong>';
555+
$message .= '<ol style="margin-left: 20px;">';
556+
$message .= '<li>Go to your <a href="https://account.mapbox.com/access-tokens/" target="_blank">Mapbox account settings</a></li>';
557+
$message .= '<li>Find your access token and click to edit it</li>';
558+
$message .= '<li>In the "URL restrictions" section, add the URL shown above</li>';
559+
560+
// Special note for local development URLs
561+
if ( isset( $mapbox_key_active_state['referer_sent'] ) ) {
562+
$referer = $mapbox_key_active_state['referer_sent'];
563+
if ( strpos( $referer, 'localhost' ) !== false || strpos( $referer, '.local' ) !== false || strpos( $referer, '127.0.0.1' ) !== false ) {
564+
$message .= '<li><strong>Note:</strong> You\'re using a local development URL. Mapbox URL restrictions may not work with localhost or .local domains. Consider using a token without URL restrictions for local development, or use a tool like ngrok to create a public URL for testing.</li>';
565+
}
566+
}
567+
568+
$message .= '<li>Save your changes and test again</li>';
569+
$message .= '</ol>';
570+
571+
// Add API message if available
572+
if ( isset( $mapbox_key_active_state['api_message'] ) && ! empty( $mapbox_key_active_state['api_message'] ) ) {
573+
$message .= '<br><br><em>Mapbox API Response: ' . esc_html( $mapbox_key_active_state['api_message'] ) . '</em>';
574+
}
575+
} else {
576+
// Add API message details for other error types if available
577+
if ( isset( $mapbox_key_active_state['api_message'] ) && ! empty( $mapbox_key_active_state['api_message'] ) && $mapbox_key_active_state['api_message'] !== $mapbox_key_active_state['message'] ) {
578+
$message .= '<br><br><em>API Response: ' . esc_html( $mapbox_key_active_state['api_message'] ) . '</em>';
579+
}
580+
}
446581
}
447582
}
448583
?>
@@ -470,7 +605,7 @@ public static function metabox_for_admin() {
470605
<tr>
471606
<td>
472607
<p id="reachable_source" class="<?php echo esc_attr( $status_class ) ?>">
473-
<?php echo esc_html( $message ); ?>
608+
<?php echo wp_kses_post( $message ); ?>
474609
</p>
475610
</td>
476611
</tr>

0 commit comments

Comments
 (0)