Changeset 2942806 for wpide/trunk/freemius/includes/class-fs-api.php
- Timestamp:
- 07/25/2023 01:33:16 AM (22 months ago)
- File:
- 1 edited
- wpide/trunk/freemius/includes/class-fs-api.php (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
wpide/trunk/freemius/includes/class-fs-api.php
r2830392 r2942806 190 190 * @param string $method 191 191 * @param array $params 192 * @param bool $ retry Is in retry or first call attempt.192 * @param bool $in_retry Is in retry or first call attempt. 193 193 * 194 194 * @return array|mixed|string|void 195 195 */ 196 private function _call( $path, $method = 'GET', $params = array(), $ retry = false ) {196 private function _call( $path, $method = 'GET', $params = array(), $in_retry = false ) { 197 197 $this->_logger->entrance( $method . ':' . $path ); 198 199 $force_http = ( ! $in_retry && self::$_options->get_option( 'api_force_http', false ) ); 198 200 199 201 if ( self::is_temporary_down() ) { … … 225 227 $result = $this->_api->Api( $path, $method, $params ); 226 228 227 if ( null !== $result && 228 isset( $result->error ) && 229 isset( $result->error->code ) && 230 'request_expired' === $result->error->code 229 if ( 230 ! $in_retry && 231 null !== $result && 232 isset( $result->error ) && 233 isset( $result->error->code ) 231 234 ) { 232 if ( ! $retry ) { 235 $retry = false; 236 237 if ( 'request_expired' === $result->error->code ) { 233 238 $diff = isset( $result->error->timestamp ) ? 234 239 ( time() - strtotime( $result->error->timestamp ) ) : … … 238 243 if ( false !== $this->_sync_clock_diff( $diff ) ) { 239 244 // Retry call with new synced clock. 240 return $this->_call( $path, $method, $params, true );245 $retry = true; 241 246 } 247 } else if ( 248 Freemius_Api_WordPress::IsHttps() && 249 FS_Api::is_ssl_error_response( $result ) 250 ) { 251 $force_http = true; 252 $retry = true; 253 } 254 255 if ( $retry ) { 256 if ( $force_http ) { 257 $this->toggle_force_http( true ); 258 } 259 260 $result = $this->_call( $path, $method, $params, true ); 242 261 } 243 262 } 244 263 } 245 264 246 if ( $this->_logger->is_on() && self::is_api_error( $result ) ) { 247 // Log API errors. 248 $this->_logger->api_error( $result ); 265 if ( self::is_api_error( $result ) ) { 266 if ( $this->_logger->is_on() ) { 267 // Log API errors. 268 $this->_logger->api_error( $result ); 269 } 270 271 if ( $force_http ) { 272 $this->toggle_force_http( false ); 273 } 249 274 } 250 275 … … 338 363 } 339 364 365 /** 366 * @todo Remove this method after migrating Freemius::safe_remote_post() to FS_Api::call(). 367 * 368 * @author Leo Fajardo (@leorw) 369 * @since 2.5.4 370 * 371 * @param string $url 372 * @param array $remote_args 373 * 374 * @return array|WP_Error The response array or a WP_Error on failure. 375 */ 376 static function remote_request( $url, $remote_args ) { 377 if ( ! class_exists( 'Freemius_Api_WordPress' ) ) { 378 require_once WP_FS__DIR_SDK . '/FreemiusWordPress.php'; 379 } 380 381 if ( method_exists( 'Freemius_Api_WordPress', 'RemoteRequest' ) ) { 382 return Freemius_Api_WordPress::RemoteRequest( $url, $remote_args ); 383 } 384 385 // The following is for backward compatibility when a modified PHP SDK version is in use and the `Freemius_Api_WordPress:RemoteRequest()` method doesn't exist. 386 $response = wp_remote_request( $url, $remote_args ); 387 388 if ( 389 is_array( $response ) && 390 ( 391 empty( $response['headers'] ) || 392 empty( $response['headers']['x-api-server'] ) 393 ) 394 ) { 395 // API is considered blocked if the response doesn't include the `x-api-server` header. When there's no error but this header doesn't exist, the response is usually not in the expected form (e.g., cannot be JSON-decoded). 396 $response = new WP_Error( 'api_blocked', htmlentities( $response['body'] ) ); 397 } 398 399 return $response; 400 } 401 340 402 /** 341 403 * Check if there's a cached version of the API request. … … 408 470 } 409 471 410 /** 411 * Test API connectivity. 412 * 413 * @author Vova Feldman (@svovaf) 414 * @since 1.0.9 If fails, try to fallback to HTTP. 415 * @since 1.1.6 Added a 5-min caching mechanism, to prevent from overloading the server if the API if 416 * temporary down. 417 * 418 * @return bool True if successful connectivity to the API. 419 */ 420 static function test() { 421 self::_init(); 422 423 $cache_key = 'ping_test'; 424 425 $test = self::$_cache->get_valid( $cache_key, null ); 426 427 if ( is_null( $test ) ) { 428 $test = Freemius_Api_WordPress::Test(); 429 430 if ( false === $test && Freemius_Api_WordPress::IsHttps() ) { 431 // Fallback to HTTP, since HTTPS fails. 432 Freemius_Api_WordPress::SetHttp(); 433 434 self::$_options->set_option( 'api_force_http', true, true ); 435 436 $test = Freemius_Api_WordPress::Test(); 437 438 if ( false === $test ) { 439 /** 440 * API connectivity test fail also in HTTP request, therefore, 441 * fallback to HTTPS to keep connection secure. 442 * 443 * @since 1.1.6 444 */ 445 self::$_options->set_option( 'api_force_http', false, true ); 446 } 447 } 448 449 self::$_cache->set( $cache_key, $test, WP_FS__TIME_5_MIN_IN_SEC ); 450 } 451 452 return $test; 453 } 472 /** 473 * @author Leo Fajardo (@leorw) 474 * @since 2.5.4 475 * 476 * @param bool $is_http 477 */ 478 private function toggle_force_http( $is_http ) { 479 self::$_options->set_option( 'api_force_http', $is_http, true ); 480 481 if ( $is_http ) { 482 Freemius_Api_WordPress::SetHttp(); 483 } else if ( method_exists( 'Freemius_Api_WordPress', 'SetHttps' ) ) { 484 Freemius_Api_WordPress::SetHttps(); 485 } 486 } 487 488 /** 489 * @author Leo Fajardo (@leorw) 490 * @since 2.5.4 491 * 492 * @param mixed $response 493 * 494 * @return bool 495 */ 496 static function is_blocked( $response ) { 497 return ( 498 self::is_api_error_object( $response, true ) && 499 isset( $response->error->code ) && 500 'api_blocked' === $response->error->code 501 ); 502 } 454 503 455 504 /** … … 484 533 ) 485 534 ); 486 }487 488 /**489 * Ping API for connectivity test, and return result object.490 *491 * @author Vova Feldman (@svovaf)492 * @since 1.0.9493 *494 * @param null|string $unique_anonymous_id495 * @param array $params496 *497 * @return object498 */499 function ping( $unique_anonymous_id = null, $params = array() ) {500 $this->_logger->entrance();501 502 if ( self::is_temporary_down() ) {503 return $this->get_temporary_unavailable_error();504 }505 506 $pong = is_null( $unique_anonymous_id ) ?507 Freemius_Api_WordPress::Ping() :508 $this->_call( 'ping.json?' . http_build_query( array_merge(509 array( 'uid' => $unique_anonymous_id ),510 $params511 ) ) );512 513 if ( $this->is_valid_ping( $pong ) ) {514 return $pong;515 }516 517 if ( self::should_try_with_http( $pong ) ) {518 // Fallback to HTTP, since HTTPS fails.519 Freemius_Api_WordPress::SetHttp();520 521 self::$_options->set_option( 'api_force_http', true, true );522 523 $pong = is_null( $unique_anonymous_id ) ?524 Freemius_Api_WordPress::Ping() :525 $this->_call( 'ping.json?' . http_build_query( array_merge(526 array( 'uid' => $unique_anonymous_id ),527 $params528 ) ) );529 530 if ( ! $this->is_valid_ping( $pong ) ) {531 self::$_options->set_option( 'api_force_http', false, true );532 }533 }534 535 return $pong;536 535 } 537 536 … … 565 564 } 566 565 567 /**568 * Check if valid ping request result.569 *570 * @author Vova Feldman (@svovaf)571 * @since 1.1.1572 *573 * @param mixed $pong574 *575 * @return bool576 */577 function is_valid_ping( $pong ) {578 return Freemius_Api_WordPress::Test( $pong );579 }580 581 566 function get_url( $path = '' ) { 582 567 return Freemius_Api_WordPress::GetUrl( $path, $this->_api->IsSandbox() ); … … 595 580 self::$_cache->clear(); 596 581 } 582 583 /** 584 * @author Leo Fajardo (@leorw) 585 * @since 2.5.4 586 */ 587 static function clear_force_http_flag() { 588 self::$_options->unset_option( 'api_force_http' ); 589 } 597 590 598 591 #---------------------------------------------------------------------------------- … … 618 611 * 619 612 * @param mixed $result 613 * @param bool $ignore_message 620 614 * 621 615 * @return bool Is API result contains an error. 622 616 */ 623 static function is_api_error_object( $result ) {617 static function is_api_error_object( $result, $ignore_message = false ) { 624 618 return ( 625 619 is_object( $result ) && 626 620 isset( $result->error ) && 627 isset( $result->error->message ) 621 ( $ignore_message || isset( $result->error->message ) ) 622 ); 623 } 624 625 /** 626 * @author Leo Fajardo (@leorw) 627 * @since 2.5.4 628 * 629 * @param WP_Error|object|string $response 630 * 631 * @return bool 632 */ 633 static function is_ssl_error_response( $response ) { 634 $http_error = null; 635 636 if ( $response instanceof WP_Error ) { 637 if ( 638 isset( $response->errors ) && 639 isset( $response->errors['http_request_failed'] ) 640 ) { 641 $http_error = strtolower( $response->errors['http_request_failed'][0] ); 642 } 643 } else if ( 644 self::is_api_error_object( $response ) && 645 ! empty( $response->error->message ) 646 ) { 647 $http_error = $response->error->message; 648 } 649 650 return ( 651 ! empty( $http_error ) && 652 ( 653 false !== strpos( $http_error, 'curl error 35' ) || 654 ( 655 false === strpos( $http_error, '</html>' ) && 656 false !== strpos( $http_error, 'ssl' ) 657 ) 658 ) 628 659 ); 629 660 }
Note: See TracChangeset for help on using the changeset viewer.